char *WebClient::executeWebMethod( char *inMethod, char *inURL, int *outContentLength, char **outFinalURL, char **outMimeType, long inTimeoutInMilliseconds ) { char *returnString = NULL; if (outFinalURL) *outFinalURL = NULL; char *startString = "http://"; char *urlCopy = strdup( inURL ); char *urlStart = stringLocateIgnoreCase( urlCopy, startString ); char *serverStart; if( urlStart == NULL ) { // no http:// at start of URL serverStart = urlCopy; } else { serverStart = &( urlStart[ strlen( startString ) ] ); } // find the first occurrence of "/", which is the end of the // server name char *serverNameCopy = strdup( serverStart ); char *serverEnd = strstr( serverNameCopy, "/" ); char *getPath = strstr( serverStart, "/" ); if( serverEnd == NULL ) { serverEnd = &( serverStart[ strlen( serverStart ) ] ); getPath = "/"; } // terminate the url here to extract the server name serverEnd[0] = '\0'; int portNumber = 80; // look for a port number char *colon = strstr( serverNameCopy, ":" ); if( colon != NULL ) { char *portNumberString = &( colon[1] ); int numRead = sscanf( portNumberString, "%d", & portNumber ); if( numRead != 1 ) { portNumber = 80; } // terminate the name here so port isn't taken as part // of the address colon[0] = '\0'; } HostAddress *host = new HostAddress( strdup( serverNameCopy ), portNumber ); // will be set to true if we time out while connecting char timedOut; Socket *sock = SocketClient::connectToServer( host, inTimeoutInMilliseconds, &timedOut ); char *finalURL = strdup( inURL ); char *mimeType = NULL; int receivedLength = 0; if( sock != NULL ) { SocketStream *stream = new SocketStream( sock ); // reuse the same timeout for read operations stream->setReadTimeout( inTimeoutInMilliseconds ); // method and trailing space need to be sent in the same // buffer to work around a bug in certain web servers char *methodWithSpace = new char[ strlen( inMethod ) + 2 ]; sprintf( methodWithSpace, "%s ", inMethod ); // send the request stream->writeString( methodWithSpace ); stream->writeString( getPath ); stream->writeString( " HTTP/1.0\r\n" ); stream->writeString( "Host: " ); stream->writeString( serverNameCopy ); stream->writeString( "\r\n\r\n" ); delete [] methodWithSpace; // the simplest thing to do is to read upto the // socket close first, then extract the content char *received = receiveData( stream, &receivedLength ); char *content = NULL; char notFound = false; if( stringLocateIgnoreCase ( received, "404 Not Found" ) != NULL ) { notFound = true; } // watch for redirection headers if( stringLocateIgnoreCase( received, "302 Found" ) != NULL || stringLocateIgnoreCase( received, "301 Moved Permanently" ) != NULL || stringLocateIgnoreCase( received, "302 Object Moved" ) != NULL ) { // call ourself recursively to fetch the redirection char *locationTag = "Location: "; char *locationTagStart = stringLocateIgnoreCase( received, locationTag ); if( locationTagStart != NULL ) { char *locationStart = &( locationTagStart[ strlen( locationTag ) ] ); // replace next \r with \0 char *nextChar = locationStart; while( nextChar[0] != '\r' && nextChar[0] != '\0' ) { nextChar = &( nextChar[1] ); } nextChar[0] = '\0'; char *newFinalURL=NULL; if (strcmp(inURL,locationStart)) content = getWebPage( locationStart, &receivedLength, &newFinalURL, &mimeType ); delete [] locationTagStart; delete [] finalURL; finalURL = newFinalURL; if( content == NULL ) { // not found recursively notFound = true; } } } char *contentStartString = "\r\n\r\n"; char *contentTypeStartString = "Content-type:"; if( notFound ) { returnString = NULL; } else { if( content == NULL ) { // scan for content type char *contentTypeStartMarker = stringLocateIgnoreCase( received, contentTypeStartString ); if( contentTypeStartMarker != NULL ) { // skip marker char *contentTypeStart = &( contentTypeStartMarker[ strlen( contentTypeStartString ) ] ); // extract content type // make sure the buffer is big enough char *contentType = new char[ strlen( contentTypeStartMarker ) ]; int numRead = sscanf( contentTypeStart, "%s", contentType ); if( numRead == 1 ) { // trim mimeType = strdup( contentType ); } delete [] contentType; delete [] contentTypeStartMarker; } // extract the content from what we've received char *contentStart = strstr( received, contentStartString ); if( contentStart != NULL ) { content = &( contentStart[ strlen( contentStartString ) ] ); receivedLength = receivedLength - strlen( contentStartString ) - ( (long)(contentStart - received) ); returnString = new char[ receivedLength + 1 ]; returnString = (char*)memcpy( returnString, content, receivedLength ); returnString[ receivedLength ] = '\0'; } } else { // we already obtained our content recursively returnString = new char[ receivedLength + 1 ]; returnString = (char*)memcpy( returnString, content, receivedLength ); returnString[ receivedLength ] = '\0'; delete [] content; } } delete [] received; delete stream; delete sock; } delete host ; free ( serverNameCopy ) ; free ( urlCopy ) ; if( outFinalURL != NULL ) { *outFinalURL = finalURL; } else { free ( finalURL ) ; } if( outMimeType != NULL ) { *outMimeType = mimeType; } else { if( mimeType != NULL ) { free ( mimeType ) ; } } *outContentLength = receivedLength; return returnString; }
int WebRequest::step() { if( mError ) { return -1; } if( mSock == NULL ) { // we know mLookupThread is not NULL if we get here if( mLookupThread->isLookupDone() ) { mError = true; mNumericalAddress = mLookupThread->getResult(); if( mNumericalAddress != NULL ) { // use timeout of 0 for non-blocking // will be set to true if we time out while connecting char timedOut; mSock = SocketClient::connectToServer( mNumericalAddress, 0, &timedOut ); if( mSock != NULL ) { mError = false; } } if( mError ) { // lookup or socket construction failed if( mNumericalAddress == NULL ) { printf( "Error: " "WebRequest failed to lookup %s\n", mSuppliedAddress->mAddressString ); } else { printf( "Error: " "WebRequest failed to construct " "socket to %s:%d\n", mNumericalAddress->mAddressString, mNumericalAddress->mPort ); } return -1; } } else { // still looking up return 0; } } int connectStatus = mSock->isConnected(); if( connectStatus == 0 ) { // still trying to connect return 0; } else if( connectStatus < 0 ) { // failed to connect mError = true; printf( "Error: " "WebRequest failed to connect to %s:%d\n", mNumericalAddress->mAddressString, mNumericalAddress->mPort ); return -1; } else if( connectStatus == 1 ) { // connected if( mRequestPosition < (int)( strlen( mRequest ) ) ) { // try to send more char *remainingRequest = &( mRequest[ mRequestPosition ] ); int numSent = mSock->send( (unsigned char *)remainingRequest, strlen( remainingRequest ), // non-blocking false ); if( numSent == -1 ) { mError = true; printf( "Error: " "WebRequest failed to connect to " "send full request\n" ); return -1; } if( numSent == -2 ) { return 0; } mRequestPosition += numSent; // don't start looking for response in same step, // even if we just sent the entire request // in practice, it's never ready that fast return 0; } else if( mResultReady ) { return 1; } else { // done sending request // still receiving response long bufferLength = 5000; unsigned char *buffer = new unsigned char[ bufferLength ]; // non-blocking // keep reading as long as we get full buffers int numRead = bufferLength; while( numRead > 0 ) { numRead = mSock->receive( buffer, bufferLength, 0 ); if( numRead > 0 ) { for( int i=0; i<numRead; i++ ) { mResponse.push_back( buffer[i] ); } } } delete [] buffer; if( numRead == -1 ) { // connection closed, done done receiving result // process it char *responseString = mResponse.getElementString(); int responseLength = mResponse.size(); if( stringLocateIgnoreCase( responseString, "404 Not Found" ) != NULL ) { mError = true; delete [] responseString; printf( "Error: " "WebRequest got 404 Not Found error for URL: %s", mURL ); return -1; } const char *contentStartString = "\r\n\r\n"; char *contentStart = strstr( responseString, contentStartString ); if( contentStart != NULL ) { // skip start string char *content = &( contentStart[ strlen( contentStartString ) ] ); // pointer arithmetic: // ugly, but we don't know that result does not contain // \0, so we can't use streln to find result length int resultLength = responseLength - strlen( contentStartString ) - (int)( contentStart - responseString ); mResult = new char[ resultLength + 1 ]; memcpy( mResult, content, resultLength ); mResult[ resultLength ] = '\0'; mResultReady = true; delete [] responseString; return 1; } else { mError = true; printf( "Error: " "WebRequest got badly formatted response:\n%s\n", responseString ); delete [] responseString; return -1; } } else { // still receiving response return 0; } } } // should never get here // count it as error printf( "Error: " "WebRequest got out of expected case tree\n" ); return -1; }
WebRequest::WebRequest( const char *inMethod, const char *inURL, const char *inBody, const char *inProxy ) : mError( false ), mURL( stringDuplicate( inURL ) ), mRequest( NULL ), mRequestPosition( -1 ), mResultReady( false ), mResult( NULL ), mSock( NULL ) { const char *startString = "http://"; char *urlCopy = stringDuplicate( inURL ); char *urlStart = stringLocateIgnoreCase( urlCopy, startString ); char *serverStart; if( urlStart == NULL ) { // no http:// at start of URL serverStart = urlCopy; } else { serverStart = &( urlStart[ strlen( startString ) ] ); } // find the first occurrence of "/", which is the end of the // server name char *serverNameCopy; char *requestHostNameCopy = stringDuplicate( serverStart ); if( inProxy != NULL ) { serverNameCopy = stringDuplicate( inProxy ); } else { // will be same as parsed, request host name copy later serverNameCopy = NULL; } char *getPath; if( inProxy != NULL ) { // for proxy, pass entire URL as method target getPath = (char*)inURL; } else { // for direct connection, pass only file sub-path from URL getPath = strstr( serverStart, "/" ); } char *hostNameEnd = strstr( requestHostNameCopy, "/" ); if( hostNameEnd == NULL ) { hostNameEnd = &( requestHostNameCopy[ strlen( requestHostNameCopy ) ] ); if( inProxy == NULL ) { getPath = (char *)"/"; } } // terminate the url here to extract the host name and port hostNameEnd[0] = '\0'; if( inProxy == NULL ) { serverNameCopy = stringDuplicate( requestHostNameCopy ); } int portNumber = 80; // look for a port number char *colon = strstr( serverNameCopy, ":" ); if( colon != NULL ) { char *portNumberString = &( colon[1] ); int numRead = sscanf( portNumberString, "%d", & portNumber ); if( numRead != 1 ) { portNumber = 80; } // terminate the name here so port isn't taken as part // of the address colon[0] = '\0'; } mSuppliedAddress = new HostAddress( stringDuplicate( serverNameCopy ), portNumber ); mNumericalAddress = NULL; mLookupThread = NULL; // launch right into name lookup mLookupThread = new LookupThread( mSuppliedAddress ); mSock = NULL; // compose the request into a buffered stream StringBufferOutputStream tempStream; tempStream.writeString( inMethod ); tempStream.writeString( " " ); tempStream.writeString( getPath ); tempStream.writeString( " HTTP/1.0\r\n" ); tempStream.writeString( "Host: " ); tempStream.writeString( requestHostNameCopy ); tempStream.writeString( "\r\n" ); if( inBody != NULL ) { char *lengthString = autoSprintf( "Content-Length: %d\r\n", strlen( inBody ) ); tempStream.writeString( lengthString ); delete [] lengthString; tempStream.writeString( "Content-Type: application/x-www-form-urlencoded\r\n\r\n" ); tempStream.writeString( inBody ); } else { tempStream.writeString( "\r\n" ); } mRequest = tempStream.getString(); mRequestPosition = 0; delete [] serverNameCopy; delete [] requestHostNameCopy; delete [] urlCopy; }
void SearchThread::run() { running = true; /* search in cache */ char *searchString = strdup((char *) this->searchTerms.toUtf8 ().constData ()); SimpleVector < char *>*tokens = tokenizeString (searchString); int numSearchTerms = tokens->size (); int pos; bool locked = semCache.tryAcquire(1,1000); for (pos = 0; pos < nbCache; pos++) { if(address!="" && address !="ALL" && Cache[pos].host != address) continue; // check if this is a hash-only search char hashOnlySearch = false; const char *hashStart = "hash_"; char *hashString = (char *)malloc(41); char *pointerToHashStart = strstr (searchString, hashStart); if (pointerToHashStart != NULL) { // search contains a hash-only search. // extract hash, and ignore any other search terms char *pointerToHash = &(pointerToHashStart[strlen (hashStart)]); // hash should be at most 40 characters long int numRead = sscanf (pointerToHash, "%40s", hashString); if (numRead == 1) { delete[]searchString; searchString = hashString; hashOnlySearch = true; } else { free(hashString); } } else { free(hashString); } char hitAll = true; if (!hashOnlySearch) { // check each term for (int j = 0; j < numSearchTerms && hitAll; j++) { char *term = *(tokens->getElement (j)); char * tmpstr = stringLocateIgnoreCase (Cache[pos].name, term); if (tmpstr == NULL) { // missed this term hitAll = false; } else delete [] tmpstr; } } else { char *hashTerm = *(tokens->getElement (0)); if (strcasecmp (hashString, hashTerm) != 0) { hitAll = false; } } if (hitAll) { QTextCodec *codecutf=QTextCodec::codecForName("utf8"); QTextCodec *codeclat=QTextCodec::codecForName("iso8859-1"); QString qstr; // try to convert string from utf8 qstr=codecutf->toUnicode(Cache[pos].name); // test if conversion is reversible if(strcmp(Cache[pos].name,qstr.toUtf8().data())) // if not reversible, it's not utf8, convert from iso8859 : qstr=codeclat->toUnicode(Cache[pos].name); QApplication::postEvent (eventReceiver, new SearchResultEvent (qstr, Cache[pos].size, QString::fromLatin1 (Cache[pos].hash), QString::fromLatin1 (Cache[pos].host))); } } if(locked) semCache.release(1); for (int i = 0; i < numSearchTerms; i++) { delete[](*(tokens->getElement (i))); } delete tokens; free( searchString ); MuteLayer::muteLayerSearch ((char *) this->searchTerms. toLatin1 ().constData (), SearchThread::muteSearchHandler, this, 3000, (char *) this->address. toLatin1 ().constData ()); }