//------------------------------------------------------------- string API::buildAPICall( string method, map<string,string> args, Format format, bool bSigned ){ string call = "/services/rest/?method=" + method; switch ( format ) { case FLICKR_XML: args["format"] = "rest"; break; case FLICKR_JSON: args["format"] = "json"; args["nojsoncallback"] = "1"; break; case FLICKR_JSONP: args["format"] = "json"; break; } map<string,string>::iterator it = args.begin(); for ( it; it != args.end(); ++it ){ call += "&" + it->first + "=" + it->second; } if ( bSigned ){ args["method"] = method; call += "&api_sig=" + apiSig( args ); } return call; }
int FlickrPrivate::request(const FlickrMethod &method, const FlickrRequest &request, bool get, void* userData) { QMap<QString,QString> map = method.args; map.insert("method", method.method); map.insert("api_key",_apiKey); if(!_token.isEmpty()) { map.insert("auth_token", _token); } QMapIterator<QString, QString> i(map); QStringList keyList; while(i.hasNext()) { i.next(); keyList << i.key(); } qSort(keyList.begin(), keyList.end()); QString apiSig(_apiSecret); QUrl url = QUrl("https://www.flickr.com/services/rest/"); QUrlQuery urlQuery; for(int i = 0; i < keyList.size(); ++i) { apiSig.append(keyList.at(i) + map.value(keyList.at(i))); urlQuery.addQueryItem(keyList.at(i), map.value(keyList.at(i))); } urlQuery.addQueryItem("api_sig", md5(apiSig)); url.setQuery(urlQuery); _requestCounter++; RequestData requestData; requestData.request = request.requests; requestData.userData = userData; requestData.requestId = _requestCounter; QNetworkReply *reply; if(!get) { reply = _networkAccessManager->post(QNetworkRequest(QUrl("https://www.flickr.com/services/rest/")), url.toEncoded(QUrl::RemoveFragment)); } else { reply = _networkAccessManager->get(QNetworkRequest(url)); } requestDataMap.insert(reply,requestData); return requestData.requestId; }
int FlickrPrivate::upload(const FlickrPhoto &photo, const FlickrRequest &request, void* userData) { QByteArray boundary = generateBoundary(); QByteArray payload; QDataStream dataStream(&payload, QIODevice::WriteOnly); QMap<QString,QString> map = photo.args; map.insert("api_key", _apiKey); if(!_token.isEmpty()) { map.insert("auth_token", _token); } bool uploading = photo.photoId.isEmpty(); if(!uploading){ map.insert("photo_id", photo.photoId); } QMapIterator<QString, QString> i(map); QStringList keyList; while(i.hasNext()) { i.next(); keyList << i.key(); } qSort(keyList.begin(), keyList.end()); QString apiSig(_apiSecret); for(int i = 0; i < keyList.size(); ++i) { apiSig.append(keyList.at(i) + map.value(keyList.at(i))); QByteArray field = constructField(keyList.at(i),map.value(keyList.at(i)),boundary); dataStream.writeRawData(field.data(), field.length()); } apiSig = md5(apiSig); QByteArray sigField = constructField("api_sig", apiSig, boundary); dataStream.writeRawData(sigField.data(), sigField.length()); QByteArray fileField = constructField("photo", "", boundary, photo.file); dataStream.writeRawData(fileField.data(), fileField.length()); QFile file(photo.file); file.open(QIODevice::ReadOnly); while(!file.atEnd()) { QByteArray line = file.readLine(); dataStream.writeRawData(line.data(),line.length()); } file.close(); QByteArray endField; endField.append("\r\n--"); endField.append(boundary); endField.append("--\r\n\r\n"); dataStream.writeRawData(endField.data(), endField.length()); QString urlTmp("http://api.flickr.com/services/"); urlTmp.append((uploading)?"upload/":"replace/"); QNetworkRequest uploadRequest(urlTmp); uploadRequest.setRawHeader("Content-Type","multipart/form-data; boundary="+boundary); uploadRequest.setRawHeader("Host","ww.api.flickr.com"); _requestCounter++; RequestData requestData; requestData.request = request.requests; requestData.userData = userData; requestData.requestId = _requestCounter; QNetworkReply *reply = _networkAccessManager->post(uploadRequest,payload); connect(reply,SIGNAL(uploadProgress(qint64, qint64)), this, SLOT(uploadProgress(qint64, qint64))); requestDataMap.insert(reply,requestData); return requestData.requestId; }
//------------------------------------------------------------- string API::doUpload( string image ){ if ( !bAuthenticated ){ ofLogWarning( "Not authenticated! Please call authenticate() with proper api key and secret" ); return ""; } else if ( currentPerms != FLICKR_WRITE ){ ofLogWarning( "You do not have proper permissions to upload! Please call authenticate() with permissions of ofxFlickr::FLICKR_WRITE" ); return ""; } map<string,string> args; args["api_key"] = api_key; args["auth_token"] = auth_token; string result; FilePartSource * fps = new FilePartSource(image, "image/jpeg"); try { // prepare session const URI uri( "https://" + api_base ); HTTPSClientSession session( uri.getHost(), uri.getPort() ); HTTPRequest req(HTTPRequest::HTTP_POST, "/services/upload/", HTTPMessage::HTTP_1_0); req.setContentType("multipart/form-data"); // setup form HTMLForm form; form.set("api_key", api_key); form.set("auth_token", auth_token); form.set("api_sig", apiSig( args )); form.setEncoding(HTMLForm::ENCODING_MULTIPART); form.addPart("photo", fps); form.prepareSubmit(req); std::ostringstream oszMessage; form.write(oszMessage); std::string szMessage = oszMessage.str(); req.setContentLength((int) szMessage.length() ); //session.setKeepAlive(true); // send form ostream & out = session.sendRequest(req) << szMessage; // get response HTTPResponse res; cout << res.getStatus() << " " << res.getReason() << endl; // print response istream &is = session.receiveResponse(res); StreamCopier::copyToString(is, result); } catch (Exception &ex) { cerr << "error? " + ex.displayText() <<endl; } string photoid; ofxXmlSettings xml; xml.loadFromBuffer(result); xml.pushTag("rsp");{ photoid = xml.getValue("photoid", ""); }; xml.popTag(); return photoid; }
//-------------------------------------------------------------- bool API::getAuthToken( Permissions perms ){ // build call map<string,string> args; args["api_key"] = api_key; // get frob string result = makeAPICall( "flickr.auth.getFrob", args, FLICKR_XML, true ); ofxXmlSettings xml; xml.loadFromBuffer(result); xml.pushTag("rsp");{ frob = xml.getValue("frob", ""); }; xml.popTag(); // authenticate // %a = API key, %b = perms, %c = frob, %d = api_sig string authURL = auth; ofStringReplace(authURL, "%a", api_key); string perm = "write"; switch (perms) { case FLICKR_WRITE: perm = "write"; break; case FLICKR_READ: perm = "read"; break; case FLICKR_DELETE: perm = "delete"; break; } map<string,string> toEncode; toEncode["api_key"] = api_key; toEncode["perms"] = perm; toEncode["frob"] = frob; ofStringReplace(authURL, "%b", perm); ofStringReplace(authURL, "%c", frob); ofStringReplace(authURL, "%d", apiSig(toEncode)); // this part is weird! ofLaunchBrowser has a tiny bug #ifdef TARGET_OSX string commandStr = "open '"+authURL +"'"; system(commandStr.c_str()); #else cout << authURL; ofLaunchBrowser(authURL); #endif bool bValidToken = false; int numSeconds = 0; int secondsWait = 2; for( numSeconds; numSeconds<30; numSeconds+=secondsWait ){ map<string,string> auth_args; auth_args["api_key"] = api_key; auth_args["frob"] = frob; // get frob string auth_result = makeAPICall( "flickr.auth.getToken", auth_args, FLICKR_XML, true ); xml.loadFromBuffer(auth_result); xml.pushTag("rsp"); { xml.pushTag("auth"); { auth_token = xml.getValue("token", ""); } xml.popTag(); } xml.popTag(); bValidToken = !( auth_token == "" ); if ( bValidToken ) break; numSeconds += secondsWait; ofSleepMillis(1000); } //this is a workaround! bValidToken = true; if ( !bValidToken ){ ofLogError( "OAuth didn't succeed. Maybe you took too long?"); return false; } // save auth token to XML for safe keeping ofxXmlSettings toSave; toSave.addTag("settings"); toSave.pushTag("settings");{ toSave.addValue("token", auth_token); }; toSave.popTag(); toSave.saveFile("flickr.xml"); return true; }