void InventorySlotButton::setHalfMoveTip( char inVault ) { const char *tipHalf = "backpackHalfSlotTip"; const char *tipOne = "backpackSlotTip"; if( inVault ) { tipHalf = "vaultHalfSlotTip"; tipOne = "vaultSlotTip"; } char *tip; if( mQuantity > 3 ) { int sellQuantity = mQuantity / 2; const char *toolDescription = getToolDescriptionPlural( mObjectID ); tip = autoSprintf( translate( tipHalf ), sellQuantity, toolDescription, sellQuantity * mSellPrice ); } else { const char *toolDescription = getToolDescription( mObjectID ); tip = autoSprintf( translate( tipOne ), toolDescription, mSellPrice ); } setMouseOverTip( tip ); delete [] tip; }
void InventorySlotButton::setObject( int inID ) { mObjectID = inID; if( mObjectID == -1 ) { setMouseOverTip( "" ); mSprite = NULL; mQuantity = 0; } else { mQuantity = 1; const char *toolDescription = getToolDescription( mObjectID ); switch( mTransferStatus ) { case 1: { char *tip = autoSprintf( translate( "backpackSlotTip" ), toolDescription ); setMouseOverTip( tip ); delete [] tip; } break; case 2: { char *tip = autoSprintf( translate( "vaultSlotTip" ), toolDescription ); setMouseOverTip( tip ); delete [] tip; } break; case 3: { char *tip = autoSprintf( translate( "sellSlotTip" ), toolDescription, mSellPrice ); setMouseOverTip( tip ); delete [] tip; } break; case 4: { setHalfSellTip(); } break; case 5: { setHalfMoveTip( false ); } break; case 6: { setHalfMoveTip( true ); } break; default: setMouseOverTip( toolDescription ); break; } mSprite = getToolSprite( mObjectID ); } }
char *makePossessive( char *inNameString ) { char *namePossessive; if( inNameString[ strlen( inNameString ) - 1 ] == 's' ) { namePossessive = autoSprintf( "%s'", inNameString ); } else { namePossessive = autoSprintf( "%s's", inNameString ); } delete [] inNameString; return namePossessive; }
void ReplayRobHousePage::setLog( RobberyLog inLog ) { mGridDisplay.setHouseMap( inLog.houseMap ); mGridDisplay.setMoveList( inLog.moveList ); mGridDisplay.setWifeMoney( inLog.wifeMoney ); mGridDisplay.setWifeName( inLog.wifeName ); mGridDisplay.setSonName( inLog.sonName ); mGridDisplay.setDaughterName( inLog.daughterName ); mMusicSeed = inLog.musicSeed; if( mDescription != NULL ) { delete [] mDescription; } const char *descriptionKey = "replayDescription"; if( inLog.isBounty ) { descriptionKey = "replayDescriptionBounty"; } mDescription = autoSprintf( translate( descriptionKey ), inLog.robberName, inLog.victimName, inLog.lootValue ); if( mPackSlotsString != NULL ) { delete [] mPackSlotsString; } mPackSlotsString = stringDuplicate( inLog.backpackContents ); inventorySlotsFromString( mPackSlotsString, mPackSlots, NUM_PACK_SLOTS ); }
void deleteCategoryFromBank( int inParentID ) { File categoriesDir( NULL, "categories" ); if( categoriesDir.exists() && categoriesDir.isDirectory() ) { File *cacheFile = categoriesDir.getChildFile( "cache.fcz" ); cacheFile->remove(); delete cacheFile; char *fileName = autoSprintf( "%d.txt", inParentID ); File *categoryFile = categoriesDir.getChildFile( fileName ); categoryFile->remove(); delete [] fileName; delete categoryFile; } freeCategoryRecord( inParentID ); }
void drawBalance( int inLoot, int inChangeCost ) { doublePair labelPos = { 9, 2 }; mainFont->drawString( translate( "editBalance" ), labelPos, alignRight ); labelPos.y = 1.25; labelPos.x -= 0.125; char *balanceMessage = autoSprintf( "$%d", inLoot ); numbersFontFixed->drawString( balanceMessage, labelPos, alignRight ); delete [] balanceMessage; if( inChangeCost > 0 ) { char costRed = ( inChangeCost > inLoot ); labelPos.y = 0.5; char *costMessage = autoSprintf( "-$%d", inChangeCost ); if( costRed ) { setDrawColor( 1, 0, 0, 1 ); } else { // else green setDrawColor( 0.06666, 0.68627451, 0.454901961, 1 ); } numbersFontFixed->drawString( costMessage, labelPos, alignRight ); delete [] costMessage; } }
void SettingsManager::setSetting( const char *inSettingName, SimpleVector<char *> *inSettingVector ) { char **settingParts = inSettingVector->getElementArray(); char *settingString = join( settingParts, inSettingVector->size(), "\n" ); delete [] settingParts; if( mHashingOn ) { // compute hash char *stringToHash = autoSprintf( "%s%s", settingString, mStaticMembers.mHashSalt ); char *hash = computeSHA1Digest( stringToHash ); delete [] stringToHash; char *hashFileName = getSettingsFileName( inSettingName, "hash" ); FILE *file = fopen( hashFileName, "w" ); delete [] hashFileName; if( file != NULL ) { fprintf( file, "%s", hash ); fclose( file ); } delete [] hash; } FILE *file = getSettingsFile( inSettingName, "w" ); if( file != NULL ) { fprintf( file, "%s", settingString ); fclose( file ); } delete [] settingString; // else do nothing }
char *getTicketHash() { const char *codeToHash = ""; if( downloadCode != NULL ) { codeToHash = downloadCode; } // strip out "-" separators int numParts; char **codeParts = split( codeToHash, "-", &numParts ); char *pureCode = join( codeParts, numParts, "" ); for( int i=0; i<numParts; i++ ) { delete [] codeParts[i]; } delete [] codeParts; char *toHash = autoSprintf( "%d%d%s", serverSequenceNumber, ticketHashVersionNumber, sharedServerSecret ); char *hash = hmac_sha1( pureCode, toHash ); delete [] pureCode; delete [] toHash; char *result = autoSprintf( "sequence_number=%d&ticket_hmac=%s", serverSequenceNumber, hash ); delete [] hash; serverSequenceNumber++; return result; }
void InventorySlotButton::drawContents() { SpriteButton::drawContents(); if( mQuantity > 1 ) { // darken corner double verts[6]; float colors[12]; verts[0] = -mWide / 2; verts[1] = -mHigh / 2; colors[0] = 0; colors[1] = 0; colors[2] = 0; colors[3] = 0; verts[2] = mWide / 2; verts[3] = -mHigh / 2; colors[4] = 0; colors[5] = 0; colors[6] = 0; colors[7] = 0.75; verts[4] = mWide / 2; verts[5] = mHigh / 2; colors[8] = 0; colors[9] = 0; colors[10] = 0; colors[11] = 0; drawTrianglesColor( 1, verts, colors ); doublePair textPos = { 0.5 - mDrawScale, -0.5 }; char *text = autoSprintf( "%d", mQuantity ); setDrawColor( 0.828, 0.647, 0.212, 1 ); mFont->drawString( text, textPos, alignRight ); delete [] text; } }
// sha1 digest of ascii base-10 tool id and reach concatonated with the // key above static char *computeReachSignature( toolRecord *inRecord ) { char *reachString = autoSprintf( "%d %d %s", inRecord->id, inRecord->reach, reachSignatureKey ); char *sig = computeSHA1Digest( reachString ); delete [] reachString; return sig; }
void LoadBackpackPage::checkUndoStatus() { if( mPurchaseHistory.size() == 0 ) { // history exhausted mUndoButton.setVisible( false ); } else { mUndoButton.setVisible( true ); PurchaseHistoryRecord lastTrans = *( mPurchaseHistory.getElement( mPurchaseHistory.size() - 1 ) ); char *tip; if( lastTrans.quantity < -1 ) { // sell multiple tip = autoSprintf( translate( "backpackMultipleSellUndoTip" ), - lastTrans.quantity, getToolDescriptionPlural( lastTrans.objectID ) ); } else { // sell or buy single const char *tipKey = "backpackUndoTip"; if( lastTrans.quantity < 0 ) { // last buy was a sell tipKey = "backpackSellUndoTip"; } tip = autoSprintf( translate( tipKey ), getToolDescription( lastTrans.objectID ) ); } mUndoButton.setMouseOverTip( tip ); delete [] tip; } }
void InventorySlotButton::setHalfSellTip() { char *tip; if( mQuantity > 3 ) { int sellQuantity = mQuantity / 2; const char *toolDescription = getToolDescriptionPlural( mObjectID ); tip = autoSprintf( translate( "sellHalfSlotTip" ), sellQuantity, toolDescription, sellQuantity * mSellPrice ); } else { const char *toolDescription = getToolDescription( mObjectID ); tip = autoSprintf( translate( "sellSlotTip" ), toolDescription, mSellPrice ); } setMouseOverTip( tip ); delete [] tip; }
ChannelReceivingThread::ChannelReceivingThread (InputStream * inInputStream, OutboundChannel * inOutboundChannel, Socket * inSocket, char *inRemoteAddress, int inRemotePort, LocalAddressReceiver * inMessageReceiver, OutboundChannelManager * inOutboundChannelManager, void *inConnectionMaintainer, HostCatcher * inHostCatcher, MessageIDTracker * inMessageIDTracker, KbLimiter * inLimiter, RandomSource * inRandSource): mLock (new QMutex ()), mInputStream (inInputStream), mOutboundChannel (inOutboundChannel), mSocket (inSocket), mRemoteAddress (stringDuplicate (inRemoteAddress)), mRemotePort (inRemotePort), mReceiver (inMessageReceiver), mOutboundChannelManager (inOutboundChannelManager), mConnectionMaintainer (inConnectionMaintainer), mHostCatcher (inHostCatcher), mMessageIDTracker (inMessageIDTracker), mLimiter (inLimiter), mStopSignal (false), mFinished (false), mLoggerName (NULL), mRandSource (inRandSource) { mLoggerName = autoSprintf ("ChannelReceivingThread %s:%d\n", mRemoteAddress, mRemotePort); mMaxUtilityCounter = settings->getMaxMessageUtilitySetting(); mUtilityAlpha = settings->getUtilityAlphaSetting(); mUtilityBeta = settings->getUtilityBetaSetting(); mUtilityGamma = settings->getUtilityGammaSetting(); this->start (); }
char *readStreamUpToTagAndGetToken( InputStream *inInputStream, char *inTag, int inMaxCharsToRead, int inTokenNumber ) { // read the string char *readString = readStreamUpToTag( inInputStream, inTag, inMaxCharsToRead ); if( readString == NULL ) { return NULL; } SimpleVector<char *> *readTokens = tokenizeString( readString ); delete [] readString; // second token should be their key char *selectedToken = NULL; int numTokens = readTokens->size(); if( numTokens > inTokenNumber ) { selectedToken = stringDuplicate( *( readTokens->getElement( inTokenNumber ) ) ); } else { char *message = autoSprintf( "Looking for token %d, but only %d tokens available\n", inTokenNumber, numTokens ); AppLog::error( "readStreamUpToTagAndGetToken", message ); } for( int i=0; i<numTokens; i++ ) { delete [] *( readTokens->getElement( i ) ); } delete readTokens; // will be NULL if not enough tokens read return selectedToken; }
void recordPlayerLineage( char *inEmail, double inAge, int inPlayerID, int inParentID, int inDisplayID, int inKillerID, const char *inName, const char *inLastSay, char inMale ) { if( useLineageServer ) { if( inName == NULL ) { inName = "NAMELESS"; } if( inLastSay == NULL ) { inLastSay = ""; } WebRequest *request; char *encodedEmail = URLUtils::urlEncode( inEmail ); char *url = autoSprintf( "%s?action=get_sequence_number" "&email=%s", lineageServerURL, encodedEmail ); delete [] encodedEmail; request = new WebRequest( "GET", url, NULL ); printf( "Starting new web request for %s\n", url ); delete [] url; LineageRecord r = { stringDuplicate( inEmail ), inAge, inPlayerID, inParentID, inDisplayID, inKillerID, stringDuplicate( inName ), stringDuplicate( inLastSay ), inMale, request, -1 }; records.push_back( r ); } }
void LoadBackpackPage::checkBuyButtonStatus() { if( mSellMode ) { mBuyButton.setVisible( false ); return; } int selectedObject = mToolPicker.getSelectedObject(); if( selectedObject == -1 ) { mBuyButton.setVisible( false ); return; } int price = mToolPicker.getPrice( selectedObject ); if( price > mLootValue ) { mBuyButton.setVisible( false ); return; } // we can afford it for( int i=0; i<NUM_PACK_SLOTS; i++ ) { int slotObject = mPackSlots[i]->getObject(); if( slotObject == -1 || slotObject == selectedObject ) { // empty or matching slot found mBuyButton.setVisible( true ); char *tip = autoSprintf( translate( "buyTip" ), getToolDescription( selectedObject ) ); mBuyButton.setMouseOverTip( tip ); delete [] tip; return; } } // no empty/matching slots mBuyButton.setVisible( false ); }
void BuyAuctionPage::makeActive( char inFresh ) { if( !inFresh ) { return; } // send back to server char *ticketHash = getTicketHash(); char *actionString = autoSprintf( "action=buy_auction&user_id=%d" "&%s" "&object_id=%d", userID, ticketHash, mObjectID ); delete [] ticketHash; mWebRequest = startWebRequestSerial( "POST", serverURL, actionString ); delete [] actionString; mReturnToHome = false; mStatusError = false; mStatusMessageKey = NULL; setStatusDirect( NULL, false ); mHomeButton.setVisible( false ); mBoughtSlot.setVisible( false ); setWaiting( true ); }
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; }
char *readStreamUpToTag( InputStream *inInputStream, char *inTag, int inMaxCharsToRead ) { char *readCharBuffer = new char[ inMaxCharsToRead + 1 ]; int numCharsRead = 0; char tagSeen = false; char readError = false; int tagLength = strlen( inTag ); // start with empty string readCharBuffer[ numCharsRead ] = '\0'; while( numCharsRead < inMaxCharsToRead && !tagSeen && !readError ) { long numRead = inInputStream->readByte( (unsigned char *) ( &( readCharBuffer[ numCharsRead ] ) ) ); if( numRead != 1 ) { readError = true; readCharBuffer[ numCharsRead ] = '\0'; } else { numCharsRead++; // terminate and check if buffer ends with our tag readCharBuffer[ numCharsRead ] = '\0'; if( numCharsRead > tagLength ) { char *possibleBodyStart = &( readCharBuffer[ numCharsRead - tagLength ] ); if( strcmp( possibleBodyStart, inTag ) == 0 ) { tagSeen = true; } } } } if( !readError && tagSeen ) { char *returnString = stringDuplicate( readCharBuffer ); delete [] readCharBuffer; return returnString; } else { char *message = autoSprintf( "Failed to find end tag \"%s\", read %d characters:\n%s\n", inTag, numCharsRead, readCharBuffer ); AppLog::info( "readStreamUpToTag", message ); delete [] message; delete [] readCharBuffer; return NULL; } }
char * ChannelReceivingThread::processFlags (char *inMessageID, char *inFromAddress, char *inOldFlags, char *outIgnoreUC, char *outDropMessage, char *inLoggerName) { char *flags = stringDuplicate (inOldFlags); *outIgnoreUC = false; *outDropMessage = false; // first, check if message should be signed // addresses starting with PKH are hashes of sender's public key if (stringStartsWith (inFromAddress, "PKH")) { // make sure hash in address matches attatched public key // get public key char *pubKey = getFlagData (flags, "PUBLIC_KEY_"); if (pubKey == NULL) { AppLog::detail (inLoggerName, "Message from a PKH address does not have a PUBLIC_KEY flag." " Dropping."); *outDropMessage = true; return flags; } // get signature char *signedID = getFlagData (flags, "SIGNED_ID_"); if (pubKey == NULL) { AppLog::detail (inLoggerName, "Message from a PKH address does not have a SIGNED_ID flag." " Dropping."); delete[]pubKey; *outDropMessage = true; return flags; } char *trueKeyHash = computeSHA1Digest (pubKey); // skip "PKH" in address to get to key hash char *hashInAddress = &(inFromAddress[3]); int trueHashToAddressHashCompare = strcmp (trueKeyHash, hashInAddress); delete[]trueKeyHash; if (trueHashToAddressHashCompare != 0) { AppLog::detail (inLoggerName, "PUBLIC_KEY hash does not match hash from PKH address." " Dropping."); delete[]pubKey; *outDropMessage = true; return flags; } // we have a pubkey that matches the from address // and we have already extracted the signature above // check the signature char signatureCorrect = CryptoUtils::rsaVerify (pubKey, (unsigned char *) inMessageID, strlen (inMessageID), signedID); delete[]pubKey; delete[]signedID; if (!signatureCorrect) { AppLog::detail (inLoggerName, "Bad signature on message from a PKH address." " Dropping."); *outDropMessage = true; return flags; } } // process a FORWARD flag char *pointerToForwardFlag = strstr (flags, "FORWARD_"); if (pointerToForwardFlag != NULL) { // message has forward flag // extract the hash from the forward flag char *oldForwardFlag = stringDuplicate (pointerToForwardFlag); char *pointerToFlagSeparator = strstr (oldForwardFlag, "|"); if (pointerToFlagSeparator != NULL) { // terminate string at separator pointerToFlagSeparator[0] = '\0'; } // skip FORWARD_ to get to the hash char *pointerToHash = &(oldForwardFlag[strlen ("FORWARD_")]); // re-hash the hash to produce a new hash char *newHash = muteComputeNewForwardHash (pointerToHash); if (newHash != NULL) { // continue forwarding *outIgnoreUC = true; char *newForwardFlag = autoSprintf ("FORWARD_%s", newHash); // replace old flag with new one char *tempFlags = muteRemoveFlag (flags, oldForwardFlag); char *newFlags = muteAddFlag (tempFlags, newForwardFlag); delete[]tempFlags; delete[]flags; delete[]newForwardFlag; flags = newFlags; delete[]newHash; } else { // we're breaking the forward tree *outIgnoreUC = false; // remove the forward flag char *newFlags = muteRemoveFlag (flags, oldForwardFlag); delete[]flags; flags = newFlags; AppLog::detail (inLoggerName, "Breaking the FORWARD tree."); } delete[]oldForwardFlag; } // process a DROP_TTL flag char *pointerToDropTTLFlag = strstr (flags, "DROP_TTL_"); if (pointerToDropTTLFlag != NULL) { // message has drop TTL flag // extract the hash from the dropTTL flag char *oldDropTTLFlag = stringDuplicate (pointerToDropTTLFlag); char *pointerToFlagSeparator = strstr (oldDropTTLFlag, "|"); if (pointerToFlagSeparator != NULL) { // terminate string at separator pointerToFlagSeparator[0] = '\0'; } // skip DROP_TTL_ to get to the TTL value char *pointerToTTLValue = &(oldDropTTLFlag[strlen ("DROP_TTL_")]); int ttlValue; int numRead = sscanf (pointerToTTLValue, "%d", &ttlValue); if (numRead == 1) { ttlValue--; if (ttlValue <= 0) { *outDropMessage = true; AppLog::detail (inLoggerName, "Breaking the DROP_TTL tree, since the TTL reached 0."); } else { char *newDropTTLFlag = autoSprintf ("DROP_TTL_%d", ttlValue); // replace old flag with new one char *tempFlags = muteRemoveFlag (flags, oldDropTTLFlag); char *newFlags = muteAddFlag (tempFlags, newDropTTLFlag); delete[]tempFlags; delete[]flags; delete[]newDropTTLFlag; flags = newFlags; } // ignore the UC in drop mode *outIgnoreUC = true; } delete[]oldDropTTLFlag; } // process a DROP_CHAIN flag char *pointerToDropChainFlag = strstr (flags, "DROP_CHAIN"); if (pointerToDropChainFlag != NULL) { // message has drop chain flag // ignore UCs on all DROP tail messages *outIgnoreUC = true; if (muteShouldDropTailChainMessages ()) { *outDropMessage = true; AppLog::detail (inLoggerName, "Breaking the DROP_CHAIN."); } } return flags; }
ScreenGL::ScreenGL( int inWide, int inHigh, char inFullScreen, unsigned int inMaxFrameRate, char inRecordEvents, const char *inWindowName, KeyboardHandlerGL *inKeyHandler, MouseHandlerGL *inMouseHandler, SceneHandlerGL *inSceneHandler ) : mWide( inWide ), mHigh( inHigh ), mImageSizeSet( false ), mImageWide( inWide ), mImageHigh( inHigh ), mFullScreen( inFullScreen ), m2DMode( false ), mViewPosition( new Vector3D( 0, 0, 0 ) ), mViewOrientation( new Angle3D( 0, 0, 0 ) ), mMouseHandlerVector( new SimpleVector<MouseHandlerGL*>() ), mKeyboardHandlerVector( new SimpleVector<KeyboardHandlerGL*>() ), mSceneHandlerVector( new SimpleVector<SceneHandlerGL*>() ), mRedrawListenerVector( new SimpleVector<RedrawListenerGL*>() ) { // add handlers if NULL (the default) was not passed in for them if( inMouseHandler != NULL ) { addMouseHandler( inMouseHandler ); } if( inKeyHandler != NULL ) { addKeyboardHandler( inKeyHandler ); } if( inSceneHandler != NULL ) { addSceneHandler( inSceneHandler ); } if( mFullScreen ) { glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ); //| GLUT_FULLSCREEN ); } else { glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ); } if( !mFullScreen ) { glutInitWindowSize( mWide, mHigh ); glutCreateWindow( inWindowName ); } else { // use game mode for full screen char *gameMode = autoSprintf( "%dx%d:32", mWide, mHigh ); glutGameModeString( gameMode ); if( glutGameModeGet( GLUT_GAME_MODE_POSSIBLE ) ) { glutEnterGameMode(); delete [] gameMode; } else { printf( "The full-screen mode %s is not available\n", gameMode ); delete [] gameMode; exit(1); } } glutIgnoreKeyRepeat( 1 ); glutKeyboardFunc( callbackKeyboard ); glutKeyboardUpFunc( callbackKeyboardUp ); glutSpecialFunc( callbackSpecialKeyboard ); glutSpecialUpFunc( callbackSpecialKeyboardUp ); glutReshapeFunc( callbackResize ); glutMotionFunc( callbackMotion ); glutMouseFunc( callbackMouse ); glutPassiveMotionFunc( callbackPassiveMotion ); glutDisplayFunc( callbackDisplay ); glutIdleFunc( callbackIdle ); glEnable( GL_DEPTH_TEST ); glEnable( GL_CULL_FACE ); glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glCullFace( GL_BACK ); glFrontFace( GL_CCW ); }
void CheckinHousePage::step() { // wait until pending LiveHousePage requests are sent // to prevent bad request orderings (house checked in before // start_self_test received by server). if( LiveHousePage::areRequestsPending() ) { // note that we don't step LiveHousePage otherwise, because // we don't want it starting NEW ping requests after // we send our request (lest our request's sequence number // will be stale) LiveHousePage::step(); return; } if( ! mRequestStarted ) { // send back to server char *ticketHash = getTicketHash(); char *actionString = autoSprintf( "action=end_edit_house&user_id=%d" "&%s&died=%d&house_map=%s&vault_contents=%s" "&backpack_contents=%s&gallery_contents=%s" "&price_list=%s&purchase_list=%s&sell_list=%s" "&self_test_move_list=%s&family_exit_paths=%s", userID, ticketHash, mDied, mHouseMap, mVaultContents, mBackpackContents, mGalleryContents, mPriceList, mPurchaseList, mSellList, mMoveList, mFamilyExitPaths ); delete [] ticketHash; mWebRequest = startWebRequestSerial( "POST", serverURL, actionString ); delete [] actionString; mRequestStarted = true; return; } if( mWebRequest != -1 ) { int stepResult = stepWebRequestSerial( mWebRequest ); if( stepResult != 0 ) { setWaiting( false ); } switch( stepResult ) { case 0: break; case -1: mStatusError = true; mStatusMessageKey = "err_webRequest"; clearWebRequestSerial( mWebRequest ); mWebRequest = -1; mMenuButton.setVisible( true ); blockQuitting( false ); break; case 1: { char *result = getWebResultSerial( mWebRequest ); clearWebRequestSerial( mWebRequest ); mWebRequest = -1; printf( "Web result = %s\n", result ); if( strstr( result, "OK" ) != NULL ) { // house checked in! if( mDied != 1 ) { mStatusError = false; mStatusMessageKey = "houseCheckedIn"; mReturnToMenu = true; } else { mStatusError = true; mStatusMessageKey = "deathMessage"; mStartOverButton.setVisible( true ); blockQuitting( false ); } } else { mStatusError = true; mStatusMessageKey = "houseCheckInFailed"; mMenuButton.setVisible( true ); blockQuitting( false ); } delete [] result; } break; } } }
void stepLineageLog() { if( ! useLineageServer ) { return; } for( int i=0; i<records.size(); i++ ) { LineageRecord *r = records.getElement( i ); int result = r->request->step(); char recordDone = false; if( result == -1 ) { AppLog::info( "Request to lineage server failed." ); recordDone = true; } else if( result == 1 ) { // done, have result char *webResult = r->request->getResult(); if( r->sequenceNumber == -1 ) { // still waiting for sequence number response int numRead = sscanf( webResult, "%d", &( r->sequenceNumber ) ); if( numRead != 1 ) { AppLog::info( "Failed to read sequence number " "from lineage server response." ); recordDone = true; } else { delete r->request; // start lineage-posting request char *seqString = autoSprintf( "%d", r->sequenceNumber ); char *lineageServerSharedSecret = SettingsManager::getStringSetting( "lineageServerSharedSecret", "secret_phrase" ); char *hash = hmac_sha1( lineageServerSharedSecret, seqString ); delete [] lineageServerSharedSecret; delete [] seqString; char *encodedEmail = URLUtils::urlEncode( r->email ); char *encodedName = URLUtils::urlEncode( r->name ); char *encodedLastSay = URLUtils::urlEncode( r->lastSay ); int maleInt = 0; if( r->male ) { maleInt = 1; } char *url = autoSprintf( "%s?action=log_life" "&server=%s" "&email=%s" "&age=%f" "&player_id=%d" "&parent_id=%d" "&display_id=%d" "&killer_id=%d" "&name=%s" "&last_words=%s" "&male=%d" "&sequence_number=%d" "&hash_value=%s", lineageServerURL, serverID, encodedEmail, r->age, r->playerID, r->parentID, r->displayID, r->killerID, encodedName, encodedLastSay, maleInt, r->sequenceNumber, hash ); delete [] encodedEmail; delete [] encodedName; delete [] encodedLastSay; delete [] hash; r->request = new WebRequest( "GET", url, NULL ); printf( "Starting new web request for %s\n", url ); delete [] url; } } else { if( strstr( webResult, "DENIED" ) != NULL ) { AppLog::info( "Server log_life request rejected by lineage server" ); } recordDone = true; } delete [] webResult; } if( recordDone ) { delete r->request; delete [] r->email; delete [] r->name; delete [] r->lastSay; records.deleteElement( i ); i--; } } }
int main( int inNumArgs, char **inArgs ) { if( inNumArgs != 8 ) { usage(); } File voiceFile( NULL, inArgs[1] ); if( ! voiceFile.exists() || voiceFile.isDirectory() ) { usage(); } int dataLength; unsigned char *aiffData = voiceFile.readFileContents( &dataLength ); if( aiffData == NULL ) { usage(); } samples = readMono16AIFFData( aiffData, dataLength, &numSamples, &sampleRate ); delete [] aiffData; if( samples == NULL ) { usage(); } int numRead = sscanf( inArgs[2], "%d", &fps ); if( numRead != 1 ) { usage(); } int mps = 0; numRead = sscanf( inArgs[3], "%d", &mps ); if( numRead != 1 ) { usage(); } int framesPerMove = ceil( (double)fps / (double)mps ); printf( "%d frames per move\n", framesPerMove ); double thresh = 0; numRead = sscanf( inArgs[4], "%lf", &thresh ); if( numRead != 1 ) { usage(); } File shapesDir( NULL, inArgs[5] ); if( ! shapesDir.exists() || ! shapesDir.isDirectory() ) { usage(); } File destDir( NULL, inArgs[6] ); if( ! destDir.exists() || ! destDir.isDirectory() ) { usage(); } File listFile( NULL, inArgs[7] ); if( listFile.isDirectory() ) { usage(); } SimpleVector<char> list; shapeFiles = shapesDir.getChildFilesSorted( &numShapes ); if( numShapes < 2 ) { usage(); } char **shapeStrings = new char*[numShapes]; for( int i=0; i<numShapes; i++ ) { shapeStrings[i] = autoSprintf( "%d\n", i ); } double numSec = numSamples / (double)sampleRate; int numFrames = ceil( numSec * fps ); File **frameShapes = new File*[numFrames]; // default to closed mouth for( int i=0; i<numFrames; i++ ) { frameShapes[i] = shapeFiles[0]; } int i = 0; while( i < numFrames ) { // avoid flicker by holding quiet frame longer int framesQuiet = 0; while( i < numFrames && ( ! getTalking( i, thresh ) || framesQuiet < framesPerMove ) ) { frameShapes[i] = shapeFiles[0]; list.appendElementString( shapeStrings[0] ); i++; framesQuiet++; } // talking now int framesTalking = 0; int pick = randSource.getRandomBoundedInt( 1, numShapes - 1 ); File *curShape = shapeFiles[ pick ]; while( i < numFrames && ( getTalking( i, thresh ) || framesTalking < framesPerMove ) ) { frameShapes[i] = curShape; list.appendElementString( shapeStrings[pick] ); framesTalking ++; if( framesTalking % framesPerMove == 0 ) { File *newCurShape = curShape; // pick next randomly, but force change while( newCurShape == curShape ) { pick = randSource.getRandomBoundedInt( 1, numShapes - 1 ); newCurShape = shapeFiles[ pick ]; } curShape = newCurShape; } i++; } } for( int i=0; i<numFrames; i++ ) { char *name = autoSprintf( "frame%05d.tga", i+1 ); File *dest = destDir.getChildFile( name ); frameShapes[i]->copy( dest ); delete [] name; delete dest; } char *listString = list.getElementString(); listFile.writeToFile( listString ); for( int i=0; i<numShapes; i++ ) { delete shapeFiles[i]; delete [] shapeStrings[i]; } delete [] shapeFiles; delete [] samples; return 0; }
SimpleVector<char *> *SettingsManager::getSetting( const char *inSettingName ) { char *fileName = getSettingsFileName( inSettingName ); File *settingsFile = new File( NULL, fileName ); delete [] fileName; char *fileContents = settingsFile->readFileContents(); delete settingsFile; if( fileContents == NULL ) { // return empty vector return new SimpleVector<char *>(); } if( mHashingOn ) { char *hashFileName = getSettingsFileName( inSettingName, "hash" ); File *hashFile = new File( NULL, hashFileName ); delete [] hashFileName; char *savedHash = hashFile->readFileContents(); delete hashFile; if( savedHash == NULL ) { printf( "Hash missing for setting %s\n", inSettingName ); delete [] fileContents; return new SimpleVector<char *>(); } // compute hash char *stringToHash = autoSprintf( "%s%s", fileContents, mStaticMembers.mHashSalt ); char *hash = computeSHA1Digest( stringToHash ); delete [] stringToHash; int difference = strcmp( hash, savedHash ); delete [] hash; delete [] savedHash; if( difference != 0 ) { printf( "Hash mismatch for setting %s\n", inSettingName ); delete [] fileContents; return new SimpleVector<char *>(); } } // else tokenize the file contents SimpleVector<char *> *returnVector = tokenizeString( fileContents ); delete [] fileContents; return returnVector; }
void initTools() { File elementsDir( NULL, "gameElements" ); if( !elementsDir.exists() || !elementsDir.isDirectory() ) { return; } File *toolsDir = elementsDir.getChildFile( "tools" ); if( toolsDir == NULL ) { return; } else if( !toolsDir->exists() || !toolsDir->isDirectory() ) { delete toolsDir; return; } int numTools; File **toolNameDirs = toolsDir->getChildFiles( &numTools ); delete toolsDir; if( toolNameDirs == NULL ) { return; } for( int i=0; i<numTools; i++ ) { File *f = toolNameDirs[i]; if( f->exists() && f->isDirectory() ) { char completeRecord = true; toolRecord r; r.name = f->getFileName(); r.description = NULL; r.descriptionPlural = NULL; r.sprite = NULL; File *infoFile = f->getChildFile( "info.txt" ); completeRecord = readInfoFile( infoFile, &( r.id ), &( r.description ) ); delete infoFile; if( completeRecord ) { File *pluralFile = f->getChildFile( "plural.txt" ); completeRecord = readPluralFile( pluralFile, &( r.descriptionPlural ) ); delete pluralFile; } if( completeRecord ) { // read reach, if present (if not, default to 1) r.reach = 1; File *reachFile = f->getChildFile( "reach.txt" ); if( reachFile->exists() ) { char *reach = reachFile->readFileContents(); sscanf( reach, "%d", &( r.reach ) ); delete [] reach; } delete reachFile; File *reachSigFile = f->getChildFile( "reachSignature.txt" ); char *reachSigContents = NULL; if( reachSigFile->exists() ) { reachSigContents = reachSigFile->readFileContents(); } delete reachSigFile; char reachSigOK = true; if( regenerateReachSignatures ) { // ignore reachSignature.txt and generate a new one char *newSig = computeReachSignature( &r ); File *childFile = f->getChildFile( "reachSignature.txt" ); if( childFile != NULL ) { childFile->writeToFile( newSig ); delete childFile; } delete [] newSig; } else if( reachSigContents == NULL ) { reachSigOK = false; } else { // else check it char *sig = trimWhitespace( reachSigContents ); char *trueSig = computeReachSignature( &r ); if( strcmp( trueSig, sig ) != 0 ) { reachSigOK = false; } delete [] sig; delete [] trueSig; } if( reachSigContents != NULL ) { delete [] reachSigContents; } if( !reachSigOK ) { char *dirName = f->getFullFileName(); char *message = autoSprintf( "%s\n%s", translate( "badReachSignature" ), dirName ); delete [] dirName; loadingFailed( message ); delete [] message; } // look for sprite TGA int numChildFiles; File **childFiles = f->getChildFiles( &numChildFiles ); char *tgaPath = NULL; char *shadeMapTgaPath = NULL; for( int j=0; j<numChildFiles; j++ ) { File *f = childFiles[j]; char *name = f->getFileName(); if( strstr( name, "_shadeMap.tga" ) != NULL ) { if( shadeMapTgaPath != NULL ) { delete [] shadeMapTgaPath; } shadeMapTgaPath = f->getFullFileName(); } else if( strstr( name, ".tga" ) != NULL ) { if( tgaPath != NULL ) { delete [] tgaPath; } tgaPath = f->getFullFileName(); } delete [] name; delete childFiles[j]; } delete [] childFiles; if( tgaPath != NULL ) { // assume only one orientation here // discard extras SpriteHandle readSprites[ MAX_ORIENTATIONS ]; int numOrientations = readShadeMappedSprites( tgaPath, shadeMapTgaPath, readSprites ); if( numOrientations == 0 ) { completeRecord = false; } else { r.sprite = readSprites[0]; for( int o=1; o<numOrientations; o++ ) { freeSprite( readSprites[o] ); } } } else { if( shadeMapTgaPath != NULL ) { delete [] shadeMapTgaPath; } completeRecord = false; } } if( completeRecord ) { if( r.id >= idSpaceSize ) { idSpaceSize = r.id + 1; } tools.push_back( r ); } else { delete [] r.name; if( r.description != NULL ) { delete [] r.description; } if( r.descriptionPlural != NULL ) { delete [] r.descriptionPlural; } if( r.sprite != NULL ) { freeSprite( r.sprite ); } } } delete f; } delete [] toolNameDirs; // build map idToIndexMap = new int[idSpaceSize]; for( int i=0; i<idSpaceSize; i++ ) { idToIndexMap[i] = -1; } for( int i=0; i<tools.size(); i++ ) { toolRecord r = *( tools.getElement( i ) ); idToIndexMap[r.id] = i; } }
void BuyAuctionPage::step() { if( mWebRequest != -1 ) { int stepResult = stepWebRequestSerial( mWebRequest ); if( stepResult != 0 ) { setWaiting( false ); } switch( stepResult ) { case 0: break; case -1: mStatusError = true; mStatusMessageKey = "err_webRequest"; clearWebRequestSerial( mWebRequest ); mWebRequest = -1; mHomeButton.setVisible( true ); break; case 1: { char *result = getWebResultSerial( mWebRequest ); clearWebRequestSerial( mWebRequest ); mWebRequest = -1; printf( "Web result = %s\n", result ); if( strstr( result, "DENIED" ) != NULL ) { mStatusError = true; mStatusMessageKey = "auctionBuyFailed"; mHomeButton.setVisible( true ); } else { // auction successful SimpleVector<char *> *tokens = tokenizeString( result ); if( tokens->size() != 2 || strcmp( *( tokens->getElement( 1 ) ), "OK" ) != 0 ) { mStatusError = true; mStatusMessageKey = "err_badServerResponse"; } else { int price; sscanf( *( tokens->getElement( 0 ) ), "%d", &price ); mBoughtSlot.setObject( mObjectID ); mBoughtSlot.setVisible( true ); mLootValue -= price; if( strcmp( mGalleryContents, "#" ) == 0 ) { // was empty, just the one new item now delete [] mGalleryContents; mGalleryContents = autoSprintf( "%d", mObjectID ); } else { // prepend char *old = mGalleryContents; mGalleryContents = autoSprintf( "%d#%s", mObjectID, mGalleryContents ); delete [] old; } const char *objectDescription = getGalleryObjectDescription( mObjectID ); char *quotedDescription = autoSprintf( "\"%s\"", objectDescription ); char *statusString = autoSprintf( translate( "auctionBuySucceed" ), quotedDescription, price ); delete [] quotedDescription; setStatusDirect( statusString, false ); delete [] statusString; } mHomeButton.setVisible( true ); for( int i=0; i<tokens->size(); i++ ) { delete [] *( tokens->getElement( i ) ); } delete tokens; } delete [] result; } break; } } }
void LiveHousePage::step() { if( sWebRequest != -1 ) { int result = stepWebRequestSerial( sWebRequest ); if( result != 0 ) { // send is over, not matter what response we get back // same response possibilies for all requests types here switch( result ) { case -1: mCheckoutStale = true; if( mCurrentRequestForStartTest ) { mStartTestFailed = true; } printf( "Web request FAILED!\n" ); break; case 1: { char *response = getWebResultSerial( sWebRequest ); printf( "Server response: %s\n", response ); // same OK result expected whether we // have sent a ping or a self-test start/end if( strstr( response, "OK" ) == NULL ) { mCheckoutStale = true; if( mCurrentRequestForStartTest ) { mStartTestFailed = true; } if( strstr( response, "OUT_OF_TIME" ) != NULL ) { mOutOfTime = true; } } delete [] response; } } clearWebRequestSerial( sWebRequest ); sWebRequest = -1; } } else if( sPendingTestRequests.size() > 0 ) { const char *command = *( sPendingTestRequests.getElement( 0 ) ); sPendingTestRequests.deleteElement( 0 ); if( strcmp( command, "start_self_test" ) == 0 ) { mCurrentRequestForStartTest = true; } else { mCurrentRequestForStartTest = false; } char *ticketHash = getTicketHash(); char *fullRequestURL = autoSprintf( "%s?action=%s&user_id=%d" "&%s", serverURL, command, userID, ticketHash ); delete [] ticketHash; sWebRequest = startWebRequestSerial( "GET", fullRequestURL, NULL ); delete [] fullRequestURL; // counts as a ping sLastPingTime = game_time( NULL ); } else if( ! mCheckoutStale ) { int currentTime = game_time( NULL ); if( currentTime > sLastPingTime + 60 * 4 ) { // getting close to five minute timeout mark if( currentTime - mLastActionTime < 60 * 5 ) { // there's been activity in the last five minutes // send ping char *ticketHash = getTicketHash(); char *fullRequestURL = autoSprintf( "%s?action=ping_house&user_id=%d" "&%s", serverURL, userID, ticketHash ); delete [] ticketHash; sWebRequest = startWebRequestSerial( "GET", fullRequestURL, NULL ); mCurrentRequestForStartTest = false; delete [] fullRequestURL; sLastPingTime = currentTime; } } } }
int main( int inNumArgs, char **inArgs ) { if( inNumArgs != 5 ) { usage(); } char *address = inArgs[1]; int port = 8005; sscanf( inArgs[2], "%d", &port ); char *emailPrefix = inArgs[3]; int numClients = 1; sscanf( inArgs[4], "%d", &numClients ); Client *connections = new Client[ numClients ]; // first, connect each int numConnected = 0; for( int i=0; i<numClients; i++ ) { connections[i].i = i; connections[i].id = -1; connections[i].skipCompressedData = 0; connections[i].pendingCMData = false; connections[i].moving = false; connections[i].dead = false; connections[i].disconnected = false; HostAddress a( stringDuplicate( address ), port ); char timeout = false; connections[i].sock = SocketClient::connectToServer( &a, 5000, &timeout ); if( timeout ) { printf( "Client %d timed out when trying to connect\n", i ); delete connections[i].sock; connections[i].sock = NULL; continue; } if( connections[i].sock != NULL ) { numConnected ++; char *email = autoSprintf( "*****@*****.**", emailPrefix, i ); printf( "Client %d connected, logging in with email %s\n", i, email ); char *message = autoSprintf( "LOGIN %s aaaa aaaa#", email ); connections[i].sock->send( (unsigned char*)message, strlen( message ), true, false ); delete [] message; delete [] email; } else { printf( "Client %d failed to connect\n", i ); } } // process messages while( numConnected > 0 ) { numConnected = 0; for( int i=0; i<numClients; i++ ) { if( connections[i].sock == NULL ) { continue; } numConnected ++; if( connections[i].id == -1 ) { // still waiting for first PU if( connections[i].disconnected ) { printf( "Client %d lost connection\n", i ); delete connections[i].sock; connections[i].sock = NULL; continue; } char *message = getNextMessage( &( connections[i] ) ); if( message != NULL ) { //printf( "Client %d got message:\n%s\n\n", i, message ); if( strstr( message, "MC" ) == message ) { //printf( "Client %d got first map chunk\n", i ); int sizeX, sizeY, x, y, binarySize, compSize; sscanf( message, "MC\n%d %d %d %d\n%d %d\n", &sizeX, &sizeY, &x, &y, &binarySize, &compSize ); connections[i].skipCompressedData = compSize; } else if( strstr( message, "PU" ) == message ) { // PU message! // last line describes us int numLines; char **lines = split( message, "\n", &numLines ); if( numLines > 2 ) { // first line is about us parsePlayerUpdateMessage( &( connections[i] ), lines[ numLines - 2 ] ); } printf( "Client %d got first player update, " "pid = %d, pos = %d,%d\n", i, connections[i].id, connections[i].x, connections[i].y ); for( int p=0; p<numLines; p++ ) { delete [] lines[p]; } delete [] lines; } delete [] message; } } else { // player is live if( connections[i].dead ) { printf( "Client %d died, closing connection\n", i ); delete connections[i].sock; connections[i].sock = NULL; continue; } if( connections[i].disconnected ) { printf( "Client %d lost connection\n", i ); delete connections[i].sock; connections[i].sock = NULL; continue; } if( !connections[i].moving ) { // make a move connections[i].moving = true; //printf( "Client %d starting move\n", i ); int xDelt = 0; int yDelt = 0; while( xDelt == 0 && yDelt == 0 ) { xDelt = randSource.getRandomBoundedInt( -1, 1 ); yDelt = randSource.getRandomBoundedInt( -1, 1 ); } char *message = autoSprintf( "MOVE %d %d %d %d#", connections[i].x, connections[i].y, xDelt, yDelt ); connections[i].sock->send( (unsigned char*)message, strlen( message ), true, false ); delete [] message; } char *message = getNextMessage( &( connections[i] ) ); if( message != NULL ) { if( strstr( message, "MC" ) == message ) { int sizeX, sizeY, x, y, binarySize, compSize; sscanf( message, "MC\n%d %d %d %d\n%d %d\n", &sizeX, &sizeY, &x, &y, &binarySize, &compSize ); connections[i].skipCompressedData = compSize; } else if( strstr( message, "PU" ) == message ) { // PU message! int numLines; char **lines = split( message, "\n", &numLines ); for( int p=1; p<numLines-1; p++ ) { parsePlayerUpdateMessage( &( connections[i] ), lines[p] ); } for( int p=0; p<numLines; p++ ) { delete [] lines[p]; } delete [] lines; } delete [] message; } } } } printf( "No more clients connected\n" ); for( int i=0; i<numClients; i++ ) { if( connections[i].sock != NULL ) { delete connections[i].sock; } } delete [] connections; return 1; }
char *WebClient::executeWebMethod( const char *inMethod, char *inURL, char *inBody, int *outContentLength, char **outFinalURL, char **outMimeType, long inTimeoutInMilliseconds ) { char *returnString = 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 = stringDuplicate( serverStart ); char *serverEnd = strstr( serverNameCopy, "/" ); const 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( stringDuplicate( serverNameCopy ), portNumber ); // will be set to true if we time out while connecting char timedOut; Socket *sock = SocketClient::connectToServer( host, inTimeoutInMilliseconds, &timedOut ); char *finalURL = stringDuplicate( 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" ); if( inBody != NULL ) { char *lengthString = autoSprintf( "Content-Length: %d\r\n", strlen( inBody ) ); stream->writeString( lengthString ); delete [] lengthString; stream->writeString( "Content-Type: application/x-www-form-urlencoded\r\n\r\n" ); stream->writeString( inBody ); } else { stream->writeString( "\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 const 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; content = getWebPage( locationStart, &receivedLength, &newFinalURL, &mimeType ); delete [] finalURL; finalURL = newFinalURL; if( content == NULL ) { // not found recursively notFound = true; } } } const char *contentStartString = "\r\n\r\n"; const 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 = stringDuplicate( contentType ); } delete [] contentType; } // extract the content from what we've received char *contentStart = strstr( received, contentStartString ); if( contentStart != NULL ) { content = &( contentStart[ strlen( contentStartString ) ] ); receivedLength = receivedLength - strlen( contentStartString ) - ( (int)contentStart - (int)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; delete [] serverNameCopy; delete [] urlCopy; if( outFinalURL != NULL ) { *outFinalURL = finalURL; } else { delete [] finalURL; } if( outMimeType != NULL ) { *outMimeType = mimeType; } else { if( mimeType != NULL ) { delete [] mimeType; } } *outContentLength = receivedLength; return returnString; }