void CsvFile::write(const HeaderList& header, const DataMap& data) throw (FileException) { std::ofstream file(filename.c_str()); if (!file) throw FileException("Cannot open file", filename, __FUNCTION_NAME__); // Print raw of headers for (HeaderList::const_iterator it = header.begin(); it != header.end(); ++it) { file << separator << *it; } // End of line file << std::endl; // Print all data raws for (DataMap::const_iterator rawit = data.begin() ; rawit != data.end(); ++rawit) { file<< rawit->first; for (DataRaw::const_iterator it = rawit->second.begin(); it != rawit->second.end(); ++it) { if (*it > 0) file << separator << *it; else file << separator; } // End of line file << std::endl; } };
void CHttpServer::call_ruby_proc( rho::String const &query, String const &body ) { unsigned long valProc = 0; convertFromStringA( query.c_str(), valProc ); HeaderList headers; headers.addElement(HttpHeader("Content-Type","application/x-www-form-urlencoded")); VALUE req = create_request_hash("", "", "", "", "POST", "", String(), headers, body); addHashToHash(req,"proc",valProc); VALUE data = callFramework(req); String strReply = String(getStringFromValue(data), getStringLenFromValue(data)); rho_ruby_releaseValue(data); send_response(strReply); }
unsigned int khrn_hw_addr(const void *addr) { ghw_error_e result; #ifdef FILE_DUMP fprintf(fp_dump, "khrn_hwaddr %x\n", addr); #endif u32 phys; unsigned int virt = (unsigned int) addr; HeaderNode* head = mem_list.getHead(); while (head != NULL) { MemHeader* header = head->get(); unsigned int va = (unsigned int)header->getVirt(); if ( (va <= virt) && (virt <= va + header->getSize()) ) { unsigned int out = header->getPhys() + (virt-va); if (out == 0) printf("input of %p out of ZERO!\n", addr); return out; } head = head->getNext(); } result = mem_allocator->virt2phys(phys, (void*)virt); if (result != GHW_ERROR_NONE) { result = mem_allocator1->virt2phys(phys, (void*)virt); } if (phys == 0) printf("input of %p out of ZERO!\n", addr); return phys; }
void *khrn_hw_unaddr(uint32_t addr) { ghw_error_e result; #ifdef FILE_DUMP fprintf(fp_dump, "khrn_hw_unaddr %x\n", addr); #endif void* virt; unsigned int phys = (unsigned int) addr; HeaderNode* head = mem_list.getHead(); while (head != NULL) { MemHeader* header = head->get(); unsigned int pa = (unsigned int)header->getPhys(); if ( (pa <= phys) && (phys <= pa + header->getSize()) ) { return ((unsigned char*)header->getVirt()) + (phys-pa); } head = head->getNext(); } result = mem_allocator->phys2virt(phys, (void*&)virt); if (result != GHW_ERROR_NONE) { mem_allocator1->phys2virt(phys, (void*&)virt); } return virt; }
bool CHttpServer::call_ruby_method(String const &uri, String const &body, String& strReply) { Route route; if (!dispatch(uri, route)) return false; HeaderList headers; headers.addElement(HttpHeader("Content-Type","application/x-www-form-urlencoded")); VALUE req = create_request_hash(route.application, route.model, route.action, route.id, "POST", uri, String(), headers, body); VALUE data = callFramework(req); strReply = String(getStringFromValue(data), getStringLenFromValue(data)); rho_ruby_releaseValue(data); return true; }
virtual ~MemHeader() { if(mNode) mem_list.removeNode(mNode); mSize = 0; mAlign =0; mFlags =MEM_FLAG_NONE; mTerm = NULL; mHandle = NULL; ref_count =0; retain_count=0; lock_count =0; mNode = NULL; }
void *mem_alloc_legacy_ex(MEM_FLAG_T flags) { #ifdef FILE_DUMP fprintf(fp_dump, "mem_alloc_legacy_ex %x\n", flags); #endif GhwMemHandle *handle; MemHeader *header = NULL; handle = mem_allocator->alloc(LEGACY_BLOCK_SIZE, 12); header = new MemHeader(handle,LEGACY_BLOCK_SIZE,12,flags); header->setNode(mem_list.addElement(header,0)); return header->getVirt(); }
MEM_HANDLE_T mem_wrap(void *p, uint32_t phys,uint32_t size, uint32_t align, MEM_FLAG_T flags, const char *desc) { #ifdef FILE_DUMP fprintf(fp_dump, "mem_wrap %x %x %x %x %x %x\n", p, phys, size, align, flags, desc); #endif GhwMemHandle* handle; MemHeader* header; if((p == NULL) || (phys == NULL)) { return MEM_HANDLE_INVALID; } handle = (GhwMemHandle*) new GhwMemHandleWrap(size, phys, p); header = new MemHeader(handle,size,align,flags); header->setNode(mem_list.addElement(header, 0)); return (void*)header; }
void mem_free_legacy(void *ptr) { #ifdef FILE_DUMP fprintf(fp_dump, "mem_free_legacy %x\n", ptr); #endif u32 phys; unsigned int virt = (unsigned int) ptr; HeaderNode* head = mem_list.getHead(); while (head != NULL) { MemHeader* header = head->get(); unsigned int va = (unsigned int)header->getVirt(); if ( (va <= virt) && (virt <= va + header->getSize()) ) { header->release(); break; } head = head->getNext(); } }
bool CHttpServer::parse_request(String &method, String &uri, String &query, HeaderList &headers, String &body ) { method.clear(); uri.clear(); headers.clear(); body.clear(); size_t s = 0; ByteVector request; bool parsing_headers = true; size_t content_length = 0; for (;;) { if (!receive_request(request)) return false; size_t lim = request.size(); while (parsing_headers) { size_t e; for(e = s; e < lim && request[e] != '\r'; ++e); if (e >= lim - 1) { // Incomplete line, will read further break; } if (request[e + 1] != '\n') { if (verbose) RAWLOG_ERROR("Wrong request syntax, line should ends by '\\r\\n'"); return false; } String line(&request[s], e - s); s = e + 2; if (line.empty()) { parsing_headers = false; break; } if (uri.empty()) { // Parse start line if (!parse_startline(line, method, uri, query) || uri.empty()) return false; } else { Header hdr; if (!parse_header(line, hdr) || hdr.name.empty()) return false; headers.push_back(hdr); String low; std::transform(hdr.name.begin(), hdr.name.end(), std::back_inserter(low), &::tolower); if (low == "content-length") { content_length = ::atoi(hdr.value.c_str()); } } } if (!parsing_headers) { if (content_length == 0) return true; if (lim - s < content_length) continue; body.assign(&request[s], &request[s] + content_length); return true; } } }
bool CHttpServer::receive_request(ByteVector &request) { if (verbose) RAWTRACE("Receiving request..."); ByteVector r; char buf[BUF_SIZE]; int attempts = 0; for(;;) { if (verbose) RAWTRACE("Read portion of data from socket..."); int n = recv(m_sock, &buf[0], sizeof(buf), 0); //RAWTRACE1("RECV: %d", n); if (n == -1) { int e = RHO_NET_ERROR_CODE; if (verbose) RAWTRACE1("RECV ERROR: %d", e); #if !defined(WINDOWS_PLATFORM) if (e == EINTR) continue; #else if (e == WSAEINTR) continue; #endif #if defined(OS_WP8) || (defined(RHODES_QT_PLATFORM) && defined(OS_WINDOWS_DESKTOP)) || defined(OS_WINCE) if (e == EAGAIN || e == WSAEWOULDBLOCK) { #else if (e == EAGAIN) { #endif if (!r.empty()) break; if(++attempts > (HTTP_EAGAIN_TIMEOUT*10)) { if (verbose) RAWLOG_ERROR("Error when receiving data from socket. Client does not send data for " HTTP_EAGAIN_TIMEOUT_STR " sec. Cancel recieve."); return false; } fd_set fds; FD_ZERO(&fds); FD_SET(m_sock, &fds); timeval tv = {0}; tv.tv_usec = 100000;//100 MS select(m_sock + 1, &fds, 0, 0, &tv); continue; } if (verbose) RAWLOG_ERROR1("Error when receiving data from socket: %d", e); return false; } if (n == 0) { if(!r.empty()) { if (verbose) RAWTRACE("Client closed connection gracefully"); break; } else { if (verbose) RAWLOG_ERROR("Connection gracefully closed before we receive any data"); return false; } } else { if (verbose) RAWTRACE1("Actually read %d bytes", n); r.insert(r.end(), &buf[0], &buf[0] + n); } } if (!r.empty()) { request.insert(request.end(), r.begin(), r.end()); if ( !rho_conf_getBool("log_skip_post") ) { String strRequest(request.begin(),request.end()); if (verbose) RAWTRACE1("Received request:\n%s", strRequest.c_str()); } } return true; } bool CHttpServer::send_response_impl(String const &data, bool continuation) { #ifdef OS_MACOSX if ( m_localResponseWriter != 0 ) { m_localResponseWriter->writeResponse( data ); return true; } #endif if (verbose) { if (continuation) if (verbose) RAWTRACE("Send continuation data..."); else if (verbose) RAWTRACE("Sending response..."); } // First of all, make socket blocking #if defined(WINDOWS_PLATFORM) unsigned long optval = 0; if(::ioctlsocket(m_sock, FIONBIO, &optval) == SOCKET_ERROR) { RAWLOG_ERROR1("Can not set blocking socket mode: %d", RHO_NET_ERROR_CODE); return false; } #else int flags = fcntl(m_sock, F_GETFL); if (flags == -1) { if (verbose) RAWLOG_ERROR1("Can not get current socket mode: %d", errno); return false; } if (fcntl(m_sock, F_SETFL, flags & ~O_NONBLOCK) == -1) { if (verbose) RAWLOG_ERROR1("Can not set blocking socket mode: %d", errno); return false; } #endif size_t pos = 0; for(; pos < data.size();) { int n = send(m_sock, data.c_str() + pos, data.size() - pos, 0); if (n == -1) { int e = RHO_NET_ERROR_CODE; #if !defined(WINDOWS_PLATFORM) if (e == EINTR) continue; #endif if (verbose) RAWLOG_ERROR1("Can not send response data: %d", e); return false; } if (n == 0) break; pos += n; } //String dbg_response = response.size() > 100 ? response.substr(0, 100) : response; //RAWTRACE2("Sent response:\n%s%s", dbg_response.c_str(), response.size() > 100 ? "..." : " "); if (continuation) { if (verbose) RAWTRACE1("Sent response body: %d bytes", data.size()); } else if ( !rho_conf_getBool("log_skip_post") ) { if (verbose) RAWTRACE1("Sent response (only headers displayed):\n%s", data.c_str()); } return true; } bool CHttpServer::send_response(String const &response, bool redirect) { #ifdef OS_ANDROID if (redirect) { CAutoPtr<IRhoThreadImpl> ptrThread = rho_get_RhoClassFactory()->createThreadImpl(); ptrThread->sleep(20); } #endif return send_response_impl(response, false); } String CHttpServer::create_response(String const &reason) { return create_response(reason, ""); } String CHttpServer::create_response(String const &reason, HeaderList const &headers) { return create_response(reason, headers, ""); } String CHttpServer::create_response(String const &reason, String const &body) { return create_response(reason, HeaderList(), body); } String CHttpServer::create_response(String const &reason, HeaderList const &hdrs, String const &body) { String response = "HTTP/1.1 "; response += reason; response += "\r\n"; char buf[50]; snprintf(buf, sizeof(buf), "%d", m_port); HeaderList headers; headers.push_back(Header("Host", String("127.0.0.1:") + buf)); headers.push_back(Header("Connection", "close")); headers.push_back(HttpHeader("Access-Control-Allow-Origin", "*")); std::copy(hdrs.begin(), hdrs.end(), std::back_inserter(headers)); for(HeaderList::const_iterator it = headers.begin(), lim = headers.end(); it != lim; ++it) { response += it->name; response += ": "; response += it->value; response += "\r\n"; } response += "\r\n"; response += body; return response; }
bool CHttpServer::decide(String const &method, String const &arg_uri, String const &query, HeaderList const &headers, String const &body/*, IResponseSender& respSender*/ ) { if (verbose) RAWTRACE1("Decide what to do with uri %s", arg_uri.c_str()); callback_t callback = registered(arg_uri); if (callback) { if (verbose) RAWTRACE1("Uri %s is registered callback, so handle it appropriately", arg_uri.c_str()); if ( callback == rho_http_ruby_proc_callback ) call_ruby_proc( query, body ); else callback(this, query.length() ? query : body); return false; } String uri = arg_uri; String fullPath = CFilePath::join(m_root, uri); #ifndef RHO_NO_RUBY_API if (rho_ruby_is_started()) { Route route; if (dispatch(uri, route)) { if (verbose) RAWTRACE1("Uri %s is correct route, so enable MVC logic", uri.c_str()); VALUE req = create_request_hash(route.application, route.model, route.action, route.id, method, uri, query, headers, body); VALUE data = callFramework(req); String reply(getStringFromValue(data), getStringLenFromValue(data)); rho_ruby_releaseValue(data); bool isRedirect = String_startsWith(reply, "HTTP/1.1 301") || String_startsWith(reply, "HTTP/1.1 302"); if (!send_response(reply, isRedirect)) return false; if (method == "GET") rho_rhodesapp_keeplastvisitedurl(uri.c_str()); if ( sync::RhoconnectClientManager::haveRhoconnectClientImpl() ) { if (!route.id.empty()) { sync::RhoconnectClientManager::rho_sync_addobjectnotify_bysrcname(route.model.c_str(), route.id.c_str()); } } return true; } if (isdir(fullPath)) { if (verbose) RAWTRACE1("Uri %s is directory, redirecting to index", uri.c_str()); String q = query.empty() ? "" : "?" + query; HeaderList headers; headers.push_back(Header("Location", CFilePath::join( uri, "index" RHO_ERB_EXT) + q)); send_response(create_response("301 Moved Permanently", headers), true); return false; } if (isindex(uri)) { if (!isfile(fullPath)) { if (verbose) RAWLOG_ERROR1("The file %s was not found", fullPath.c_str()); String error = "<!DOCTYPE html><html><font size=\"+4\"><h2>404 Not Found.</h2> The file " + uri + " was not found.</font></html>"; send_response(create_response("404 Not Found",error)); return false; } if (verbose) RAWTRACE1("Uri %s is index file, call serveIndex", uri.c_str()); VALUE req = create_request_hash(route.application, route.model, route.action, route.id, method, uri, query, headers, body); VALUE data = callServeIndex((char *)fullPath.c_str(), req); String reply(getStringFromValue(data), getStringLenFromValue(data)); rho_ruby_releaseValue(data); if (!send_response(reply)) return false; if (method == "GET") rho_rhodesapp_keeplastvisitedurl(uri.c_str()); return true; } } #endif // Try to send requested file if (verbose) RAWTRACE1("Uri %s should be regular file, trying to send it", uri.c_str()); PROF_START("READ_FILE"); bool bRes = send_file(uri, headers); PROF_STOP("READ_FILE"); return bRes; }
bool CHttpServer::send_file(String const &path, HeaderList const &hdrs) { String fullPath = CFilePath::normalizePath(path); if (String_startsWith(fullPath,"/app/db/db-files") ) fullPath = CFilePath::join( rho_native_rhodbpath(), path.substr(4) ); else if (fullPath.find(m_root) != 0 && fullPath.find(m_strRhoRoot) != 0 && fullPath.find(m_strRuntimeRoot) != 0 && fullPath.find(m_userroot) != 0 && fullPath.find(m_strRhoUserRoot) != 0) fullPath = CFilePath::join( m_root, path ); struct stat st; bool bCheckExist = true; #ifdef RHODES_EMULATOR String strPlatform = RHOSIMCONF().getString("platform"); if ( strPlatform.length() > 0 ) { String fullPath1 = fullPath; int nDot = fullPath1.rfind('.'); if ( nDot >= 0 ) fullPath1.insert(nDot, String(".") + strPlatform); else fullPath1 += String(".") + strPlatform; if (stat(fullPath1.c_str(), &st) == 0 && S_ISREG(st.st_mode)) { fullPath = fullPath1; bCheckExist = false; } } #endif bool doesNotExists = bCheckExist && (stat(fullPath.c_str(), &st) != 0 || !S_ISREG(st.st_mode)); if ( doesNotExists ) { // looking for files at 'rho/apps' at runtime folder fullPath = CFilePath::join( m_strRuntimeRoot, path ); } if (verbose) RAWTRACE1("Sending file %s...", fullPath.c_str()); if ( doesNotExists ) { if ( stat(fullPath.c_str(), &st) != 0 || !S_ISREG(st.st_mode) ) { doesNotExists = true; }else doesNotExists = false; } #ifdef RHODES_EMULATOR if ( doesNotExists ) { CTokenizer oTokenizer( RHOSIMCONF().getString("ext_path"), ";" ); while (oTokenizer.hasMoreTokens()) { String tok = oTokenizer.nextToken(); tok = String_trim(tok); String fullPath1 = CFilePath::join( tok, path ); if (stat(fullPath1.c_str(), &st) == 0 && S_ISREG(st.st_mode)) { fullPath = fullPath1; doesNotExists = false; break; } } } #endif if ( doesNotExists ) { if (verbose) RAWLOG_ERROR1("The file %s was not found", path.c_str()); String error = "<!DOCTYPE html><html><font size=\"+4\"><h2>404 Not Found.</h2> The file " + path + " was not found.</font></html>"; send_response(create_response("404 Not Found",error)); return false; } PROF_START("LOW_FILE"); FILE *fp = fopen(fullPath.c_str(), "rb"); PROF_STOP("LOW_FILE"); if (!fp) { if (verbose) RAWLOG_ERROR1("The file %s could not be opened", path.c_str()); String error = "<!DOCTYPE html><html><font size=\"+4\"><h2>404 Not Found.</h2> The file " + path + " could not be opened.</font></html"; send_response(create_response("404 Not Found",error)); return false; } HeaderList headers; // Detect mime type headers.push_back(Header("Content-Type", get_mime_type(path))); if ( String_startsWith(path, "/public") ) { headers.push_back(Header("Expires", "Thu, 15 Apr 2020 20:00:00 GMT") ); headers.push_back(Header("Cache-Control", "max-age=2592000") ); } // Content length char* buf = new char[FILE_BUF_SIZE]; String start_line; size_t file_size = st.st_size; size_t range_begin = 0, range_end = file_size - 1; size_t content_size = file_size; if (parse_range(hdrs, &range_begin, &range_end)) { if (range_end >= file_size) range_end = file_size - 1; if (range_begin >= range_end) range_begin = range_end - 1; content_size = range_end - range_begin + 1; if (fseek(fp, range_begin, SEEK_SET) == -1) { RAWLOG_ERROR1("Can not seek to specified range start: %lu", (unsigned long)range_begin); snprintf(buf, FILE_BUF_SIZE, "bytes */%lu", (unsigned long)file_size); headers.push_back(Header("Content-Range", buf)); send_response(create_response("416 Request Range Not Satisfiable",headers)); fclose(fp); delete[] buf; return false; } snprintf(buf, FILE_BUF_SIZE, "bytes %lu-%lu/%lu", (unsigned long)range_begin, (unsigned long)range_end, (unsigned long)file_size); headers.push_back(Header("Content-Range", buf)); start_line = "206 Partial Content"; } else { start_line = "200 OK"; } snprintf(buf, FILE_BUF_SIZE, "%lu", (unsigned long)content_size); headers.push_back(Header("Content-Length", buf)); // Send headers if (!send_response(create_response(start_line, headers))) { if (verbose) RAWLOG_ERROR1("Can not send headers while sending file %s", path.c_str()); fclose(fp); delete[] buf; return false; } // Send body for (size_t start = range_begin; start < range_end + 1;) { size_t need_to_read = range_end - start + 1; if (need_to_read == 0) break; if (need_to_read > FILE_BUF_SIZE) need_to_read = FILE_BUF_SIZE; PROF_START("LOW_FILE"); size_t n = fread(buf, 1, need_to_read, fp);//fread(buf, 1, need_to_read, fp); PROF_STOP("LOW_FILE"); if (n < need_to_read) { if (ferror(fp) ) { if (verbose) RAWLOG_ERROR2("Can not read part of file (at position %lu): %s", (unsigned long)start, strerror(errno)); } else if ( feof(fp) ) { if (verbose) RAWLOG_ERROR1("End of file reached, but we expect data (%lu bytes)", (unsigned long)need_to_read); } fclose(fp); delete[] buf; return false; } start += n; if (!send_response_body(String(buf, n))) { if (verbose) RAWLOG_ERROR1("Can not send part of data while sending file %s", path.c_str()); fclose(fp); delete[] buf; return false; } } PROF_START("LOW_FILE"); fclose(fp); PROF_STOP("LOW_FILE"); delete[] buf; if (verbose) RAWTRACE1("File %s was sent successfully", path.c_str()); return false; }
void CsvFile::read(HeaderList& header, DataMap& data) const throw (FileException, CustomException) { std::ifstream file(filename.c_str()); if (!file) throw FileException("Cannot open file", filename, __FUNCTION_NAME__); // a buffer to store the line read std::string line; if ( ! std::getline(file, line)) throw FileException("Cannot get the first line of file", filename, __FUNCTION_NAME__); unsigned int pointer = 0; unsigned int rawnb = 0; std::string word =""; int localHostColNumber = -1, tmp=0; bool uselocalhost=false; bool useotherthanlocalhost=false; // Parse the first line (header line) while(pointer < line.size()) { while( pointer < line.size() && line[pointer] != separator) { //remove white spaces if (line[pointer] != ' ') { word.push_back(line[pointer]); } pointer++; } if( !word.empty()) { // warning if id already in if (std::find(header.begin(), header.end(), word) != header.end() ) { // Was error before, now just a warning: may be convenient to have several time the same name in a header Msg::warning("Duplicate header element '"+ word+"' in file "+filename, __FUNCTION_NAME__); // throw FileException("Duplicate header elements'"+ word+"'",filename, __FUNCTION_NAME__); } header.push_back(word); tmp++; } // if we have "localhost" in csv file, note the column number. if(word == "localhost" || word == "Localhost" || word == "127.0.0.1") localHostColNumber = tmp; pointer++; word.clear(); } // Parse the lines while (std::getline(file, line)) { rawnb++; pointer = 0; bool firstWord = true; // Are we parsing the first column unsigned int column = 0; // Which column is being scanned? std::string id; while(line.size() > pointer) { // get word word.clear(); while(line.size() > pointer && line[pointer] != separator) { if (line[pointer] != ' ') word.push_back(line[pointer]); pointer++; } pointer++; if (firstWord) { // it's the map id if ( word.empty() ) break; // forget about this line and go to parse next line id = word; if(data.find(id) != data.end()) throw CustomException("Component : " + id + " is specified twice in CSV file.", __FUNCTION_NAME__ ); // init the raw of this id with zeros. data[id].insert(data[id].begin(), header.size(),0); firstWord = false; } else { if (!word.empty()) { // store data try{ data[id].at(column) = convertTo<int>(word); if (data[id].at(column) > 0)// one component instance at least mapped { if(column == localHostColNumber-1) // we are reading in a locahost column { // Remember that we have one component mapped on a localHost. uselocalhost=true; } else { // Remember that we have one component mapped on an host different from localHost. useotherthanlocalhost=true; } if(uselocalhost && useotherthanlocalhost) throw FileException("Host name 'localhost' is used in CSV file in conjunction with other host names or IP address. Replace 'localhost' by IP address or machine name to avoid problems", filename, __FUNCTION_NAME__); } }//end try catch(const BadConversion& e) { throw FileException("Raw="+toString<unsigned int>(rawnb+1)+", col="+toString<unsigned int>(column+2)+") contains non integer value="+word,filename, __FUNCTION_NAME__); // std::cerr << "ERROR: Csv File "<<fileName<<", element (raw="<<rawnb+1<<", col="<<column+2<<") contains non integer value="<<word<< std::endl; } catch(const std::out_of_range& e) { throw FileException("Element (raw="+toString<unsigned int>(rawnb+1)+", col="+toString<unsigned int>(column+2)+") out of column (value="+word+", ignored)",filename, __FUNCTION_NAME__); // std::cerr << "WARNING : Csv File "<<fileName<<", element (raw="<<rawnb+1<<", col="<<column+2<<") out of column (value="<<word<<", ignored)"<< std::endl; } } column++; } } } };
bool CHttpServer::decide(String const &method, String const &arg_uri, String const &query, HeaderList const &headers, String const &body) { RAWTRACE1("Decide what to do with uri %s", arg_uri.c_str()); callback_t callback = registered(arg_uri); if (callback) { RAWTRACE1("Uri %s is registered callback, so handle it appropriately", arg_uri.c_str()); if ( callback == rho_http_ruby_proc_callback ) call_ruby_proc( query, body ); else callback(this, query.length() ? query : body); return false; } String uri = arg_uri; //#ifdef OS_ANDROID // //Work around malformed Android WebView URLs // if (!String_startsWith(uri, "/app") && // !String_startsWith(uri, "/public") && // !String_startsWith(uri, "/data")) // { // RAWTRACE1("Malformed URL: '%s', adding '/app' prefix.", uri.c_str()); // uri = CFilePath::join("/app", uri); // } //#endif String fullPath = CFilePath::join(m_root, uri); Route route; if (dispatch(uri, route)) { RAWTRACE1("Uri %s is correct route, so enable MVC logic", uri.c_str()); VALUE req = create_request_hash(route.application, route.model, route.action, route.id, method, uri, query, headers, body); VALUE data = callFramework(req); String reply(getStringFromValue(data), getStringLenFromValue(data)); rho_ruby_releaseValue(data); bool isRedirect = String_startsWith(reply, "HTTP/1.1 301") || String_startsWith(reply, "HTTP/1.1 302"); if (!send_response(reply, isRedirect)) return false; if (method == "GET") rho_rhodesapp_keeplastvisitedurl(uri.c_str()); if ( sync::RhoconnectClientManager::haveRhoconnectClientImpl() ) { if (!route.id.empty()) { sync::RhoconnectClientManager::rho_sync_addobjectnotify_bysrcname(route.model.c_str(), route.id.c_str()); } } return true; } //#ifndef OS_ANDROID if (isdir(fullPath)) { RAWTRACE1("Uri %s is directory, redirecting to index", uri.c_str()); String q = query.empty() ? "" : "?" + query; HeaderList headers; headers.push_back(Header("Location", CFilePath::join( uri, "index"RHO_ERB_EXT) + q)); send_response(create_response("301 Moved Permanently", headers), true); return false; } //#else // //Work around this Android redirect bug: // //http://code.google.com/p/android/issues/detail?can=2&q=11583&id=11583 // if (isdir(fullPath)) { // RAWTRACE1("Uri %s is directory, override with index", uri.c_str()); // return decide(method, CFilePath::join( uri, "index"RHO_ERB_EXT), query, headers, body); // } //#endif if (isindex(uri)) { if (!isfile(fullPath)) { RAWLOG_ERROR1("The file %s was not found", fullPath.c_str()); String error = "<html><font size=\"+4\"><h2>404 Not Found.</h2> The file " + uri + " was not found.</font></html>"; send_response(create_response("404 Not Found",error)); return false; } RAWTRACE1("Uri %s is index file, call serveIndex", uri.c_str()); VALUE req = create_request_hash(route.application, route.model, route.action, route.id, method, uri, query, headers, body); VALUE data = callServeIndex((char *)fullPath.c_str(), req); String reply(getStringFromValue(data), getStringLenFromValue(data)); rho_ruby_releaseValue(data); if (!send_response(reply)) return false; if (method == "GET") rho_rhodesapp_keeplastvisitedurl(uri.c_str()); return true; } // Try to send requested file RAWTRACE1("Uri %s should be regular file, trying to send it", uri.c_str()); return send_file(uri, headers); }
PyObject * PyPreprocessor_scanHeaders( PyPreprocessor * self, PyObject * args, PyObject * kwds ) { static char * kwlist[] = { "pp_ctx", "filename", NULL }; PyObject * pObject = 0; PyObject * filename = 0; assert( self->pp ); if ( !PyArg_ParseTupleAndKeywords( args, kwds, "OO", kwlist, &pObject, &filename ) ) return NULL; if ( !pObject || ( (PyTypeObject *)PyObject_Type( pObject ) != &PyPreprocessingContextType ) ) { PyErr_SetString( PyExc_Exception, "Invalid preprocessing context parameter." ); return NULL; } PyPreprocessingContext const * ppContext( reinterpret_cast<PyPreprocessingContext *>( pObject ) ); if ( filename && !PyUnicode_Check( filename ) ) { PyErr_SetString( PyExc_Exception, "Expected a string as 'filename' parameter." ); return NULL; } Headers headers; HeaderList missing; PyThreadState * _save; bool result; try { Py_UNBLOCK_THREADS result = self->pp->scanHeaders( *ppContext->ppContext, PyUnicode_AsUTF8( filename ), headers, missing ); } catch ( std::runtime_error const & error ) { Py_BLOCK_THREADS PyErr_SetString( PyExc_RuntimeError, error.what() ); return NULL; } catch ( std::exception const & error ) { Py_BLOCK_THREADS PyErr_SetString( PyExc_Exception, error.what() ); return NULL; } catch ( ... ) { Py_BLOCK_THREADS PyErr_SetString( PyExc_Exception, "Unhandled exception" ); return NULL; } if ( !result ) { Py_BLOCK_THREADS PyErr_SetString( PyExc_Exception, "Failed to preprocess file." ); return NULL; } // Group result by dir. typedef std::vector<Header const *> HeaderPtrList; typedef std::unordered_map<Dir, HeaderPtrList> DirsAndHeaders; DirsAndHeaders dirsAndHeaders; for ( Header const & header : headers ) dirsAndHeaders[ header.dir ].push_back( &header ); Py_BLOCK_THREADS PyObject * dirsTuple = PyTuple_New( dirsAndHeaders.size() ); std::size_t dirIndex( 0 ); for ( DirsAndHeaders::value_type const & dirAndHeaders : dirsAndHeaders ) { PyObject * headersInDirTuple = PyTuple_New( dirAndHeaders.second.size() ); std::size_t headersInDirTupleIndex( 0 ); for ( Header const * header : dirAndHeaders.second ) { PyObject * headerEntry = PyTuple_New( 3 ); PyTuple_SET_ITEM( headerEntry, 0, PyUnicode_FromStringAndSize( header->name.get().data(), header->name.get().size() ) ); PyObject * const isRelative( header->relative ? Py_True : Py_False ); Py_INCREF( isRelative ); PyTuple_SET_ITEM( headerEntry, 1, isRelative ); PyContentEntry * contentEntry( (PyContentEntry *)_PyObject_New( &PyContentEntryType ) ); contentEntry->ptr = header->contentEntry.get(); intrusive_ptr_add_ref( contentEntry->ptr ); PyTuple_SET_ITEM( headerEntry, 2, (PyObject *)contentEntry ); PyTuple_SET_ITEM( headersInDirTuple, headersInDirTupleIndex++, headerEntry ); } PyObject * dirTuple = PyTuple_New( 2 ); llvm::StringRef const dirStr( dirAndHeaders.first.get() ); PyObject * dir = PyUnicode_FromStringAndSize( dirStr.data(), dirStr.size() ); PyTuple_SET_ITEM( dirTuple, 0, dir ); PyTuple_SET_ITEM( dirTuple, 1, headersInDirTuple ); PyTuple_SET_ITEM( dirsTuple, dirIndex++, dirTuple ); } PyObject * missingHeadersTuple = PyTuple_New( missing.size() ); std::size_t missingIndex( 0 ); for ( HeaderList::value_type const & missingHeader : missing ) { PyObject * val = PyUnicode_FromStringAndSize( missingHeader.data(), missingHeader.size() ); PyTuple_SET_ITEM( missingHeadersTuple, missingIndex++, val ); } PyObject * resultTuple = PyTuple_New( 2 ); PyTuple_SET_ITEM( resultTuple, 0, dirsTuple ); PyTuple_SET_ITEM( resultTuple, 1, missingHeadersTuple ); return resultTuple; }
static ngx_int_t ngx_http_cxxmvc_handler(ngx_http_request_t *r) { using dragon::kHttp_Method_Get; using dragon::kResponseTypeRedirect; using dragon::HeaderList; using dragon::CookieList; using dragon::StringRef; using dragon::HttpRequest; using dragon::HttpResponse; ngx_buf_t *buf = NULL; ngx_chain_t out; unsigned uriLen = r->uri.len; if (r->args.len > 0) uriLen = r->uri.len + r->args.len + 1; struct sockaddr_in *sin; ngx_addr_t addr; addr.sockaddr = r->connection->sockaddr; addr.socklen = r->connection->socklen; sin = (struct sockaddr_in *)addr.sockaddr; char *ip = inet_ntoa(sin->sin_addr); StringRef IP(ip, strlen(ip)); StringRef routingUrl((const char *)r->uri.data, uriLen); StringRef userAgent; if (r->headers_in.user_agent) userAgent = StringRef((const char *)r->headers_in.user_agent->value.data, r->headers_in.user_agent->value.len); std::string userCookie = ngx_http_get_cookie(r); std::string lang = ngx_http_get_language(r); HttpRequest req; HttpResponse res; req.SetMethod(kHttp_Method_Get); req.SetUrl(routingUrl); req.SetIp(IP); //req.SetHost(StringRef(host, strlen(host))); req.SetUserAgent(userAgent); req.SetUserCookie(StringRef(userCookie.c_str(), userCookie.length())); req.SetAcceptLanguage(StringRef(lang.c_str(), lang.length())); req.ParseCookie(); DE.ResponseRequest(req, res); ngx_str_t k = ngx_string("X-Powered-By"); ngx_str_t v = ngx_string("cxxmvc/0.1");; ngx_http_add_header(r, &v, &k); if (res.GetResponseType() == kResponseTypeRedirect) { ngx_str_t k = ngx_string("location"); ngx_str_t v = {res.GetContent().length(), (u_char *)res.GetContent().c_str()}; ngx_http_add_header(r, &v, &k); } HeaderList headers = res.GetHeaders(); if (headers.size() > 0) { HeaderList::iterator iter; HeaderList::iterator end = headers.end(); for (iter = headers.begin(); iter != end; ++iter) { ngx_str_t k; ngx_str_t v; k.data = (u_char *)ngx_pcalloc(r->pool, iter->first.length()+1); k.len = iter->first.length(); strcpy((char *)k.data, (const char *)iter->first.c_str()); v.data = (u_char *)ngx_pcalloc(r->pool, iter->second.length()+1); v.len = iter->second.length(); strcpy((char *)v.data, (const char *)iter->second.c_str()); // std::cout << "key : "<< k.data << std::endl; // std::cout << "value : " << v.data << std::endl; ngx_http_add_header(r, &v, &k); } } CookieList cookies = res.GetCookies(); if (cookies.size() > 0) { CookieList::iterator iter; CookieList::iterator end = cookies.end(); for (iter = cookies.begin(); iter != end; ++iter) { ngx_str_t v; v.data = (u_char *)ngx_pcalloc(r->pool, iter->length()+1); v.len = iter->length(); strcpy((char *)v.data, (const char *)iter->c_str()); ngx_http_add_cookie(r, v); } } r->headers_out.status = res.GetStatusCode(); r->headers_out.content_type.len = res.GetContentType().length(); r->headers_out.content_type.data = (u_char *)res.GetContentType().c_str(); if (res.GetDetaRef().length() > 0) r->headers_out.content_length_n = res.GetDetaRef().length(); else r->headers_out.content_length_n = res.GetContent().length(); ngx_http_send_header(r); buf = (ngx_buf_t *)ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); if (buf == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Failed to allocate response buffer."); return NGX_ERROR; } if (res.GetDetaRef().length() > 0) { buf->pos = (u_char *)res.GetDetaRef().data(); buf->last = buf->pos + res.GetDetaRef().length(); } else { buf->pos = (u_char *)res.GetContent().c_str(); buf->last = buf->pos + res.GetContent().length(); } buf->memory = 1; /* content is in read-only memory */ buf->last_buf = 1; /* there will be no more buffers in the request */ out.buf = buf; out.next = NULL; return ngx_http_output_filter(r, &out); }