2 * This file is part of sharing-plugin-template
4 * Copyright (C) 2008-2009 Nokia Corporation. All rights reserved.
6 * This maemo code example is licensed under a MIT-style license,
7 * that can be found in the file called "COPYING" in the root
16 #include <libxml/parser.h>
17 #include <libxml/xpath.h>
18 #include <curl/curl.h>
21 #include "libsharing/sharing-tag.h"
22 #include "libsharing/sharing-service-option.h"
26 static size_t getUrlContentWriteFunction(void *ptr, size_t size, size_t nmemb, void *data);
27 std::string getUrlContent(const char* url,const char* token);
28 std::string getXmlElementValueByXPath(xmlDocPtr xmlDoc, const char* xmlXPath);
29 static gchar* createTagsStr (const GSList* tags);
31 yandexGetSessionKeyResult yandexGetSessionKey(char** key, char** request_id) {
32 yandexGetSessionKeyResult ret = YANDEX_GET_SESSION_KEY_FAILED;
33 std::string getSessionKeyRequestBody = getUrlContent("http://auth.mobile.yandex.ru/yamrsa/key/",NULL);
34 if (!getSessionKeyRequestBody.empty()) {
35 xmlDocPtr xmlDoc = NULL;
36 xmlDoc = xmlReadMemory(getSessionKeyRequestBody.c_str(), (int) getSessionKeyRequestBody.length(), "yandexGetSessionKey.xml", NULL, 0);
38 std::string str_key = getXmlElementValueByXPath(xmlDoc, "/response/key");
39 std::string str_request_id = getXmlElementValueByXPath(xmlDoc, "/response/request_id");
40 if (!str_key.empty() && !str_request_id.empty()) {
41 ret = YANDEX_GET_SESSION_KEY_SUCCESS;
42 *key = (char*) malloc(str_key.length()+1);
43 if (*key) strcpy(*key, str_key.c_str());
44 *request_id = (char*) malloc(str_request_id.length()+1);
45 if (*request_id) strcpy(*request_id, str_request_id.c_str());
53 yandexGetAuthTokenResult yandexGetAuthToken(const char* request_id, const char* key, const char* username, const char* password, char** token) {
54 yandexGetAuthTokenResult ret = YANDEX_GET_AUTH_TOKEN_FAILED;
56 /* Build crypted base64 encoded credentials string */
57 CCryptoProviderRSA encrypter;
58 encrypter.ImportPublicKey(key);
59 std::string credentials("<credentials login=\"");
60 credentials += username;
61 credentials += "\" password=\"";
62 credentials += password;
63 credentials += "\"/>";
64 char crypted_credentials[MAX_CRYPT_BITS / sizeof(char)] = "\0";
65 size_t crypted_credentials_length = 0;
66 encrypter.Encrypt(credentials.c_str(), credentials.size(), crypted_credentials, crypted_credentials_length);
67 std::string b64_crypted_credentials = base64_encode((unsigned char *)crypted_credentials, crypted_credentials_length);
73 struct curl_httppost *formpost = NULL;
74 struct curl_httppost *lastptr = NULL;
75 struct curl_slist *headerlist=NULL;
76 static const char expectHeader[] = "Expect:";
77 curl_formadd(&formpost,
79 CURLFORM_COPYNAME, "request_id",
80 CURLFORM_COPYCONTENTS, request_id,
82 curl_formadd(&formpost,
84 CURLFORM_COPYNAME, "credentials",
85 CURLFORM_COPYCONTENTS, b64_crypted_credentials.c_str(),
87 curl = curl_easy_init();
89 headerlist = curl_slist_append(headerlist, expectHeader);
90 curl_easy_setopt(curl, CURLOPT_URL, "http://auth.mobile.yandex.ru/yamrsa/token/");
91 curl_easy_setopt(curl, CURLOPT_USERAGENT, PLUGIN_USER_AGENT);
92 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
93 curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
94 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, getUrlContentWriteFunction);
95 curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&body);
96 res = curl_easy_perform(curl);
97 curl_easy_cleanup(curl);
98 curl_formfree(formpost);
99 curl_slist_free_all (headerlist);
100 if (CURLE_OK == res && !body.empty()) {
101 std::string str_token;
102 xmlDocPtr xmlDoc = NULL;
103 xmlDoc = xmlReadMemory(body.c_str(), body.length(), "yandexGetAuthToken.xml", NULL, 0);
104 if (xmlDoc != NULL) {
105 str_token = getXmlElementValueByXPath(xmlDoc,"/response/token");
106 if (str_token.empty()) ret = YANDEX_GET_AUTH_TOKEN_INVALID_USER;
108 ret = YANDEX_GET_AUTH_TOKEN_SUCCESS;
109 *token = (char*) malloc(str_token.length()+1);
110 if (*token) strcpy(*token, str_token.c_str());
119 int curlProgressCallback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow) {
120 SharingTransfer* transfer = (SharingTransfer*) clientp;
121 gdouble progress = 0;
122 if (ultotal > 0) progress = ulnow / ultotal;
123 if (transfer) sharing_transfer_set_progress(transfer,progress);
127 yandexSendPhotoResult yandexSendPhoto(const char* token, const SharingEntryMedia* photo, SharingTransfer* transfer, yandexPhotoOptions options) {
128 yandexSendPhotoResult ret = YANDEX_SEND_PHOTO_FAILED;
130 const gchar* filepath = sharing_entry_media_get_localpath(photo);
131 gchar* filename = sharing_entry_media_get_filename(photo);
132 gchar* title = sharing_entry_media_get_title(photo);
133 gchar* contentType = sharing_entry_media_get_mime(photo);
134 gchar* tags = createTagsStr(sharing_entry_media_get_tags (photo));
135 std::string access_type = "public";
136 if (options.access == YANDEX_PHOTO_ACCESS_FRIENDS) access_type = "friends";
137 else if (options.access == YANDEX_PHOTO_ACCESS_PRIVATE) access_type = "private";
138 std::string publish = "0";
139 if (options.publish == YANDEX_PHOTO_PUBLISH) publish = "1";
141 struct stat fileStat;
142 if (stat(filepath,&fileStat) == 0) {
146 struct curl_httppost *formpost = NULL;
147 struct curl_httppost *lastptr = NULL;
148 struct curl_slist *headerlist=NULL;
149 static const char expectHeader[] = "Expect:";
150 curl_formadd(&formpost,
152 CURLFORM_COPYNAME, "image",
153 CURLFORM_FILE, filepath,
154 CURLFORM_FILENAME, filename,
155 CURLFORM_CONTENTTYPE, contentType,
158 curl_formadd(&formpost,
160 CURLFORM_COPYNAME, "album",
161 CURLFORM_COPYCONTENTS, options.album,
164 curl_formadd(&formpost,
166 CURLFORM_COPYNAME, "access_type",
167 CURLFORM_COPYCONTENTS, access_type.c_str(),
170 curl_formadd(&formpost,
172 CURLFORM_COPYNAME, "title",
173 CURLFORM_COPYCONTENTS, title,
176 curl_formadd(&formpost,
178 CURLFORM_COPYNAME, "tags",
179 CURLFORM_COPYCONTENTS, tags,
181 curl_formadd(&formpost,
183 CURLFORM_COPYNAME, "pub_channel",
184 CURLFORM_COPYCONTENTS, PUB_CHANNEL,
186 curl_formadd(&formpost,
188 CURLFORM_COPYNAME, "app_platform",
189 CURLFORM_COPYCONTENTS, APP_PLATFORM,
191 curl_formadd(&formpost,
193 CURLFORM_COPYNAME, "app_version",
194 CURLFORM_COPYCONTENTS, APP_VERSION,
196 curl_formadd(&formpost,
198 CURLFORM_COPYNAME, "yaru",
199 CURLFORM_COPYCONTENTS, publish.c_str(),
201 curl = curl_easy_init();
203 headerlist = curl_slist_append(headerlist, expectHeader);
204 char authHeader[2048];
205 sprintf(authHeader,"Authorization: FimpToken realm=\"fotki.yandex.ru\", token=\"%s\"",token);
206 headerlist = curl_slist_append(headerlist, authHeader);
207 curl_easy_setopt(curl, CURLOPT_URL, "http://api-fotki.yandex.ru/post/");
208 curl_easy_setopt(curl, CURLOPT_USERAGENT, PLUGIN_USER_AGENT);
209 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
210 curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
211 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, getUrlContentWriteFunction);
212 curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&body);
213 curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
214 curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, curlProgressCallback);
215 curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, transfer);
216 res = curl_easy_perform(curl);
217 curl_easy_cleanup(curl);
218 if (CURLE_OK == res) ret = YANDEX_SEND_PHOTO_SUCCESS;
219 else ret = YANDEX_SEND_PHOTO_FILE_INVALID_TOKEN; // TODO: check other errors too
221 curl_formfree(formpost);
222 curl_slist_free_all (headerlist);
223 } else ret = YANDEX_SEND_PHOTO_FILE_NOT_FOUND;
225 if (tags) g_free(tags);
226 if (contentType) g_free(contentType);
227 if (title) g_free(title);
228 if (filename) g_free(filename);
233 yandexGetAlbumsListResult yandexGetAlbumsList(const char* token, const char* username, GSList** albumOptionValues) {
234 yandexGetAlbumsListResult ret = YANDEX_GET_ALBUM_LIST_FAILED;
236 std::string albumsListURL("http://api-fotki.yandex.ru/api/users/");
237 albumsListURL += username; albumsListURL += "/albums/";
238 std::string body = getUrlContent(albumsListURL.c_str(),token);
240 xmlDocPtr xmlDoc = NULL;
241 xmlDoc = xmlReadMemory(body.c_str(), body.length(), "albums.xml", NULL, 0);
242 if (xmlDoc != NULL) {
243 xmlNodePtr feed = xmlDoc->children;
244 if (feed && (xmlStrEqual(feed->name, (const xmlChar*)"feed"))) {
245 xmlNodePtr entry = feed->children;
247 if (xmlStrEqual(entry->name,(const xmlChar*)"entry")) {
248 xmlChar* path = xmlGetNodePath(entry);
249 if (path) free(path);
250 xmlNodePtr id = NULL;
251 xmlNodePtr title = NULL;
252 xmlNodePtr summary = NULL;
253 xmlNodePtr isProtected = NULL;
254 xmlNodePtr entryChildren = entry->children;
255 while (entryChildren) {
256 if (xmlStrEqual(entryChildren->name,(const xmlChar*)"id")) id = entryChildren;
257 else if (xmlStrEqual(entryChildren->name,(const xmlChar*)"title")) title = entryChildren;
258 else if (xmlStrEqual(entryChildren->name,(const xmlChar*)"summary")) summary = entryChildren;
259 else if (xmlStrEqual(entryChildren->name,(const xmlChar*)"protected")) isProtected = entryChildren;
260 entryChildren = entryChildren->next;
263 xmlChar* idStr = xmlNodeGetContent(id);
265 const xmlChar* idStrNum = NULL;
267 for (s=xmlStrlen(idStr);s>0;s--)
268 if (idStr[s] == ':') {
269 idStrNum = idStr+s+1;
272 xmlChar* titleStr = title ? xmlNodeGetContent(title) : NULL;
273 xmlChar* summaryStr = summary ? xmlNodeGetContent(summary) : NULL;
274 xmlChar* isProtectedStr = isProtected ? xmlGetProp(isProtected,(const xmlChar*)"value") : NULL;
276 SharingServiceOptionValue* albumValue = sharing_service_option_value_new((const gchar*)idStrNum,titleStr?(const gchar*)titleStr:"Unnamed",summaryStr?(const gchar*)summaryStr:"");
277 *albumOptionValues = g_slist_append(*albumOptionValues,albumValue);
278 ret = YANDEX_GET_ALBUM_LIST_SUCCESS;
280 if (idStr) free(idStr);
281 if (titleStr) free(titleStr);
282 if (summaryStr) free(summaryStr);
283 if (isProtectedStr) free(isProtectedStr);
297 static size_t getUrlContentWriteFunction(void *ptr, size_t size, size_t nmemb, void *data) {
298 std::string* body = (std::string*) data;
299 size_t realsize = size * nmemb;
300 if (body) body->append((const char*)ptr,realsize);
303 std::string getUrlContent(const char* url, const char* token) {
307 struct curl_slist *headerlist = NULL;
308 curl = curl_easy_init();
311 std::string authHeader("Authorization: FimpToken realm=\"fotki.yandex.ru\", token=\"");
312 authHeader += token; authHeader += "\"";
313 headerlist = curl_slist_append(headerlist, authHeader.c_str());
315 curl_easy_setopt(curl, CURLOPT_URL, url);
316 curl_easy_setopt(curl, CURLOPT_USERAGENT, PLUGIN_USER_AGENT);
317 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, getUrlContentWriteFunction);
318 curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&body);
319 res = curl_easy_perform(curl);
320 curl_easy_cleanup(curl);
321 if (headerlist) curl_slist_free_all (headerlist);
322 if (CURLE_OK != res) body.clear();
327 std::string getXmlElementValueByXPath(xmlDocPtr xmlDoc, const char* xmlXPath) {
329 if (xmlDoc != NULL) {
330 xmlXPathContextPtr context = xmlXPathNewContext(xmlDoc);
331 if (context != NULL) {
332 xmlXPathObjectPtr result = xmlXPathEvalExpression((const xmlChar*)xmlXPath, context);
333 if (result != NULL) {
334 if(!xmlXPathNodeSetIsEmpty(result->nodesetval)) {
335 content = (char*) xmlNodeGetContent(result->nodesetval->nodeTab[0]);
337 xmlXPathFreeObject(result);
339 xmlXPathFreeContext(context);
345 static gchar* createTagsStr (const GSList* tags) {
347 for (const GSList* p = tags; p != NULL; p = g_slist_next (p)) {
348 SharingTag* tag = (SharingTag*)(p->data);
349 SharingTagType type = sharing_tag_get_type(tag);
350 if (SHARING_TAG_SHARE != type) continue;
351 const gchar* tmp = sharing_tag_get_word (tag);
353 gchar* new_ret = NULL;
355 new_ret = g_strdup_printf ("%s, %s", ret, tmp);
356 g_free (ret); /* old return is freed */
358 new_ret = g_strdup (tmp);