Use this library to upload images to twitpic.com. The library creates and uses its own TCPSocket. Requires EthernetNetIf and DNSResolver. (this library actually designed by a friend of mine, novachild, with no mbed license of his own.)
TwitPic.cpp
00001 /* 00002 TwitPic.cpp - TwitPic Image Uploader for mbed 00003 Copyright (c) novachild 2011. All right reserved. 00004 00005 This library is distributed in the hope that it will be useful, 00006 but WITHOUT ANY WARRANTY; without even the implied warranty of 00007 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00008 */ 00009 00010 #include "TwitPic.h" 00011 #include "string.h" 00012 00013 #define MIN(a, b) (a < b ? a : b) 00014 #define MAX(a, b) (a > b ? a : b) 00015 00016 #define SENDING_BUFFER_SIZE 4096 //must be large enough to hold all parameters: I wouldn't go under 2 KB. 00017 #define RECEIVING_BUFFER_SIZE 1024 //for holding respones (early ones will be discared, 1KB should do) 00018 #define SENDING_CHUNK_SIZE 1024 //amount to send over the socket at once. 00019 00020 #define TWITPIC_URL "api.twitpic.com" 00021 #define TWITPIC_UPLOAD_API_URL "/1/upload.xml" 00022 #define TWITPIC_UPLOAD_AND_POST_API_URL "/1/uploadAndPost.xml" 00023 00024 #define BOUNDARY "----------0dcb31395642" 00025 #define HEADER "--" BOUNDARY 00026 #define FOOTER "--" BOUNDARY "--" 00027 00028 #define DEBUG 1 00029 #define TRACE 1 00030 00031 00032 const char* m_twitpic_api_key; //twitpic API key 00033 const char* m_consumer_key; //Consumer key 00034 const char* m_consumer_secret; //Consumer secret 00035 const char* m_access_token; //Access Token 00036 const char* m_access_token_secret; //Access Token secret 00037 const char* twitterMessage; 00038 00039 bool post = false; 00040 00041 bool sentHeaders = false; 00042 bool sentParameters = false; 00043 bool sentImageData = false; 00044 bool sentFooter = false; 00045 bool finishedSending = false; 00046 00047 bool positiveResponse = false; 00048 bool readyToReturn = false; 00049 bool stillPolling = false; 00050 00051 char sendBuf[SENDING_BUFFER_SIZE]; 00052 char recvBuf[RECEIVING_BUFFER_SIZE]; 00053 00054 int imgSize=0; 00055 int writing_position = 0; 00056 int errorCode = 0; 00057 int preCalcedContentLength=0; 00058 00059 int totalSentData=0; 00060 00061 FILE *imgFile; 00062 00063 00064 TwitPic::TwitPic(const char *twitpic_api_key, const char *consumer_key, const char *consumer_secret, const char *access_token, const char *access_token_secret) { 00065 00066 m_twitpic_api_key = twitpic_api_key; 00067 m_consumer_key = consumer_key; 00068 m_consumer_secret = consumer_secret; 00069 m_access_token = access_token; 00070 m_access_token_secret = access_token_secret; 00071 socket.setOnEvent(this, &TwitPic::handleTCPSocketEvents); 00072 00073 preCalcedContentLength = 7 * (sizeof(HEADER)-1) + 00074 24* (sizeof("\r\n")-1) + 00075 6 * (sizeof("Content-Disposition: form-data; name=\"") - 1) + 00076 sizeof("key") + 00077 sizeof("consumer_token") + 00078 sizeof("consumer_secret") + 00079 sizeof("oauth_token") + 00080 sizeof("oauth_secret") + 00081 sizeof("message") + 00082 strlen(m_twitpic_api_key) + 00083 strlen(m_consumer_key) + 00084 strlen(m_consumer_secret) + 00085 strlen(m_access_token) + 00086 strlen(m_access_token_secret) + 00087 sizeof("\r\nContent-Disposition: form-data; name=\"media\"; filename=\"image.jpg\"\r\n")-1 + 00088 sizeof("Content-Type: image/jpeg\r\n")-1 + 00089 sizeof("Content-Transfer-Encoding: binary\r\n\r\n")-1 + 00090 sizeof("\r\n")-1 + 00091 sizeof(FOOTER) - 1 + 00092 sizeof("\r\n") - 1; 00093 00094 } 00095 00096 int TwitPic::upload(const char *message, 00097 FILE *img, 00098 bool toPost) { 00099 00100 if (TRACE) printf("-----------------------TRACE: upload\n"); 00101 post = toPost; 00102 imgFile = img; 00103 twitterMessage = message; 00104 00105 DNSResolver resolver; 00106 server.setIp(resolver.resolveName("api.twitpic.com")); 00107 server.setPort(80); 00108 00109 //Calculate image size 00110 fseek (imgFile , 0 , SEEK_END); 00111 imgSize = ftell (img); 00112 rewind (imgFile); 00113 00114 00115 00116 sentHeaders = false; 00117 sentParameters = false; 00118 sentImageData = false; 00119 sentFooter = false; 00120 positiveResponse = false; 00121 finishedSending = false; 00122 readyToReturn = false; 00123 writing_position = 0; 00124 00125 if (DEBUG) printf("Opening connection to api.twitpic.com\n"); 00126 TCPSocketErr err = socket.connect(server); 00127 if (err < 0) { 00128 if (DEBUG) printf("Error connecting socket: %i",err); 00129 return err; 00130 } 00131 00132 if (DEBUG) printf("Beginning network polling cycle.\n"); 00133 int countAfterSent = 0; 00134 while (! readyToReturn) { 00135 if (TRACE && !stillPolling) printf("-----------------------TRACE: Net::poll()\n"); 00136 stillPolling = true; 00137 Net::poll(); 00138 if (finishedSending) countAfterSent++; 00139 if (countAfterSent > 1000000) { 00140 if (DEBUG) printf("Polled 1000000 times and got no response. Quitting.\n"); 00141 positiveResponse = false; 00142 readyToReturn = true; 00143 } 00144 } 00145 00146 if (positiveResponse) { 00147 printf("Image uploaded.\n"); 00148 return 0; 00149 } else { 00150 printf("Image not successfully uploaded\n"); 00151 return errorCode; 00152 } 00153 00154 } 00155 00156 int TwitPic::uploadAndPost(const char *message, 00157 FILE *imgFile) { 00158 return upload(message, imgFile, true); 00159 } 00160 00161 void TwitPic::handleTCPSocketEvents(TCPSocketEvent ev) { 00162 stillPolling = false; 00163 if (TRACE) printf("-----------------------TRACE: handleTCPSocketEvent\n"); 00164 switch (ev) { 00165 case TCPSOCKET_ERROR: 00166 printf("-----TCPSocket: Unknown Error\n"); 00167 goto error; 00168 case TCPSOCKET_CONABRT: 00169 printf("-----TCPSocket: Connection aborted.\n"); 00170 goto error; 00171 case TCPSOCKET_CONRST: 00172 printf("-----TCPSocket: Connection reset.\n"); 00173 goto error; 00174 case TCPSOCKET_CONTIMEOUT: 00175 printf("-----TCPSocket: Connection timed out.\n"); 00176 goto error; 00177 case TCPSOCKET_DISCONNECTED: 00178 printf("-----TCPSocket: Connection disconnected.\n"); 00179 error: 00180 readyToReturn = true; 00181 errorCode = ev; 00182 positiveResponse = false; 00183 break; 00184 case TCPSOCKET_CONNECTED: 00185 if (DEBUG) printf("-----TCPSocket: Connected.\r\n"); 00186 sendNextChunk(); 00187 break; 00188 case TCPSOCKET_READABLE: 00189 if (DEBUG) printf("-----TCPSocket: Readable.\r\n"); 00190 getResponse(); 00191 break; 00192 case TCPSOCKET_WRITEABLE: 00193 if (DEBUG) printf("-----TCPSOCKET: Writeable.\r\n"); 00194 if (writing_position < SENDING_BUFFER_SIZE) { 00195 if (!sentHeaders) { 00196 sendHeaders(); 00197 } else if (!sentParameters) { 00198 sendParameters(); 00199 } else if (!sentImageData) { 00200 sendImageData(); 00201 } else if (!sentFooter) { 00202 sendFooter(); 00203 } 00204 } 00205 if (writing_position > 0) sendNextChunk(); 00206 } 00207 } 00208 00209 void TwitPic::sendHeaders() { 00210 char* positionPointer; 00211 char imgSizeAsString[25]; 00212 int neededSize = 0; 00213 int availableSize = 0; 00214 00215 if (TRACE) printf("-----------------------TRACE: sendHeaders\n"); 00216 00217 sprintf(imgSizeAsString,"%i",preCalcedContentLength + +strlen(twitterMessage) + imgSize); 00218 00219 if (post) { 00220 neededSize = sizeof(TWITPIC_UPLOAD_AND_POST_API_URL) -1; 00221 } else { 00222 neededSize = sizeof(TWITPIC_UPLOAD_API_URL)-1; 00223 } 00224 neededSize += sizeof("POST ") -1 + 00225 sizeof(" HTTP/1.0\r\n")-1 + 00226 sizeof("Content-Type: multipart/form-data; boundary=")-1 + 00227 sizeof(BOUNDARY)-1 + 00228 sizeof("\r\nContent-Length: ") - 1 + 00229 strlen(imgSizeAsString) + 00230 sizeof("\r\nExpect: 100-continue") -1 + 00231 sizeof("\r\nHost: api.twitpic.com") - 1 + 00232 sizeof("\r\n\r\n") - 1; 00233 00234 availableSize = SENDING_BUFFER_SIZE - writing_position; 00235 00236 00237 //for this guy, only add to sendBuf if you can add everything 00238 if (availableSize < neededSize) return; 00239 00240 positionPointer = sendBuf; 00241 positionPointer += writing_position; 00242 strcpy(positionPointer, "POST "); 00243 positionPointer += 5; 00244 if (post) { 00245 strcpy(positionPointer, TWITPIC_UPLOAD_AND_POST_API_URL); 00246 positionPointer += sizeof(TWITPIC_UPLOAD_AND_POST_API_URL)-1; 00247 } else { 00248 strcpy(positionPointer, TWITPIC_UPLOAD_API_URL); 00249 positionPointer += sizeof(TWITPIC_UPLOAD_API_URL)-1; 00250 } 00251 strcpy(positionPointer, " HTTP/1.1\r\n"); 00252 positionPointer += 11; 00253 strcpy(positionPointer, "Host: api.twitpic.com\r\n"); 00254 positionPointer+= sizeof("Host: api.twitpic.com\r\n")-1; 00255 strcpy(positionPointer, "Content-Length: "); 00256 positionPointer += sizeof("Content-Length: ") - 1; 00257 strcpy(positionPointer, imgSizeAsString); 00258 positionPointer += strlen(imgSizeAsString); 00259 strcpy(positionPointer,"\r\nExpect: 100-continue"); 00260 positionPointer+=sizeof("\r\nExpect: 100-continue")-1; 00261 strcpy(positionPointer, "\r\nContent-Type: multipart/form-data; boundary="); 00262 positionPointer += sizeof("\r\nContent-Type: multipart/form-data; boundary=")-1; 00263 strcpy(positionPointer, BOUNDARY); 00264 positionPointer += sizeof(BOUNDARY)-1; 00265 strcpy(positionPointer, "\r\n\r\n"); 00266 positionPointer += 4; 00267 00268 writing_position += neededSize; 00269 if (DEBUG) printf("Wrote headers to buffer. Size = %i\n. Image size reported: %s\n",neededSize, imgSizeAsString); 00270 sentHeaders = true; 00271 } 00272 00273 void TwitPic::sendParameters() { 00274 char* positionPointer; 00275 int neededSize = 0; 00276 int availableSize = 0; 00277 int actualsize = 0; 00278 char headerline[] = "Content-Disposition: form-data; name=\""; 00279 00280 if (TRACE) printf("-----------------------TRACE: sendParameters\n"); 00281 neededSize = 7 * (sizeof(HEADER)-1) + 00282 24* (sizeof("\r\n")-1) + 00283 6 * (sizeof(headerline) - 1) + 00284 sizeof("key") + 00285 sizeof("consumer_token") + 00286 sizeof("consumer_secret") + 00287 sizeof("oauth_token") + 00288 sizeof("oauth_secret") + 00289 sizeof("message") + 00290 strlen(m_twitpic_api_key) + 00291 strlen(m_consumer_key) + 00292 strlen(m_consumer_secret) + 00293 strlen(m_access_token) + 00294 strlen(m_access_token_secret) + 00295 strlen(twitterMessage) + 00296 sizeof("\r\nContent-Disposition: form-data; name=\"media\"; filename=\"image.jpg\"\r\n")-1 + 00297 sizeof("Content-Type: image/jpeg\r\n")-1 + 00298 sizeof("Content-Transfer-Encoding: binary\r\n\r\n")-1; 00299 00300 00301 availableSize = SENDING_BUFFER_SIZE - writing_position; 00302 00303 00304 //for this guy, only add to sendBuf if you can add everything 00305 if (availableSize < neededSize) return; 00306 00307 positionPointer = sendBuf; 00308 positionPointer+=writing_position; 00309 00310 //API Key 00311 strcpy(positionPointer, HEADER); 00312 positionPointer += sizeof(HEADER)-1; 00313 actualsize += sizeof(HEADER) -1; 00314 strcpy(positionPointer, "\r\n"); 00315 positionPointer += 2; 00316 actualsize += 2; 00317 00318 strcpy(positionPointer, headerline); 00319 positionPointer += strlen(headerline); 00320 actualsize += strlen(headerline); 00321 strcpy(positionPointer, "key\"\r\n\r\n"); 00322 positionPointer += sizeof("key\"\r\n\r\n")-1; 00323 actualsize += sizeof("key\"\r\n\r\n")-1; 00324 strcpy(positionPointer, m_twitpic_api_key); 00325 positionPointer += strlen(m_twitpic_api_key); 00326 actualsize +=strlen(m_twitpic_api_key); 00327 strcpy(positionPointer, "\r\n"); 00328 positionPointer+=2; 00329 actualsize +=2; 00330 //Consumer Key 00331 strcpy(positionPointer, HEADER); 00332 positionPointer += sizeof(HEADER)-1; 00333 actualsize += sizeof(HEADER) -1; 00334 strcpy(positionPointer, "\r\n"); 00335 positionPointer += 2; 00336 actualsize += 2; 00337 00338 strcpy(positionPointer, headerline); 00339 positionPointer += strlen(headerline); 00340 actualsize += strlen(headerline); 00341 strcpy(positionPointer, "consumer_token\"\r\n\r\n"); 00342 positionPointer += sizeof("consumer_token\"\r\n\r\n")-1; 00343 actualsize += sizeof("consumer_token\"\r\n\r\n")-1; 00344 strcpy(positionPointer, m_consumer_key); 00345 positionPointer += strlen(m_consumer_key); 00346 actualsize += strlen(m_consumer_key); 00347 strcpy(positionPointer, "\r\n"); 00348 positionPointer+=2; 00349 actualsize+=2; 00350 00351 //Consumer Secret 00352 strcpy(positionPointer, HEADER); 00353 positionPointer += sizeof(HEADER)-1; 00354 actualsize += sizeof(HEADER) -1; 00355 strcpy(positionPointer, "\r\n"); 00356 positionPointer += 2; 00357 actualsize += 2; 00358 00359 strcpy(positionPointer, headerline); 00360 positionPointer += strlen(headerline); 00361 actualsize += strlen(headerline); 00362 strcpy(positionPointer, "consumer_secret\"\r\n\r\n"); 00363 positionPointer += sizeof("consumer_secret\"\r\n\r\n")-1; 00364 actualsize +=sizeof("consumer_secret\"\r\n\r\n")-1; 00365 strcpy(positionPointer, m_consumer_secret); 00366 positionPointer += strlen(m_consumer_secret); 00367 actualsize += strlen(m_consumer_secret); 00368 strcpy(positionPointer, "\r\n"); 00369 positionPointer+=2; 00370 actualsize +=2; 00371 00372 //OAuth Token 00373 strcpy(positionPointer, HEADER); 00374 positionPointer += sizeof(HEADER)-1; 00375 actualsize += sizeof(HEADER) -1; 00376 strcpy(positionPointer, "\r\n"); 00377 positionPointer += 2; 00378 actualsize += 2; 00379 00380 strcpy(positionPointer, headerline); 00381 positionPointer += strlen(headerline); 00382 actualsize += strlen(headerline); 00383 strcpy(positionPointer, "oauth_token\"\r\n\r\n"); 00384 positionPointer += sizeof("oauth_token\"\r\n\r\n")-1; 00385 actualsize += sizeof("oauth_token\"\r\n\r\n")-1; 00386 strcpy(positionPointer, m_access_token); 00387 positionPointer += strlen(m_access_token); 00388 actualsize += strlen(m_access_token); 00389 strcpy(positionPointer, "\r\n"); 00390 positionPointer+=2; 00391 actualsize += 2; 00392 00393 //OAuth Secret 00394 strcpy(positionPointer, HEADER); 00395 positionPointer += sizeof(HEADER)-1; 00396 actualsize += sizeof(HEADER) -1; 00397 strcpy(positionPointer, "\r\n"); 00398 positionPointer += 2; 00399 actualsize += 2; 00400 00401 strcpy(positionPointer, headerline); 00402 positionPointer += strlen(headerline); 00403 actualsize += strlen(headerline); 00404 strcpy(positionPointer, "oauth_secret\"\r\n\r\n"); 00405 positionPointer += sizeof("oauth_secret\"\r\n\r\n")-1; 00406 actualsize += sizeof("oauth_secret\"\r\n\r\n")-1; 00407 strcpy(positionPointer, m_access_token_secret); 00408 positionPointer += strlen(m_access_token_secret); 00409 actualsize += strlen(m_access_token_secret); 00410 strcpy(positionPointer, "\r\n"); 00411 positionPointer+=2; 00412 actualsize +=2; 00413 00414 //Twitter Message 00415 strcpy(positionPointer, HEADER); 00416 positionPointer += sizeof(HEADER)-1; 00417 actualsize += sizeof(HEADER) -1; 00418 strcpy(positionPointer, "\r\n"); 00419 positionPointer += 2; 00420 actualsize += 2; 00421 00422 strcpy(positionPointer, headerline); 00423 positionPointer += strlen(headerline); 00424 actualsize += strlen(headerline); 00425 strcpy(positionPointer, "message\"\r\n\r\n"); 00426 positionPointer += sizeof("message\"\r\n\r\n")-1; 00427 actualsize += sizeof("message\"\r\n\r\n")-1; 00428 strcpy(positionPointer, twitterMessage); 00429 positionPointer += strlen(twitterMessage); 00430 actualsize += strlen(twitterMessage); 00431 strcpy(positionPointer, "\r\n"); 00432 positionPointer+=2; 00433 actualsize += 2; 00434 00435 strcpy(positionPointer,HEADER); 00436 positionPointer += sizeof(HEADER)-1; 00437 actualsize += sizeof(HEADER)-1; 00438 strcpy(positionPointer,"\r\nContent-Disposition: form-data; name=\"media\"; filename=\"image.jpg\"\r\n"); 00439 positionPointer += sizeof("\r\nContent-Disposition: form-data; name=\"media\"; filename=\"image.jpg\"\r\n")-1; 00440 actualsize += sizeof("\r\nContent-Disposition: form-data; name=\"media\"; filename=\"image.jpg\"\r\n")-1; 00441 strcpy(positionPointer,"Content-Type: image/jpeg\r\n"); 00442 positionPointer += sizeof("Content-Type: image/jpeg\r\n")-1; 00443 actualsize += sizeof("Content-Type: image/jpeg\r\n")-1; 00444 strcpy(positionPointer,"Content-Transfer-Encoding: binary\r\n\r\n"); 00445 positionPointer += sizeof("Content-Transfer-Encoding: binary\r\n\r\n")-1; 00446 actualsize+= sizeof("Content-Transfer-Encoding: binary\r\n\r\n")-1; 00447 00448 if (actualsize != neededSize) printf("ERROR in parameters: Calculated size: %i. Actual size: %i.\n", neededSize,actualsize); 00449 writing_position += actualsize; 00450 if (DEBUG) printf("Wrote parameters to buffer.\n"); 00451 sentParameters = true; 00452 00453 } 00454 void TwitPic::sendImageData() { 00455 int availableSize; 00456 int amountRead=0; 00457 char* positionPointer; 00458 00459 if (TRACE) printf("-----------------------TRACE: sendImageData\n"); 00460 00461 if (writing_position > 0) return; 00462 //fseek(imgFile,-2000,SEEK_END); 00463 positionPointer = sendBuf; 00464 positionPointer += writing_position; 00465 availableSize = SENDING_BUFFER_SIZE - writing_position; 00466 amountRead = fread(positionPointer, 1, availableSize, imgFile); 00467 writing_position += amountRead; 00468 if (DEBUG) printf("Wrote %i bytes of image to buffer.\n",amountRead); 00469 if (feof(imgFile)) { 00470 if (DEBUG) printf("Finished writing file to buffer.\n"); 00471 sentImageData = true; 00472 } 00473 } 00474 void TwitPic::sendFooter() { 00475 int availableSize; 00476 int neededSize; 00477 char* positionPointer; 00478 00479 if (TRACE) printf("-----------------------TRACE: sendFooter\n"); 00480 00481 availableSize = SENDING_BUFFER_SIZE - writing_position; 00482 neededSize = sizeof("\r\n")-1 + 00483 sizeof(FOOTER) - 1 + 00484 sizeof("\r\n") - 1; 00485 if (availableSize < neededSize) return; 00486 00487 positionPointer = sendBuf; 00488 positionPointer += writing_position; 00489 strcpy(positionPointer,"\r\n"); 00490 positionPointer+=2; 00491 strcpy(positionPointer, FOOTER); 00492 positionPointer+=sizeof(FOOTER)-1; 00493 strcpy(positionPointer,"\r\n"); 00494 positionPointer+=2; 00495 00496 writing_position+=neededSize; 00497 if (DEBUG) printf("Wrote footer to buffer.\n"); 00498 sentFooter=true; 00499 } 00500 void TwitPic::sendNextChunk() { 00501 int amountToSend; 00502 int amountSent; 00503 char* bufPointer; 00504 if (TRACE) printf("-----------------------TRACE: sendNextChunk\n"); 00505 //TODO: try both ways of doint this: looped and not. 00506 do { 00507 if (writing_position == 0) { 00508 if (!sentHeaders) { 00509 sendHeaders(); 00510 } else if (!sentParameters) { 00511 sendParameters(); 00512 } else if (!sentImageData) { 00513 sendImageData(); 00514 } else if (!sentFooter) { 00515 sendFooter(); 00516 } 00517 } 00518 amountToSend = MIN(writing_position,SENDING_CHUNK_SIZE); 00519 if (sentFooter && amountToSend == 0) { 00520 finishedSending = true; 00521 //getResponse(); 00522 } 00523 00524 amountSent = socket.send(sendBuf, amountToSend); 00525 totalSentData += amountSent; 00526 00527 if (DEBUG) printf("---Total sent data: %i bytes\n",totalSentData); 00528 00529 bufPointer = sendBuf + amountSent; 00530 memmove((void*)sendBuf, (void*)bufPointer, writing_position - amountSent); 00531 writing_position -= amountSent; 00532 } while (!finishedSending && amountSent == amountToSend); //if sent less than intended, stop sending until WRITEABLE. 00533 } 00534 void TwitPic::getResponse() { 00535 int amountReceived; 00536 char* okSpot; 00537 00538 if (TRACE) printf("-----------------------TRACE: getResponse\n"); 00539 if (DEBUG) printf("Checking for response\n"); 00540 amountReceived = socket.recv(recvBuf, RECEIVING_BUFFER_SIZE-1); 00541 recvBuf[amountReceived]='\0'; 00542 if (amountReceived > 0 && DEBUG) printf("Received response: %s\n",recvBuf); 00543 00544 okSpot = strstr(recvBuf,"200 OK"); 00545 if (okSpot != NULL) { 00546 positiveResponse = true; 00547 readyToReturn = true; 00548 } else if (finishedSending && amountReceived > 0) { 00549 positiveResponse = false; 00550 readyToReturn = true; 00551 } 00552 } 00553 00554 void TwitPic::flushResponse() { 00555 //no longer needed 00556 }
Generated on Sat Jul 16 2022 03:36:23 by 1.7.2