1  /*
2  * Copyright (C) 2008 MP3tunes, LLC
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17 */
18 
19 #ifndef _GNU_SOURCE
20 #define _GNU_SOURCE
21 #endif
22 #include <string.h>
23 #include <stdlib.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 #include <curl/curl.h>
28 #include <libxml/encoding.h>
29 #include <libxml/xmlwriter.h>
30 #include <libxml/xmlreader.h>
31 #include <libxml/xpath.h>
32 #include "locker.h"
33 #include "md5.h"
34 
35 typedef struct {
36     char *data;
37     size_t size;
38     int offset;
39 } chunk_t;
40 
41 typedef struct {
42     CURL *curl;
43     char *url;
44 } request_t;
45 
chunk_init(chunk_t ** chunk)46 void chunk_init(chunk_t** chunk) {
47     chunk_t *c = *chunk = (chunk_t*)malloc(sizeof(chunk_t));
48     c->data = NULL;
49     c->size = 0;
50 }
51 
chunk_set_data(chunk_t * chunk,char * data)52 void chunk_set_data(chunk_t* chunk, char* data) {
53     chunk->data = data;
54     chunk->size = strlen(data);
55 }
56 
chunk_deinit(chunk_t ** chunk)57 void chunk_deinit(chunk_t** chunk) {
58     chunk_t *c = *chunk;
59     free(c->data);
60     free(c);
61 }
62 
63 struct xml_xpath_s {
64     xmlDocPtr document;
65     xmlXPathContextPtr xpath_ctx;
66     xmlNodePtr context;
67 };
68 
69 typedef struct xml_xpath_s xml_xpath_t;
70 
write_chunk_callback(void * ptr,size_t size,size_t nmemb,void * data)71 size_t write_chunk_callback( void *ptr, size_t size, size_t nmemb, void *data ) {
72     size_t realsize = size * nmemb;
73     chunk_t *chunk = (chunk_t *)data;
74     chunk->data = (char *)realloc( chunk->data, chunk->size + realsize + 1 );
75     if( chunk->data != NULL ) {
76         memcpy( &(chunk->data[ chunk->size ]), ptr, realsize );
77         chunk->size += realsize;
78         chunk->data[ chunk->size ] = 0;
79     }
80 
81     return realsize;
82 }
83 
xml_xpath_init(xmlDocPtr document)84 xml_xpath_t* xml_xpath_init(xmlDocPtr document) {
85     xml_xpath_t *result = malloc(sizeof(xml_xpath_t));
86     if (result == NULL)
87         return NULL;
88 
89     result->document = document;
90     result->xpath_ctx = xmlXPathNewContext(result->document);
91     if(result->xpath_ctx == NULL) {
92         xmlFreeDoc(result->document);
93         free(result);
94         return NULL;
95     }
96     result->context = NULL;
97 
98     return result;
99 }
100 
xml_xpath_context_init(xml_xpath_t * xml_xpath,xmlNodePtr node)101 xml_xpath_t* xml_xpath_context_init(xml_xpath_t* xml_xpath, xmlNodePtr node) {
102     xml_xpath_t *result = malloc(sizeof(xml_xpath_t));
103     if (result == NULL)
104         return NULL;
105 
106     result->document = xml_xpath->document;
107     result->xpath_ctx = xmlXPathNewContext(result->document);
108     if(result->xpath_ctx == NULL) {
109         xmlFreeDoc(result->document);
110         free(result);
111         return NULL;
112     }
113     result->xpath_ctx->node = node;
114     result->context = node;
115 
116     return result;
117 }
118 
xml_xpath_deinit(xml_xpath_t * xml_xpath)119 void xml_xpath_deinit(xml_xpath_t* xml_xpath) {
120     xmlXPathFreeContext(xml_xpath->xpath_ctx);
121     if (xml_xpath->context == NULL) {
122         xmlFreeDoc(xml_xpath->document);
123     }
124     free(xml_xpath);
125 }
126 
xml_xpath_query(xml_xpath_t * xml_xpath,const char * xpath_expression)127 xmlXPathObjectPtr xml_xpath_query(xml_xpath_t *xml_xpath, const char* xpath_expression) {
128     xmlXPathObjectPtr xpath_obj;
129 
130     xpath_obj = xmlXPathEvalExpression((xmlChar*)xpath_expression, xml_xpath->xpath_ctx);
131     if (xpath_obj == NULL) {
132         return NULL;
133     }
134     if (xpath_obj->type != XPATH_NODESET) {
135         xmlXPathFreeObject(xpath_obj);
136         return NULL;
137     }
138     return xpath_obj;
139 }
140 
xml_get_text_from_nodeset(xmlNodeSetPtr nodeset)141 char* xml_get_text_from_nodeset(xmlNodeSetPtr nodeset) {
142     xmlNodePtr node;
143     xmlNodePtr child;
144     int total_nodes;
145     char* result = NULL;
146     total_nodes = (nodeset) ? nodeset->nodeNr : 0;
147 
148     if (total_nodes != 1) {
149         return NULL;
150     }
151 
152     if (nodeset->nodeTab[0]->type != XML_ELEMENT_NODE) {
153         return NULL;
154     }
155 
156     node = nodeset->nodeTab[0];
157     child = node->children;
158     while (child && (XML_TEXT_NODE != child->type))
159         child = child->next;
160     if (child && (XML_TEXT_NODE == child->type)) {
161         result = strdup((char*)child->content);
162     }
163     return result;
164 }
165 
xml_xpath_get_string(xml_xpath_t * xml_xpath,const char * xpath_expression)166 static char* xml_xpath_get_string(xml_xpath_t *xml_xpath, const char* xpath_expression) {
167     xmlXPathObjectPtr xpath_obj;
168     char* result = NULL;
169 
170     xpath_obj = xml_xpath_query(xml_xpath, xpath_expression);
171     if (xpath_obj == NULL)
172         return NULL;
173 
174     result = xml_get_text_from_nodeset(xpath_obj->nodesetval);
175 
176     xmlXPathFreeObject(xpath_obj);
177 
178     return result;
179 }
180 
xml_xpath_get_integer(xml_xpath_t * xml_xpath,const char * xpath_expression)181 int xml_xpath_get_integer(xml_xpath_t *xml_xpath, const char* xpath_expression) {
182     int result = 0;
183     char* str = xml_xpath_get_string(xml_xpath, xpath_expression);
184     if (str != NULL) {
185         result = atoi(str);
186     }
187     free(str);
188     return result;
189 }
190 
xml_xpath_get_float(xml_xpath_t * xml_xpath,const char * xpath_expression)191 float xml_xpath_get_float(xml_xpath_t *xml_xpath, const char* xpath_expression) {
192     float result = 0.0;
193     char* str = xml_xpath_get_string(xml_xpath, xpath_expression);
194     if (str != NULL) {
195         result = atof(str);
196     }
197     free(str);
198     return result;
199 }
200 
mp3tunes_locker_init(mp3tunes_locker_object_t ** obj,const char * partner_token)201 int mp3tunes_locker_init( mp3tunes_locker_object_t **obj, const char *partner_token ) {
202     mp3tunes_locker_object_t *o = *obj = (mp3tunes_locker_object_t*)malloc(sizeof(mp3tunes_locker_object_t));
203     memset(o, 0, sizeof(*o));
204 
205     o->partner_token = strdup(partner_token);
206     o->session_id = NULL;
207     o->error_message = NULL;
208 
209     o->server_api = getenv("MP3TUNES_SERVER_API");
210     if(o->server_api == NULL) {
211         o->server_api = strdup(MP3TUNES_SERVER_API_URL);
212     }
213 
214     o->server_content = getenv("MP3TUNES_SERVER_CONTENT");
215     if(o->server_content == NULL) {
216         o->server_content = strdup(MP3TUNES_SERVER_CONTENT_URL);
217     }
218 
219     o->server_login = getenv("MP3TUNES_SERVER_LOGIN");
220     if(o->server_login == NULL) {
221         o->server_login = strdup(MP3TUNES_SERVER_LOGIN_URL);
222     }
223 
224     return TRUE;
225 }
226 
mp3tunes_locker_deinit(mp3tunes_locker_object_t ** obj)227 int mp3tunes_locker_deinit( mp3tunes_locker_object_t **obj ) {
228     mp3tunes_locker_object_t *o = *obj;
229     free(o->partner_token);
230     free(o->session_id);
231     free(o->error_message);
232     free(o);
233     return TRUE;
234 }
235 
mp3tunes_request_init(request_t ** request)236 void mp3tunes_request_init(request_t **request) {
237     request_t *r = *request = malloc(sizeof(request_t));
238     r->curl = curl_easy_init();
239     r->url = NULL;
240 }
241 
mp3tunes_request_deinit(request_t ** request)242 void mp3tunes_request_deinit(request_t **request) {
243     request_t *r = *request;
244     curl_easy_cleanup(r->curl);
245     free(r->url);
246     free(r);
247 }
248 
mp3tunes_locker_api_generate_request_valist(mp3tunes_locker_object_t * obj,int server,const char * path,const char * first_name,va_list argp)249 static request_t* mp3tunes_locker_api_generate_request_valist(mp3tunes_locker_object_t *obj, int server, const char* path, const char* first_name, va_list argp) {
250     request_t *request;
251     char *server_url;
252     char *name, *value;
253     char *encoded_name, *encoded_value;
254 
255     mp3tunes_request_init(&request);
256 
257     switch (server) {
258         case MP3TUNES_SERVER_LOGIN:
259             server_url = obj->server_login;
260             break;
261         case MP3TUNES_SERVER_CONTENT:
262             server_url = obj->server_content;
263             break;
264         case MP3TUNES_SERVER_API:
265             server_url = obj->server_api;
266             break;
267         default:
268             mp3tunes_request_deinit(&request);
269             return NULL;
270             break;
271     }
272 
273     char *url = 0;
274     size_t url_size = asprintf(&url, "http://%s/%s?", server_url, path) +1;
275     name = (char*) first_name;
276     while (name) {
277         char *url_part;
278 
279         value = va_arg(argp, char*);
280 
281         encoded_name = curl_easy_escape(request->curl, name, 0);
282         encoded_value = curl_easy_escape(request->curl, value, 0);
283         size_t url_part_size = asprintf(&url_part, "%s=%s&", encoded_name, encoded_value);
284         curl_free(encoded_name);
285         curl_free(encoded_value);
286 
287 	url = realloc(url, url_size += url_part_size);
288         strcat(url, url_part);
289 
290         name = va_arg(argp, char*);
291     }
292 
293     char *end_url_part = NULL;
294     size_t end_url_part_size = 0;
295     if (server != MP3TUNES_SERVER_LOGIN) {
296         if (obj->session_id != NULL) {
297             if (server == MP3TUNES_SERVER_API) {
298                 end_url_part_size = asprintf(&end_url_part, "output=xml&sid=%s&partner_token=%s", obj->session_id, obj->partner_token);
299             } else {
300                 end_url_part_size = asprintf(&end_url_part, "sid=%s&partner_token=%s", obj->session_id, obj->partner_token);
301             }
302         } else {
303             printf("Failed because of no session id\n");
304             free(url);
305             mp3tunes_request_deinit(&request);
306             return NULL;
307         }
308     } else {
309         end_url_part_size = asprintf(&end_url_part, "output=xml&partner_token=%s", obj->partner_token);
310     }
311     url = realloc(url, url_size += end_url_part_size);
312     strcat(url, end_url_part);
313 
314     request->url = url;
315     return request;
316 
317 }
318 
mp3tunes_locker_api_generate_request(mp3tunes_locker_object_t * obj,int server,const char * path,const char * first_name,...)319 static request_t* mp3tunes_locker_api_generate_request(mp3tunes_locker_object_t *obj, int server, const char* path, const char* first_name, ...) {
320     va_list argp;
321     request_t *request;
322     va_start(argp, first_name);
323     request = mp3tunes_locker_api_generate_request_valist(obj, server, path, first_name, argp);
324     va_end(argp);
325     return request;
326 }
327 
mp3tunes_locker_api_simple_fetch(mp3tunes_locker_object_t * obj,int server,const char * path,const char * first_name,...)328 static xml_xpath_t* mp3tunes_locker_api_simple_fetch(mp3tunes_locker_object_t *obj, int server, const char* path, const char* first_name, ...) {
329     request_t *request;
330     CURLcode res;
331     chunk_t *chunk;
332     va_list argp;
333 
334     chunk_init(&chunk);
335 
336     va_start(argp, first_name);
337 
338     request = mp3tunes_locker_api_generate_request_valist(obj, server, path, first_name, argp);
339 
340     va_end(argp);
341 
342     if (request == NULL) {
343         chunk_deinit(&chunk);
344         return NULL;
345     }
346 
347     curl_easy_setopt( request->curl, CURLOPT_URL, request->url );
348     curl_easy_setopt( request->curl, CURLOPT_WRITEFUNCTION, write_chunk_callback );
349     curl_easy_setopt( request->curl, CURLOPT_WRITEDATA, (void *)chunk );
350     curl_easy_setopt( request->curl, CURLOPT_USERAGENT, "liboboe/1.0" );
351     curl_easy_setopt( request->curl, CURLOPT_NOPROGRESS, 1 );
352 
353     res = curl_easy_perform(request->curl);
354 /*    curl_easy_cleanup(request->curl); */
355     mp3tunes_request_deinit(&request);
356 
357     if (res != CURLE_OK) {
358         chunk_deinit(&chunk);
359         return NULL;
360     }
361 
362     if (chunk->data == NULL) {
363         return NULL;
364     }
365 
366     /*printf("Fetch result:\n%s\n", chunk->data);*/
367 
368     xmlDocPtr document = xmlParseDoc((xmlChar*)chunk->data);
369 
370     chunk_deinit(&chunk);
371 
372     if (document == NULL) {
373         return NULL;
374     }
375 
376     return xml_xpath_init(document);
377 }
378 
mp3tunes_locker_api_post_fetch(mp3tunes_locker_object_t * obj,int server,const char * path,char * post_data)379 static xml_xpath_t* mp3tunes_locker_api_post_fetch(mp3tunes_locker_object_t *obj, int server, const char* path, char* post_data) {
380     request_t *request;
381     CURLcode res;
382     chunk_t *chunk;
383 
384     chunk_init(&chunk);
385 
386     request = mp3tunes_locker_api_generate_request(obj, server, path, NULL);
387     if (request == NULL) {
388         chunk_deinit(&chunk);
389         return NULL;
390     }
391 
392     curl_easy_setopt( request->curl, CURLOPT_URL, request->url );
393     curl_easy_setopt( request->curl, CURLOPT_WRITEFUNCTION, write_chunk_callback );
394     curl_easy_setopt( request->curl, CURLOPT_WRITEDATA, (void *)chunk );
395     curl_easy_setopt( request->curl, CURLOPT_USERAGENT, "liboboe/1.0" );
396     curl_easy_setopt( request->curl, CURLOPT_POSTFIELDS, post_data);
397     curl_easy_setopt( request->curl, CURLOPT_NOPROGRESS, 1 );
398 
399     res = curl_easy_perform(request->curl);
400 /*    curl_easy_cleanup(request->curl); */
401     mp3tunes_request_deinit(&request);
402 
403     if (res != CURLE_OK) {
404         chunk_deinit(&chunk);
405         return NULL;
406     }
407 
408     if (chunk->data == NULL) {
409         return NULL;
410     }
411 
412     printf("Fetch result:\n%s\n", chunk->data);
413 
414     xmlDocPtr document = xmlParseDoc((xmlChar*)chunk->data);
415 
416     chunk_deinit(&chunk);
417 
418     if (document == NULL) {
419         return NULL;
420     }
421 
422     return xml_xpath_init(document);
423 }
424 
mp3tunes_locker_generate_download_url_from_file_key(mp3tunes_locker_object_t * obj,char * file_key)425 char* mp3tunes_locker_generate_download_url_from_file_key(mp3tunes_locker_object_t *obj, char *file_key) {
426     request_t *request;
427     char *path = malloc(256*sizeof(char));
428     char *ret;
429     snprintf(path, 256, "storage/lockerget/%s", file_key);
430     request = mp3tunes_locker_api_generate_request(obj, MP3TUNES_SERVER_CONTENT, path, NULL);
431     ret = request->url; request->url = NULL;
432     free(path);
433     mp3tunes_request_deinit(&request);
434     return ret;
435 }
436 
mp3tunes_locker_generate_download_url_from_file_key_and_bitrate(mp3tunes_locker_object_t * obj,char * file_key,char * bitrate)437 char* mp3tunes_locker_generate_download_url_from_file_key_and_bitrate(mp3tunes_locker_object_t *obj, char *file_key, char* bitrate) {
438     request_t *request;
439     char *path = malloc(256*sizeof(char));
440     char *ret;
441     snprintf(path, 256, "storage/lockerget/%s", file_key);
442     request = mp3tunes_locker_api_generate_request(obj, MP3TUNES_SERVER_CONTENT, path, "bitrate", bitrate, NULL);
443     ret = request->url; request->url = NULL;
444     free(path);
445     mp3tunes_request_deinit(&request);
446     return ret;
447 }
448 
449 
mp3tunes_locker_login(mp3tunes_locker_object_t * obj,const char * username,const char * password)450 int mp3tunes_locker_login(mp3tunes_locker_object_t *obj, const char* username, const char* password) {
451     xml_xpath_t* xml_xpath;
452     char *status, *session_id;
453 
454     xml_xpath = mp3tunes_locker_api_simple_fetch(obj, MP3TUNES_SERVER_LOGIN, "api/v1/login/", "username", username, "password", password, NULL);
455 
456     if (xml_xpath == NULL) {
457         return -2;
458     }
459 
460     status = xml_xpath_get_string(xml_xpath, "/mp3tunes/status");
461 
462     if (status[0] != '1') {
463       /*printf("status is %s\n", status);*/
464         char* error = xml_xpath_get_string(xml_xpath, "/mp3tunes/errorMessage");
465         /*printf("error is %s\n", error);*/
466         obj->error_message = error;
467         free(status);
468         xml_xpath_deinit(xml_xpath);
469         return -1;
470     }
471     free(status);
472 
473     session_id = xml_xpath_get_string(xml_xpath, "/mp3tunes/session_id");
474     obj->username = strdup(username);
475     obj->password = strdup(password);
476     obj->session_id = session_id;
477     xml_xpath_deinit(xml_xpath);
478 
479     return 0;
480 }
481 
mp3tunes_locker_session_valid(mp3tunes_locker_object_t * obj)482 int mp3tunes_locker_session_valid(mp3tunes_locker_object_t *obj) {
483 
484     request_t *request;
485     CURLcode res;
486     chunk_t *chunk;
487 
488     chunk_init(&chunk);
489 
490     request = mp3tunes_locker_api_generate_request(obj, MP3TUNES_SERVER_API, "api/v1/accountData", NULL);
491     if (request == NULL) {
492         chunk_deinit(&chunk);
493         return -1;
494     }
495 
496     curl_easy_setopt( request->curl, CURLOPT_URL, request->url );
497     curl_easy_setopt( request->curl, CURLOPT_WRITEFUNCTION, write_chunk_callback );
498     curl_easy_setopt( request->curl, CURLOPT_WRITEDATA, (void *)chunk );
499     curl_easy_setopt( request->curl, CURLOPT_NOBODY, 1 );
500     curl_easy_setopt( request->curl, CURLOPT_USERAGENT, "liboboe/1.0" );
501     curl_easy_setopt( request->curl, CURLOPT_HEADER, 1 );
502     curl_easy_setopt( request->curl, CURLOPT_NOPROGRESS, 1 );
503 
504     res = curl_easy_perform(request->curl);
505 /*    curl_easy_cleanup(request->curl); */
506     mp3tunes_request_deinit(&request);
507 
508     if (res != CURLE_OK) {
509         chunk_deinit(&chunk);
510         return -1;
511     }
512 
513     if (chunk->data == NULL) {
514         return -1;
515     }
516 
517     char name[] = "X-MP3tunes-ErrorNo";
518     char value[] = "401001";
519     char *result = strstr (chunk->data, name);
520     if (result != 0)
521     {
522         int i = strcspn(result, "\n");
523         char *result1 = malloc(i + 1);
524         if (result1 == NULL)
525             return -1;
526 
527         /* ensure result1 is null-terminated */
528         snprintf(result1, i+1, "%s", result);
529         /*printf("Header String: %s\n", result1);*/
530         result = strstr(result1, value);
531         free(result1);
532         if (result != 0) /* i.e., value could not be located hence there is no 404 error. */
533             return -1; /* session is invalid*/
534     }
535 
536     /*printf("Fetch result:\n%s\n", chunk->data);*/
537     return 0; /* session is valid*/
538 }
539 
mp3tunes_locker_list_init(struct mp3tunes_locker_list_s ** list)540 int mp3tunes_locker_list_init(struct mp3tunes_locker_list_s **list) {
541     struct mp3tunes_locker_list_s *l = *list = (struct mp3tunes_locker_list_s*)malloc(sizeof(struct mp3tunes_locker_list_s));
542     l->last_id = 0;
543     l->first = l->last = NULL;
544     return 0;
545 }
546 
mp3tunes_locker_track_list_init(mp3tunes_locker_track_list_t ** list)547 int mp3tunes_locker_track_list_init(mp3tunes_locker_track_list_t **list) {
548     return mp3tunes_locker_list_init((struct mp3tunes_locker_list_s**)list);
549 }
550 
mp3tunes_locker_artist_list_init(mp3tunes_locker_artist_list_t ** list)551 int mp3tunes_locker_artist_list_init(mp3tunes_locker_artist_list_t **list) {
552     return mp3tunes_locker_list_init((struct mp3tunes_locker_list_s**)list);
553 }
554 
mp3tunes_locker_album_list_init(mp3tunes_locker_album_list_t ** list)555 int mp3tunes_locker_album_list_init(mp3tunes_locker_album_list_t **list) {
556     return mp3tunes_locker_list_init((struct mp3tunes_locker_list_s**)list);
557 }
558 
mp3tunes_locker_playlist_list_init(mp3tunes_locker_playlist_list_t ** list)559 int mp3tunes_locker_playlist_list_init(mp3tunes_locker_playlist_list_t **list) {
560     return mp3tunes_locker_list_init((struct mp3tunes_locker_list_s**)list);
561 }
562 
mp3tunes_locker_list_add(struct mp3tunes_locker_list_s ** list,void * value)563 int mp3tunes_locker_list_add(struct mp3tunes_locker_list_s **list, void* value) {
564     struct mp3tunes_locker_list_s *l = *list;
565     mp3tunes_locker_list_item_t *item = (mp3tunes_locker_list_item_t*)malloc(sizeof(mp3tunes_locker_list_item_t));
566     item->id = l->last_id++;
567     item->prev = l->last;
568     item->next = NULL;
569     item->value = value;
570 
571     if (l->first) {
572         l->last = item->prev->next = item;
573     } else {
574         l->first = l->last = item;
575     }
576 
577     return 0;
578 }
579 
mp3tunes_locker_track_list_add(mp3tunes_locker_track_list_t ** list,mp3tunes_locker_track_t * track)580 int mp3tunes_locker_track_list_add(mp3tunes_locker_track_list_t **list, mp3tunes_locker_track_t *track) {
581     return mp3tunes_locker_list_add((struct mp3tunes_locker_list_s**)list, (void*)track);
582 }
583 
mp3tunes_locker_artist_list_add(mp3tunes_locker_artist_list_t ** list,mp3tunes_locker_artist_t * artist)584 int mp3tunes_locker_artist_list_add(mp3tunes_locker_artist_list_t **list, mp3tunes_locker_artist_t *artist) {
585     return mp3tunes_locker_list_add((struct mp3tunes_locker_list_s**)list, (void*)artist);
586 }
587 
mp3tunes_locker_album_list_add(mp3tunes_locker_album_list_t ** list,mp3tunes_locker_album_t * album)588 int mp3tunes_locker_album_list_add(mp3tunes_locker_album_list_t **list, mp3tunes_locker_album_t *album) {
589     return mp3tunes_locker_list_add((struct mp3tunes_locker_list_s**)list, (void*)album);
590 }
591 
mp3tunes_locker_playlist_list_add(mp3tunes_locker_playlist_list_t ** list,mp3tunes_locker_playlist_t * album)592 int mp3tunes_locker_playlist_list_add(mp3tunes_locker_playlist_list_t **list, mp3tunes_locker_playlist_t *album) {
593     return mp3tunes_locker_list_add((struct mp3tunes_locker_list_s**)list, (void*)album);
594 }
595 
mp3tunes_locker_list_deinit(struct mp3tunes_locker_list_s ** list)596 int mp3tunes_locker_list_deinit(struct mp3tunes_locker_list_s **list) {
597     struct mp3tunes_locker_list_s *l = *list;
598     if (l) {
599         mp3tunes_locker_list_item_t *list_item = l->first;
600         while(l->first) {
601             list_item = l->first->next;
602             free(l->first);
603             l->first = list_item;
604         }
605         free(l);
606         return 0;
607     }
608     return -1;
609 }
610 
mp3tunes_locker_track_list_deinit(mp3tunes_locker_track_list_t ** track_list)611 int mp3tunes_locker_track_list_deinit(mp3tunes_locker_track_list_t **track_list) {
612     mp3tunes_locker_track_list_t *list = *track_list;
613     mp3tunes_locker_list_item_t *track_item = list->first;
614     mp3tunes_locker_track_t *track;
615 
616     while (track_item != NULL) {
617         track = (mp3tunes_locker_track_t*)track_item->value;
618         free(track->trackTitle);
619         free(track->trackFileName);
620         free(track->trackFileKey);
621         free(track->downloadURL);
622         free(track->playURL);
623         free(track->albumTitle);
624         free(track->artistName);
625 
626         free(track);
627         track_item = track_item->next;
628     }
629     return mp3tunes_locker_list_deinit((struct mp3tunes_locker_list_s**)track_list);
630 }
631 
mp3tunes_locker_artist_list_deinit(mp3tunes_locker_artist_list_t ** artist_list)632 int mp3tunes_locker_artist_list_deinit(mp3tunes_locker_artist_list_t **artist_list) {
633     mp3tunes_locker_artist_list_t *list = *artist_list;
634     mp3tunes_locker_list_item_t *artist_item = list->first;
635     mp3tunes_locker_artist_t *artist;
636 
637     while (artist_item != NULL) {
638         artist = (mp3tunes_locker_artist_t*)artist_item->value;
639         free(artist->artistName);
640 
641         free(artist);
642         artist_item = artist_item->next;
643     }
644     return mp3tunes_locker_list_deinit((struct mp3tunes_locker_list_s**)artist_list);
645 }
646 
mp3tunes_locker_album_list_deinit(mp3tunes_locker_album_list_t ** album_list)647 int mp3tunes_locker_album_list_deinit(mp3tunes_locker_album_list_t **album_list) {
648     mp3tunes_locker_album_list_t *list = *album_list;
649     mp3tunes_locker_list_item_t *album_item = list->first;
650     mp3tunes_locker_album_t *album;
651 
652     while (album_item != NULL) {
653         album = (mp3tunes_locker_album_t*)album_item->value;
654         free(album->albumTitle);
655         free(album->artistName);
656 
657         free(album);
658         album_item = album_item->next;
659     }
660     return mp3tunes_locker_list_deinit((struct mp3tunes_locker_list_s**)album_list);
661 }
662 
mp3tunes_locker_playlist_list_deinit(mp3tunes_locker_playlist_list_t ** playlist_list)663 int mp3tunes_locker_playlist_list_deinit(mp3tunes_locker_playlist_list_t **playlist_list) {
664     mp3tunes_locker_playlist_list_t *list = *playlist_list;
665     mp3tunes_locker_list_item_t *playlist_item = list->first;
666     mp3tunes_locker_playlist_t *playlist;
667 
668     while (playlist_item != NULL) {
669         playlist = (mp3tunes_locker_playlist_t*)playlist_item->value;
670         free(playlist->playlistId);
671         free(playlist->playlistTitle);
672         free(playlist->title);
673         free(playlist->fileName);
674 
675         free(playlist);
676         playlist_item = playlist_item->next;
677     }
678     return mp3tunes_locker_list_deinit((struct mp3tunes_locker_list_s**)playlist_list);
679 }
680 
_mp3tunes_locker_tracks(mp3tunes_locker_object_t * obj,mp3tunes_locker_track_list_t ** tracks,int artist_id,int album_id,const char * playlist_id)681 static int _mp3tunes_locker_tracks(mp3tunes_locker_object_t *obj, mp3tunes_locker_track_list_t **tracks, int artist_id, int album_id, const char* playlist_id) {
682     xml_xpath_t* xml_xpath;
683     xmlXPathObjectPtr xpath_obj;
684     xmlNodeSetPtr nodeset;
685     xmlNodePtr node;
686     int i;
687     char artist_id_s[15];
688     char album_id_s[15];
689 
690     if (playlist_id == NULL) {
691         if (artist_id == -1 && album_id == -1) {
692             xml_xpath = mp3tunes_locker_api_simple_fetch(obj, MP3TUNES_SERVER_API, "api/v1/lockerData/", "type", "track", NULL);
693         } else if (artist_id != -1 && album_id == -1) {
694             snprintf(artist_id_s, 15, "%d", artist_id);
695             xml_xpath = mp3tunes_locker_api_simple_fetch(obj, MP3TUNES_SERVER_API, "api/v1/lockerData/", "type", "track", "artist_id", artist_id_s, NULL);
696         } else if (artist_id == -1 && album_id != -1) {
697             snprintf(album_id_s, 15, "%d", album_id);
698             xml_xpath = mp3tunes_locker_api_simple_fetch(obj, MP3TUNES_SERVER_API, "api/v1/lockerData/", "type", "track", "album_id", album_id_s, NULL);
699         } else {
700             snprintf(artist_id_s, 15, "%d", artist_id);
701             snprintf(album_id_s, 15, "%d", album_id);
702             xml_xpath = mp3tunes_locker_api_simple_fetch(obj, MP3TUNES_SERVER_API, "api/v1/lockerData/", "type", "track", "artist_id", artist_id_s, "album_id", album_id_s, NULL);
703         }
704     } else {
705         xml_xpath = mp3tunes_locker_api_simple_fetch(obj, MP3TUNES_SERVER_API, "api/v1/lockerData/", "type", "track", "playlist_id", playlist_id, NULL);
706     }
707 
708     mp3tunes_locker_track_list_init(tracks);
709 
710     if (xml_xpath == NULL) {
711         return -1;
712     }
713 
714     xpath_obj = xml_xpath_query(xml_xpath, "/mp3tunes/trackList/item");
715 
716     if (xpath_obj == NULL) {
717         return -1;
718     }
719 
720     nodeset = xpath_obj->nodesetval;
721 
722     for (i = 0; i < nodeset->nodeNr; i++) {
723         node = nodeset->nodeTab[i];
724         xml_xpath_t* xml_xpath_context = xml_xpath_context_init(xml_xpath, node);
725         mp3tunes_locker_track_t *track = (mp3tunes_locker_track_t*)malloc(sizeof(mp3tunes_locker_track_t));
726         memset(track, 0, sizeof(mp3tunes_locker_track_t));
727 
728         track->trackId = xml_xpath_get_integer(xml_xpath_context, "trackId");
729         track->trackTitle = xml_xpath_get_string(xml_xpath_context, "trackTitle");
730         track->trackNumber = xml_xpath_get_integer(xml_xpath_context, "trackNumber");
731         track->trackLength = xml_xpath_get_float(xml_xpath_context, "trackLength");
732         track->trackFileName = xml_xpath_get_string(xml_xpath_context, "trackFileName");
733         track->trackFileKey = xml_xpath_get_string(xml_xpath_context, "trackFileKey");
734         track->trackFileSize = xml_xpath_get_integer(xml_xpath_context, "trackFileSize");
735         track->downloadURL = xml_xpath_get_string(xml_xpath_context, "downloadURL");
736         track->playURL = xml_xpath_get_string(xml_xpath_context, "playURL");
737         track->albumId = xml_xpath_get_integer(xml_xpath_context, "albumId");
738         track->albumTitle = xml_xpath_get_string(xml_xpath_context, "albumTitle");
739         track->albumYear = xml_xpath_get_integer(xml_xpath_context, "albumYear");
740         track->artistName = xml_xpath_get_string(xml_xpath_context, "artistName");
741         track->artistId = xml_xpath_get_integer(xml_xpath_context, "artistId");
742 
743         mp3tunes_locker_track_list_add(tracks, track);
744         xml_xpath_deinit(xml_xpath_context);
745     }
746     xmlXPathFreeObject(xpath_obj);
747     xml_xpath_deinit(xml_xpath);
748     return 0;
749 }
750 
mp3tunes_locker_tracks_search(mp3tunes_locker_object_t * obj,mp3tunes_locker_track_list_t ** tracks,char * search)751 int mp3tunes_locker_tracks_search( mp3tunes_locker_object_t *obj, mp3tunes_locker_track_list_t **tracks, char *search) {
752     xml_xpath_t* xml_xpath;
753     xmlXPathObjectPtr xpath_obj;
754     xmlNodeSetPtr nodeset;
755     xmlNodePtr node;
756     int i;
757 
758     xml_xpath = mp3tunes_locker_api_simple_fetch(obj, MP3TUNES_SERVER_API, "api/v1/lockerSearch", "type", "track", "s", search, NULL);
759 
760     mp3tunes_locker_track_list_init(tracks);
761 
762     if (xml_xpath == NULL) {
763         return -1;
764     }
765 
766     xpath_obj = xml_xpath_query(xml_xpath, "/mp3tunes/trackList/item");
767 
768     if (xpath_obj == NULL) {
769         return -1;
770     }
771 
772     nodeset = xpath_obj->nodesetval;
773 
774     for (i = 0; i < nodeset->nodeNr; i++) {
775         node = nodeset->nodeTab[i];
776         xml_xpath_t* xml_xpath_context = xml_xpath_context_init(xml_xpath, node);
777         mp3tunes_locker_track_t *track = (mp3tunes_locker_track_t*)malloc(sizeof(mp3tunes_locker_track_t));
778         memset(track, 0, sizeof(mp3tunes_locker_track_t));
779 
780         track->trackId = xml_xpath_get_integer(xml_xpath_context, "trackId");
781         track->trackTitle = xml_xpath_get_string(xml_xpath_context, "trackTitle");
782         track->trackNumber = xml_xpath_get_integer(xml_xpath_context, "trackNumber");
783         track->trackLength = xml_xpath_get_float(xml_xpath_context, "trackLength");
784         track->trackFileName = xml_xpath_get_string(xml_xpath_context, "trackFileName");
785         track->trackFileKey = xml_xpath_get_string(xml_xpath_context, "trackFileKey");
786         track->trackFileSize = xml_xpath_get_integer(xml_xpath_context, "trackFileSize");
787         track->downloadURL = xml_xpath_get_string(xml_xpath_context, "downloadURL");
788         track->playURL = xml_xpath_get_string(xml_xpath_context, "playURL");
789         track->albumId = xml_xpath_get_integer(xml_xpath_context, "albumId");
790         track->albumTitle = xml_xpath_get_string(xml_xpath_context, "albumTitle");
791         track->albumYear = xml_xpath_get_integer(xml_xpath_context, "albumYear");
792         track->artistName = xml_xpath_get_string(xml_xpath_context, "artistName");
793         track->artistId = xml_xpath_get_integer(xml_xpath_context, "artistId");
794 
795         mp3tunes_locker_track_list_add(tracks, track);
796         xml_xpath_deinit(xml_xpath_context);
797     }
798     xmlXPathFreeObject(xpath_obj);
799     xml_xpath_deinit(xml_xpath);
800     return 0;
801 }
802 
803 
mp3tunes_locker_tracks(mp3tunes_locker_object_t * obj,mp3tunes_locker_track_list_t ** tracks)804 int mp3tunes_locker_tracks(mp3tunes_locker_object_t *obj, mp3tunes_locker_track_list_t **tracks) {
805     return _mp3tunes_locker_tracks(obj, tracks, -1, -1, NULL);
806 }
807 
mp3tunes_locker_tracks_with_artist_id(mp3tunes_locker_object_t * obj,mp3tunes_locker_track_list_t ** tracks,int artist_id)808 int mp3tunes_locker_tracks_with_artist_id(mp3tunes_locker_object_t *obj, mp3tunes_locker_track_list_t **tracks, int artist_id) {
809     return _mp3tunes_locker_tracks(obj, tracks, artist_id, -1, NULL);
810 }
811 
mp3tunes_locker_tracks_with_album_id(mp3tunes_locker_object_t * obj,mp3tunes_locker_track_list_t ** tracks,int album_id)812 int mp3tunes_locker_tracks_with_album_id(mp3tunes_locker_object_t *obj, mp3tunes_locker_track_list_t **tracks, int album_id) {
813     return _mp3tunes_locker_tracks(obj, tracks, -1, album_id, NULL);
814 }
815 
mp3tunes_locker_tracks_with_artist_id_and_album_id(mp3tunes_locker_object_t * obj,mp3tunes_locker_track_list_t ** tracks,int artist_id,int album_id)816 int mp3tunes_locker_tracks_with_artist_id_and_album_id(mp3tunes_locker_object_t *obj, mp3tunes_locker_track_list_t **tracks, int artist_id, int album_id) {
817     return _mp3tunes_locker_tracks(obj, tracks, artist_id, album_id, NULL);
818 }
819 
mp3tunes_locker_tracks_with_playlist_id(mp3tunes_locker_object_t * obj,mp3tunes_locker_track_list_t ** tracks,const char * playlist_id)820 int mp3tunes_locker_tracks_with_playlist_id(mp3tunes_locker_object_t *obj, mp3tunes_locker_track_list_t **tracks, const char* playlist_id) {
821     return _mp3tunes_locker_tracks(obj, tracks, -1, -1, playlist_id);
822 }
823 
mp3tunes_locker_tracks_with_file_key(mp3tunes_locker_object_t * obj,const char * file_keys,mp3tunes_locker_track_list_t ** tracks)824 int mp3tunes_locker_tracks_with_file_key( mp3tunes_locker_object_t *obj, const char *file_keys, mp3tunes_locker_track_list_t **tracks ) {
825     xml_xpath_t* xml_xpath;
826     xmlXPathObjectPtr xpath_obj;
827     xmlNodeSetPtr nodeset;
828     xmlNodePtr node;
829     int i;
830 
831     xml_xpath = mp3tunes_locker_api_simple_fetch(obj, MP3TUNES_SERVER_API, "api/v1/lockerData/", "type", "track", "key", file_keys, NULL);
832 
833     mp3tunes_locker_track_list_init(tracks);
834 
835     if (xml_xpath == NULL) {
836         return -1;
837     }
838 
839     xpath_obj = xml_xpath_query(xml_xpath, "/mp3tunes/trackList/item");
840 
841     if (xpath_obj == NULL) {
842         return -1;
843     }
844 
845     nodeset = xpath_obj->nodesetval;
846 
847     for (i = 0; i < nodeset->nodeNr; i++) {
848         node = nodeset->nodeTab[i];
849         xml_xpath_t* xml_xpath_context = xml_xpath_context_init(xml_xpath, node);
850         mp3tunes_locker_track_t *track = (mp3tunes_locker_track_t*)malloc(sizeof(mp3tunes_locker_track_t));
851         memset(track, 0, sizeof(mp3tunes_locker_track_t));
852 
853         track->trackId = xml_xpath_get_integer(xml_xpath_context, "trackId");
854         track->trackTitle = xml_xpath_get_string(xml_xpath_context, "trackTitle");
855         track->trackNumber = xml_xpath_get_integer(xml_xpath_context, "trackNumber");
856         track->trackLength = xml_xpath_get_float(xml_xpath_context, "trackLength");
857         track->trackFileName = xml_xpath_get_string(xml_xpath_context, "trackFileName");
858         track->trackFileKey = xml_xpath_get_string(xml_xpath_context, "trackFileKey");
859         track->trackFileSize = xml_xpath_get_integer(xml_xpath_context, "trackFileSize");
860         track->downloadURL = xml_xpath_get_string(xml_xpath_context, "downloadURL");
861         track->playURL = xml_xpath_get_string(xml_xpath_context, "playURL");
862         track->albumId = xml_xpath_get_integer(xml_xpath_context, "albumId");
863         track->albumTitle = xml_xpath_get_string(xml_xpath_context, "albumTitle");
864         track->albumYear = xml_xpath_get_integer(xml_xpath_context, "albumYear");
865         track->artistName = xml_xpath_get_string(xml_xpath_context, "artistName");
866         track->artistId = xml_xpath_get_integer(xml_xpath_context, "artistId");
867 
868         mp3tunes_locker_track_list_add(tracks, track);
869         xml_xpath_deinit(xml_xpath_context);
870     }
871     xmlXPathFreeObject(xpath_obj);
872     xml_xpath_deinit(xml_xpath);
873     return 0;
874 
875 }
876 
mp3tunes_locker_track_with_file_key(mp3tunes_locker_object_t * obj,const char * file_key,mp3tunes_locker_track_t ** track)877 int mp3tunes_locker_track_with_file_key( mp3tunes_locker_object_t *obj, const char *file_key, mp3tunes_locker_track_t **track ) {
878     xml_xpath_t* xml_xpath;
879     xmlXPathObjectPtr xpath_obj;
880     xmlNodeSetPtr nodeset;
881     xmlNodePtr node;
882 
883     xml_xpath = mp3tunes_locker_api_simple_fetch(obj, MP3TUNES_SERVER_API, "api/v1/lockerData/", "type", "track", "key", file_key, NULL);
884 
885     if (xml_xpath == NULL) {
886         return -1;
887     }
888 
889     xpath_obj = xml_xpath_query(xml_xpath, "/mp3tunes/trackList/item");
890 
891     if (xpath_obj == NULL) {
892         return -1;
893     }
894 
895     nodeset = xpath_obj->nodesetval;
896     if ( nodeset->nodeNr == 1) {
897         node = nodeset->nodeTab[0];
898 
899         xml_xpath_t* xml_xpath_context = xml_xpath_context_init(xml_xpath, node);
900         mp3tunes_locker_track_t *t = *track = (mp3tunes_locker_track_t*)malloc(sizeof(mp3tunes_locker_track_t));
901 
902         t->trackId = xml_xpath_get_integer(xml_xpath_context, "trackId");
903         t->trackTitle = xml_xpath_get_string(xml_xpath_context, "trackTitle");
904         t->trackNumber = xml_xpath_get_integer(xml_xpath_context, "trackNumber");
905         t->trackLength = xml_xpath_get_float(xml_xpath_context, "trackLength");
906         t->trackFileName = xml_xpath_get_string(xml_xpath_context, "trackFileName");
907         t->trackFileKey = xml_xpath_get_string(xml_xpath_context, "trackFileKey");
908         t->trackFileSize = xml_xpath_get_integer(xml_xpath_context, "trackFileSize");
909         t->downloadURL = xml_xpath_get_string(xml_xpath_context, "downloadURL");
910         t->playURL = xml_xpath_get_string(xml_xpath_context, "playURL");
911         t->albumId = xml_xpath_get_integer(xml_xpath_context, "albumId");
912         t->albumTitle = xml_xpath_get_string(xml_xpath_context, "albumTitle");
913         t->albumYear = xml_xpath_get_integer(xml_xpath_context, "albumYear");
914         t->artistName = xml_xpath_get_string(xml_xpath_context, "artistName");
915         t->artistId = xml_xpath_get_integer(xml_xpath_context, "artistId");
916 
917         xml_xpath_deinit(xml_xpath_context);
918         xmlXPathFreeObject(xpath_obj);
919         xml_xpath_deinit(xml_xpath);
920         return 0;
921     }
922     xmlXPathFreeObject(xpath_obj);
923     xml_xpath_deinit(xml_xpath);
924     return -1;
925 }
926 
mp3tunes_locker_artists(mp3tunes_locker_object_t * obj,mp3tunes_locker_artist_list_t ** artists)927 int mp3tunes_locker_artists(mp3tunes_locker_object_t *obj, mp3tunes_locker_artist_list_t **artists) {
928     xml_xpath_t* xml_xpath;
929     xmlXPathObjectPtr xpath_obj;
930     xmlNodeSetPtr nodeset;
931     xmlNodePtr node;
932     int i;
933 
934     xml_xpath = mp3tunes_locker_api_simple_fetch(obj, MP3TUNES_SERVER_API, "api/v1/lockerData/", "type", "artist", NULL);
935 
936     mp3tunes_locker_artist_list_init(artists);
937 
938     if (xml_xpath == NULL) {
939         return -1;
940     }
941 
942     xpath_obj = xml_xpath_query(xml_xpath, "/mp3tunes/artistList/item");
943     if (xpath_obj == NULL) {
944         return -1;
945     }
946 
947     nodeset = xpath_obj->nodesetval;
948 
949     for (i = 0; i < nodeset->nodeNr; i++) {
950         node = nodeset->nodeTab[i];
951         xml_xpath_t* xml_xpath_context = xml_xpath_context_init(xml_xpath, node);
952         mp3tunes_locker_artist_t *artist = (mp3tunes_locker_artist_t*)malloc(sizeof(mp3tunes_locker_artist_t));
953         memset(artist, 0, sizeof(mp3tunes_locker_artist_t));
954 
955         artist->artistId = xml_xpath_get_integer(xml_xpath_context, "artistId");
956         artist->artistName = xml_xpath_get_string(xml_xpath_context, "artistName");
957         artist->artistSize = xml_xpath_get_integer(xml_xpath_context, "artistSize");
958         artist->albumCount = xml_xpath_get_integer(xml_xpath_context, "albumCount");
959         artist->trackCount = xml_xpath_get_integer(xml_xpath_context, "trackCount");
960 
961         mp3tunes_locker_artist_list_add(artists, artist);
962         xml_xpath_deinit(xml_xpath_context);
963     }
964     xmlXPathFreeObject(xpath_obj);
965     xml_xpath_deinit(xml_xpath);
966     return 0;
967 }
968 
mp3tunes_locker_artists_search(mp3tunes_locker_object_t * obj,mp3tunes_locker_artist_list_t ** artists,char * search)969 int mp3tunes_locker_artists_search( mp3tunes_locker_object_t *obj, mp3tunes_locker_artist_list_t **artists, char *search) {
970     xml_xpath_t* xml_xpath;
971     xmlXPathObjectPtr xpath_obj;
972     xmlNodeSetPtr nodeset;
973     xmlNodePtr node;
974     int i;
975 
976     xml_xpath = mp3tunes_locker_api_simple_fetch(obj, MP3TUNES_SERVER_API, "api/v1/lockerSearch", "type", "artist", "s", search, NULL);
977     mp3tunes_locker_artist_list_init(artists);
978 
979     if (xml_xpath == NULL) {
980         return -1;
981     }
982 
983     xpath_obj = xml_xpath_query(xml_xpath, "/mp3tunes/artistList/item");
984     if (xpath_obj == NULL) {
985         return -1;
986     }
987 
988     nodeset = xpath_obj->nodesetval;
989 
990     for (i = 0; i < nodeset->nodeNr; i++) {
991         node = nodeset->nodeTab[i];
992         xml_xpath_t* xml_xpath_context = xml_xpath_context_init(xml_xpath, node);
993         mp3tunes_locker_artist_t *artist = (mp3tunes_locker_artist_t*)malloc(sizeof(mp3tunes_locker_artist_t));
994         memset(artist, 0, sizeof(mp3tunes_locker_artist_t));
995 
996         artist->artistId = xml_xpath_get_integer(xml_xpath_context, "artistId");
997         artist->artistName = xml_xpath_get_string(xml_xpath_context, "artistName");
998         artist->artistSize = xml_xpath_get_integer(xml_xpath_context, "artistSize");
999         artist->albumCount = xml_xpath_get_integer(xml_xpath_context, "albumCount");
1000         artist->trackCount = xml_xpath_get_integer(xml_xpath_context, "trackCount");
1001 
1002         mp3tunes_locker_artist_list_add(artists, artist);
1003         xml_xpath_deinit(xml_xpath_context);
1004     }
1005     xmlXPathFreeObject(xpath_obj);
1006     xml_xpath_deinit(xml_xpath);
1007     return 0;
1008 }
1009 
1010 
mp3tunes_locker_albums_with_artist_id(mp3tunes_locker_object_t * obj,mp3tunes_locker_album_list_t ** albums,int artist_id)1011 int mp3tunes_locker_albums_with_artist_id(mp3tunes_locker_object_t *obj, mp3tunes_locker_album_list_t **albums, int artist_id) {
1012     xml_xpath_t* xml_xpath;
1013     xmlXPathObjectPtr xpath_obj;
1014     xmlNodeSetPtr nodeset;
1015     xmlNodePtr node;
1016     int i;
1017     char artist_id_string[15];
1018 
1019     if (artist_id == -1) {
1020         xml_xpath = mp3tunes_locker_api_simple_fetch(obj, MP3TUNES_SERVER_API, "api/v1/lockerData/", "type", "album", NULL);
1021     } else {
1022         snprintf(artist_id_string, 15, "%d", artist_id);
1023         xml_xpath = mp3tunes_locker_api_simple_fetch(obj, MP3TUNES_SERVER_API, "api/v1/lockerData/", "type", "album", "artist_id", artist_id_string, NULL);
1024     }
1025 
1026     mp3tunes_locker_album_list_init(albums);
1027 
1028     if (xml_xpath == NULL) {
1029         return -1;
1030     }
1031 
1032     xpath_obj = xml_xpath_query(xml_xpath, "/mp3tunes/albumList/item");
1033 
1034     if (xpath_obj == NULL) {
1035         return -1;
1036     }
1037 
1038     nodeset = xpath_obj->nodesetval;
1039 
1040     for (i = 0; i < nodeset->nodeNr; i++) {
1041         node = nodeset->nodeTab[i];
1042         xml_xpath_t* xml_xpath_context = xml_xpath_context_init(xml_xpath, node);
1043         mp3tunes_locker_album_t *album = (mp3tunes_locker_album_t*)malloc(sizeof(mp3tunes_locker_album_t));
1044         memset(album, 0, sizeof(mp3tunes_locker_album_t));
1045 
1046         album->albumId = xml_xpath_get_integer(xml_xpath_context, "albumId");
1047         album->albumTitle = xml_xpath_get_string(xml_xpath_context, "albumTitle");
1048         album->artistId = xml_xpath_get_integer(xml_xpath_context, "artistId");
1049         album->artistName = xml_xpath_get_string(xml_xpath_context, "artistName");
1050         album->trackCount = xml_xpath_get_integer(xml_xpath_context, "trackCount");
1051         album->albumSize = xml_xpath_get_integer(xml_xpath_context, "albumSize");
1052         album->hasArt = xml_xpath_get_integer(xml_xpath_context, "hasArt");
1053 
1054         mp3tunes_locker_album_list_add(albums, album);
1055         xml_xpath_deinit(xml_xpath_context);
1056     }
1057     xmlXPathFreeObject(xpath_obj);
1058     xml_xpath_deinit(xml_xpath);
1059     return 0;
1060 }
1061 
mp3tunes_locker_albums(mp3tunes_locker_object_t * obj,mp3tunes_locker_album_list_t ** albums)1062 int mp3tunes_locker_albums(mp3tunes_locker_object_t *obj, mp3tunes_locker_album_list_t **albums) {
1063     return mp3tunes_locker_albums_with_artist_id(obj, albums, -1);
1064 }
1065 
mp3tunes_locker_albums_search(mp3tunes_locker_object_t * obj,mp3tunes_locker_album_list_t ** albums,char * search)1066 int mp3tunes_locker_albums_search(  mp3tunes_locker_object_t *obj, mp3tunes_locker_album_list_t **albums, char *search) {
1067     xml_xpath_t* xml_xpath;
1068     xmlXPathObjectPtr xpath_obj;
1069     xmlNodeSetPtr nodeset;
1070     xmlNodePtr node;
1071     int i;
1072 
1073     xml_xpath = mp3tunes_locker_api_simple_fetch(obj, MP3TUNES_SERVER_API, "api/v1/lockerSearch", "type", "album", "s", search, NULL);
1074 
1075     mp3tunes_locker_album_list_init(albums);
1076 
1077     if (xml_xpath == NULL) {
1078         return -1;
1079     }
1080 
1081     xpath_obj = xml_xpath_query(xml_xpath, "/mp3tunes/albumList/item");
1082 
1083     if (xpath_obj == NULL) {
1084         return -1;
1085     }
1086 
1087     nodeset = xpath_obj->nodesetval;
1088 
1089     for (i = 0; i < nodeset->nodeNr; i++) {
1090         node = nodeset->nodeTab[i];
1091         xml_xpath_t* xml_xpath_context = xml_xpath_context_init(xml_xpath, node);
1092         mp3tunes_locker_album_t *album = (mp3tunes_locker_album_t*)malloc(sizeof(mp3tunes_locker_album_t));
1093         memset(album, 0, sizeof(mp3tunes_locker_album_t));
1094 
1095         album->albumId = xml_xpath_get_integer(xml_xpath_context, "albumId");
1096         album->albumTitle = xml_xpath_get_string(xml_xpath_context, "albumTitle");
1097         album->artistId = xml_xpath_get_integer(xml_xpath_context, "artistId");
1098         album->artistName = xml_xpath_get_string(xml_xpath_context, "artistName");
1099         album->trackCount = xml_xpath_get_integer(xml_xpath_context, "trackCount");
1100         album->albumSize = xml_xpath_get_integer(xml_xpath_context, "albumSize");
1101         album->hasArt = xml_xpath_get_integer(xml_xpath_context, "hasArt");
1102 
1103         mp3tunes_locker_album_list_add(albums, album);
1104         xml_xpath_deinit(xml_xpath_context);
1105     }
1106     xmlXPathFreeObject(xpath_obj);
1107     xml_xpath_deinit(xml_xpath);
1108     return 0;
1109 }
1110 
1111 
1112 
1113 
mp3tunes_locker_playlists(mp3tunes_locker_object_t * obj,mp3tunes_locker_playlist_list_t ** playlists)1114 int mp3tunes_locker_playlists(mp3tunes_locker_object_t *obj, mp3tunes_locker_playlist_list_t **playlists) {
1115     xml_xpath_t* xml_xpath;
1116     xmlXPathObjectPtr xpath_obj;
1117     xmlNodeSetPtr nodeset;
1118     xmlNodePtr node;
1119     int i;
1120 
1121     xml_xpath = mp3tunes_locker_api_simple_fetch(obj, MP3TUNES_SERVER_API, "api/v1/lockerData/", "type", "playlist", NULL);
1122 
1123     mp3tunes_locker_playlist_list_init(playlists);
1124 
1125     if (xml_xpath == NULL) {
1126         return -1;
1127     }
1128 
1129     xpath_obj =xml_xpath_query(xml_xpath, "/mp3tunes/playlistList/item");
1130 
1131     if (xpath_obj == NULL) {
1132         return -1;
1133     }
1134 
1135     nodeset = xpath_obj->nodesetval;
1136 
1137     for (i = 0; i < nodeset->nodeNr; i++) {
1138         node = nodeset->nodeTab[i];
1139         xml_xpath_t* xml_xpath_context = xml_xpath_context_init(xml_xpath, node);
1140         mp3tunes_locker_playlist_t *playlist = (mp3tunes_locker_playlist_t*)malloc(sizeof(mp3tunes_locker_playlist_t));
1141         memset(playlist, 0, sizeof(mp3tunes_locker_playlist_t));
1142 
1143         playlist->playlistId = xml_xpath_get_string(xml_xpath_context, "playlistId");
1144         playlist->playlistTitle = xml_xpath_get_string(xml_xpath_context, "playlistTitle");
1145         playlist->title = xml_xpath_get_string(xml_xpath_context, "title");
1146         playlist->fileName = xml_xpath_get_string(xml_xpath_context, "fileName");
1147         playlist->fileCount = xml_xpath_get_integer(xml_xpath_context, "fileCount");
1148         playlist->playlistSize = xml_xpath_get_integer(xml_xpath_context, "playlistSize");
1149 
1150         mp3tunes_locker_playlist_list_add(playlists, playlist);
1151         xml_xpath_deinit(xml_xpath_context);
1152     }
1153     xmlXPathFreeObject(xpath_obj);
1154     xml_xpath_deinit(xml_xpath);
1155     return 0;
1156 }
1157 
mp3tunes_locker_search(mp3tunes_locker_object_t * obj,mp3tunes_locker_artist_list_t ** artists,mp3tunes_locker_album_list_t ** albums,mp3tunes_locker_track_list_t ** tracks,const char * query)1158 int mp3tunes_locker_search(mp3tunes_locker_object_t *obj, mp3tunes_locker_artist_list_t **artists, mp3tunes_locker_album_list_t **albums, mp3tunes_locker_track_list_t **tracks, const char *query) {
1159     xml_xpath_t* xml_xpath;
1160 
1161     char type[20] = "";
1162     if( artists != NULL ) {
1163       strcat( type, "artist," );
1164     }
1165     if( albums != NULL ) {
1166       strcat( type, "album," );
1167     }
1168     if( tracks != NULL ) {
1169       strcat( type, "track," );
1170     }
1171     if( strlen(type) == 0 ) {
1172       return -1;
1173     }
1174     /*printf("type: '%s' query: '%s'\n", placeholder, query);*/
1175 
1176     xml_xpath = mp3tunes_locker_api_simple_fetch(obj, MP3TUNES_SERVER_API, "api/v1/lockerSearch", "type", type, "s", query, NULL);
1177     if (xml_xpath == NULL)
1178         return -1;
1179 
1180     if(artists != NULL) {
1181         xmlXPathObjectPtr xpath_obj;
1182         xmlNodeSetPtr nodeset;
1183         xmlNodePtr node;
1184         int i;
1185         mp3tunes_locker_artist_list_init(artists);
1186 
1187         xpath_obj = xml_xpath_query(xml_xpath, "/mp3tunes/artistList/item");
1188         if (xpath_obj == NULL) {
1189             return -1;
1190         }
1191 
1192         nodeset = xpath_obj->nodesetval;
1193 
1194         for (i = 0; i < nodeset->nodeNr; i++) {
1195             node = nodeset->nodeTab[i];
1196             xml_xpath_t* xml_xpath_context = xml_xpath_context_init(xml_xpath, node);
1197             mp3tunes_locker_artist_t *artist = (mp3tunes_locker_artist_t*)malloc(sizeof(mp3tunes_locker_artist_t));
1198             memset(artist, 0, sizeof(mp3tunes_locker_artist_t));
1199 
1200             artist->artistId = xml_xpath_get_integer(xml_xpath_context, "artistId");
1201             artist->artistName = xml_xpath_get_string(xml_xpath_context, "artistName");
1202             artist->artistSize = xml_xpath_get_integer(xml_xpath_context, "artistSize");
1203             artist->albumCount = xml_xpath_get_integer(xml_xpath_context, "albumCount");
1204             artist->trackCount = xml_xpath_get_integer(xml_xpath_context, "trackCount");
1205 
1206             mp3tunes_locker_artist_list_add(artists, artist);
1207             xml_xpath_deinit(xml_xpath_context);
1208         }
1209         xmlXPathFreeObject(xpath_obj);
1210     }
1211 
1212     if( albums != NULL ) {
1213         xmlXPathObjectPtr xpath_obj;
1214         xmlNodeSetPtr nodeset;
1215         xmlNodePtr node;
1216         int i;
1217 
1218         mp3tunes_locker_album_list_init(albums);
1219 
1220         xpath_obj = xml_xpath_query(xml_xpath, "/mp3tunes/albumList/item");
1221 
1222         if (xpath_obj == NULL) {
1223             return -1;
1224         }
1225 
1226         nodeset = xpath_obj->nodesetval;
1227 
1228         for (i = 0; i < nodeset->nodeNr; i++) {
1229             node = nodeset->nodeTab[i];
1230             xml_xpath_t* xml_xpath_context = xml_xpath_context_init(xml_xpath, node);
1231             mp3tunes_locker_album_t *album = (mp3tunes_locker_album_t*)malloc(sizeof(mp3tunes_locker_album_t));
1232             memset(album, 0, sizeof(mp3tunes_locker_album_t));
1233 
1234             album->albumId = xml_xpath_get_integer(xml_xpath_context, "albumId");
1235             album->albumTitle = xml_xpath_get_string(xml_xpath_context, "albumTitle");
1236             album->artistId = xml_xpath_get_integer(xml_xpath_context, "artistId");
1237             album->artistName = xml_xpath_get_string(xml_xpath_context, "artistName");
1238             album->trackCount = xml_xpath_get_integer(xml_xpath_context, "trackCount");
1239             album->albumSize = xml_xpath_get_integer(xml_xpath_context, "albumSize");
1240             album->hasArt = xml_xpath_get_integer(xml_xpath_context, "hasArt");
1241 
1242             mp3tunes_locker_album_list_add(albums, album);
1243             xml_xpath_deinit(xml_xpath_context);
1244         }
1245         xmlXPathFreeObject(xpath_obj);
1246     }
1247     if( tracks != NULL) {
1248         xmlXPathObjectPtr xpath_obj;
1249         xmlNodeSetPtr nodeset;
1250         xmlNodePtr node;
1251         int i;
1252 
1253         mp3tunes_locker_track_list_init(tracks);
1254 
1255         xpath_obj = xml_xpath_query(xml_xpath, "/mp3tunes/trackList/item");
1256 
1257         if (xpath_obj == NULL) {
1258             return -1;
1259         }
1260 
1261         nodeset = xpath_obj->nodesetval;
1262 
1263         for (i = 0; i < nodeset->nodeNr; i++) {
1264             node = nodeset->nodeTab[i];
1265             xml_xpath_t* xml_xpath_context = xml_xpath_context_init(xml_xpath, node);
1266             mp3tunes_locker_track_t *track = (mp3tunes_locker_track_t*)malloc(sizeof(mp3tunes_locker_track_t));
1267             memset(track, 0, sizeof(mp3tunes_locker_track_t));
1268 
1269             track->trackId = xml_xpath_get_integer(xml_xpath_context, "trackId");
1270             track->trackTitle = xml_xpath_get_string(xml_xpath_context, "trackTitle");
1271             track->trackNumber = xml_xpath_get_integer(xml_xpath_context, "trackNumber");
1272             track->trackLength = xml_xpath_get_float(xml_xpath_context, "trackLength");
1273             track->trackFileName = xml_xpath_get_string(xml_xpath_context, "trackFileName");
1274             track->trackFileKey = xml_xpath_get_string(xml_xpath_context, "trackFileKey");
1275             track->trackFileSize = xml_xpath_get_integer(xml_xpath_context, "trackFileSize");
1276             track->downloadURL = xml_xpath_get_string(xml_xpath_context, "downloadURL");
1277             track->playURL = xml_xpath_get_string(xml_xpath_context, "playURL");
1278             track->albumId = xml_xpath_get_integer(xml_xpath_context, "albumId");
1279             track->albumTitle = xml_xpath_get_string(xml_xpath_context, "albumTitle");
1280             track->albumYear = xml_xpath_get_integer(xml_xpath_context, "albumYear");
1281             track->artistName = xml_xpath_get_string(xml_xpath_context, "artistName");
1282             track->artistId = xml_xpath_get_integer(xml_xpath_context, "artistId");
1283 
1284             mp3tunes_locker_track_list_add(tracks, track);
1285             xml_xpath_deinit(xml_xpath_context);
1286         }
1287         xmlXPathFreeObject(xpath_obj);
1288     }
1289     xml_xpath_deinit(xml_xpath);
1290     return 0;
1291 }
1292 
mp3tunes_locker_sync_down(mp3tunes_locker_object_t * obj,char * type,char * bytes_local,char * files_local,char * keep_local_files,char * playlist_id)1293 int mp3tunes_locker_sync_down(mp3tunes_locker_object_t *obj, char* type, char* bytes_local, char* files_local, char* keep_local_files, char* playlist_id) {
1294     xml_xpath_t* xml_xpath;
1295     xmlBufferPtr buf;
1296     xmlTextWriterPtr writer;
1297 
1298     buf = xmlBufferCreate();
1299     if (buf == NULL) {
1300         return -1;
1301     }
1302 
1303     writer = xmlNewTextWriterMemory(buf, 0);
1304 
1305     if (writer == NULL) {
1306         return -1;
1307     }
1308 
1309     if (xmlTextWriterStartDocument(writer, NULL, "UTF-8", NULL) < 0) {
1310         return -1;
1311     }
1312 
1313     if (xmlTextWriterStartElement(writer, BAD_CAST "sync") < 0) {
1314         return -1;
1315     }
1316 
1317     if (xmlTextWriterStartElement(writer, BAD_CAST "options") < 0) {
1318         return -1;
1319     }
1320 
1321     if (xmlTextWriterStartElement(writer, BAD_CAST "direction") < 0) {
1322         return -1;
1323     }
1324 
1325     if (xmlTextWriterWriteAttribute(writer, BAD_CAST "sync_down", BAD_CAST "1") < 0) {
1326         return -1;
1327     }
1328 
1329     if (xmlTextWriterEndElement(writer) < 0) {
1330         return -1;
1331     }
1332 
1333     if (xmlTextWriterStartElement(writer, BAD_CAST "file_sync") < 0) {
1334         return -1;
1335     }
1336 
1337     if (xmlTextWriterWriteAttribute(writer, BAD_CAST "type", BAD_CAST type) < 0) {
1338         return -1;
1339     }
1340 
1341     if (xmlTextWriterEndElement(writer) < 0) {
1342         return -1;
1343     }
1344 
1345     if (xmlTextWriterStartElement(writer, BAD_CAST "max") < 0) {
1346         return -1;
1347     }
1348 
1349     if (bytes_local) {
1350         if (xmlTextWriterWriteAttribute(writer, BAD_CAST "bytes_local", BAD_CAST bytes_local) < 0) {
1351             return -1;
1352         }
1353     }
1354 
1355     if (files_local) {
1356         if (xmlTextWriterWriteAttribute(writer, BAD_CAST "files_local", BAD_CAST files_local) < 0) {
1357             return -1;
1358         }
1359     }
1360 
1361     if (keep_local_files) {
1362         if (xmlTextWriterWriteAttribute(writer, BAD_CAST "keep_local_files", BAD_CAST files_local) < 0) {
1363             return -1;
1364         }
1365     }
1366 
1367     if (xmlTextWriterEndElement(writer) < 0) {
1368         return -1;
1369     }
1370 
1371     if (playlist_id) {
1372         if (xmlTextWriterStartElement(writer, BAD_CAST "playlist") < 0) {
1373             return -1;
1374         }
1375 
1376         if (xmlTextWriterWriteAttribute(writer, BAD_CAST "id", BAD_CAST playlist_id) < 0) {
1377             return -1;
1378         }
1379 
1380         if (xmlTextWriterEndElement(writer) < 0) {
1381             return -1;
1382         }
1383     }
1384 
1385     if (xmlTextWriterEndDocument(writer) < 0) {
1386         return -1;
1387     }
1388 
1389     xmlFreeTextWriter(writer);
1390 
1391     xml_xpath = mp3tunes_locker_api_post_fetch(obj, MP3TUNES_SERVER_API, "api/v1/lockerSync/", (char*)buf->content);
1392     if( xml_xpath == NULL)
1393         return -1;
1394 
1395     printf("Sync:\n%s\n", (const char *) buf->content);
1396 
1397     free(xml_xpath);
1398     xmlBufferFree(buf);
1399     return 0;
1400 }
1401 
mp3tunes_locker_generate_track_from_file_key(mp3tunes_locker_object_t * obj,char * file_key,mp3tunes_locker_track_list_t ** tracks)1402 int mp3tunes_locker_generate_track_from_file_key(mp3tunes_locker_object_t *obj, char *file_key, mp3tunes_locker_track_list_t **tracks ) {
1403     xml_xpath_t* xml_xpath;
1404     xmlXPathObjectPtr xpath_obj;
1405     xmlNodeSetPtr nodeset;
1406     xmlNodePtr node;
1407     int i;
1408 
1409     xml_xpath = mp3tunes_locker_api_simple_fetch(obj, MP3TUNES_SERVER_API, "api/v1/lockerData/", "type", "track", "key", file_key, NULL);
1410 
1411     mp3tunes_locker_track_list_init(tracks);
1412 
1413     if (xml_xpath == NULL) {
1414         return -1;
1415     }
1416 
1417     xpath_obj = xml_xpath_query(xml_xpath, "/mp3tunes/trackList/item");
1418 
1419     if (xpath_obj == NULL) {
1420         return -1;
1421     }
1422 
1423     nodeset = xpath_obj->nodesetval;
1424 
1425     for (i = 0; i < nodeset->nodeNr; i++) {
1426         node = nodeset->nodeTab[i];
1427         xml_xpath_t* xml_xpath_context = xml_xpath_context_init(xml_xpath, node);
1428         mp3tunes_locker_track_t *track = (mp3tunes_locker_track_t*)malloc(sizeof(mp3tunes_locker_track_t));
1429         memset(track, 0, sizeof(mp3tunes_locker_track_t));
1430 
1431         track->trackId = xml_xpath_get_integer(xml_xpath_context, "trackId");
1432         track->trackTitle = xml_xpath_get_string(xml_xpath_context, "trackTitle");
1433         track->trackNumber = xml_xpath_get_integer(xml_xpath_context, "trackNumber");
1434         track->trackLength = xml_xpath_get_float(xml_xpath_context, "trackLength");
1435         track->trackFileName = xml_xpath_get_string(xml_xpath_context, "trackFileName");
1436         track->trackFileKey = xml_xpath_get_string(xml_xpath_context, "trackFileKey");
1437         track->trackFileSize = xml_xpath_get_integer(xml_xpath_context, "trackFileSize");
1438         track->downloadURL = xml_xpath_get_string(xml_xpath_context, "downloadURL");
1439         track->playURL = xml_xpath_get_string(xml_xpath_context, "playURL");
1440         track->albumId = xml_xpath_get_integer(xml_xpath_context, "albumId");
1441         track->albumTitle = xml_xpath_get_string(xml_xpath_context, "albumTitle");
1442         track->albumYear = xml_xpath_get_integer(xml_xpath_context, "albumYear");
1443         track->artistName = xml_xpath_get_string(xml_xpath_context, "artistName");
1444         track->artistId = xml_xpath_get_integer(xml_xpath_context, "artistId");
1445 
1446         mp3tunes_locker_track_list_add(tracks, track);
1447         xml_xpath_deinit(xml_xpath_context);
1448     }
1449     xmlXPathFreeObject(xpath_obj);
1450     xml_xpath_deinit(xml_xpath);
1451     return 0;
1452 
1453 }
1454 
mp3tunes_locker_generate_filekey(const char * filename)1455 char* mp3tunes_locker_generate_filekey(const char *filename) {
1456   return md5_calc_file_signature(filename);
1457 }
1458 
mp3tunes_locker_upload_track(mp3tunes_locker_object_t * obj,const char * path)1459 int mp3tunes_locker_upload_track(mp3tunes_locker_object_t *obj, const char *path) {
1460     request_t *request;
1461     FILE * hd_src ;
1462     int hd ;
1463     struct stat file_info;
1464     char* file_key = mp3tunes_locker_generate_filekey(path);
1465 
1466     if (file_key == NULL)
1467         return -1;
1468 
1469     /* get the file size of the local file */
1470     hd = open(path, O_RDONLY);
1471     if (hd == -1) {
1472         free(file_key);
1473         return -1;
1474     }
1475 
1476     fstat(hd, &file_info);
1477     close(hd);
1478     /* get a FILE * of the same file*/
1479     hd_src = fopen(path, "rb");
1480 
1481     /* create the request url */
1482     char *url = malloc(256*sizeof(char));
1483     snprintf(url, 256, "storage/lockerput/%s", file_key);
1484     free(file_key);
1485     request = mp3tunes_locker_api_generate_request(obj, MP3TUNES_SERVER_CONTENT, url, NULL);
1486     if (request == NULL) {
1487         fclose(hd_src);
1488         return -1;
1489     }
1490 
1491     /*chunk_init(&chunk);*/
1492     /*curl_easy_setopt( request->curl, CURLOPT_READFUNCTION, read_callback);*/
1493     curl_easy_setopt( request->curl, CURLOPT_UPLOAD, 1L);
1494     curl_easy_setopt( request->curl, CURLOPT_PUT, 1L);
1495     curl_easy_setopt( request->curl, CURLOPT_URL, request->url);
1496     curl_easy_setopt( request->curl, CURLOPT_READDATA, hd_src);
1497     curl_easy_setopt( request->curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_info.st_size);
1498     curl_easy_setopt( request->curl, CURLOPT_USERAGENT, "liboboe/1.0" );
1499     /*printf("uploading...\n");*/
1500     /* this returns a CURLcode which should probably be checked for success etc... */
1501     curl_easy_perform(request->curl);
1502 /*    curl_easy_cleanup(request->curl); */
1503     mp3tunes_request_deinit(&request);
1504     free(url);
1505 
1506     fclose(hd_src); /* close the local file */
1507     return 0;
1508 }
1509 
mp3tunes_locker_load_track(mp3tunes_locker_object_t * obj,const char * url)1510 int mp3tunes_locker_load_track(mp3tunes_locker_object_t *obj, const char *url) {
1511     xml_xpath_t* xml_xpath;
1512     char *status;
1513     xml_xpath = mp3tunes_locker_api_simple_fetch(obj, MP3TUNES_SERVER_LOGIN, "api/v0/lockerLoad/", "email", obj->username, "url", url, "sid", obj->session_id, NULL);
1514 
1515     if (xml_xpath == NULL) {
1516         return -2;
1517     }
1518 
1519     status = xml_xpath_get_string(xml_xpath, "/mp3tunes/status");
1520 
1521     if (status[0] != '1') {
1522         /*printf("status is %s\n", status);*/
1523         char* error = xml_xpath_get_string(xml_xpath, "/mp3tunes/errorMessage");
1524         /*printf("error is %s\n", error);*/
1525         obj->error_message = error;
1526         free(status);
1527         xml_xpath_deinit(xml_xpath);
1528         return -1;
1529     }
1530     free(status);
1531     xml_xpath_deinit(xml_xpath);
1532 
1533     return 0;
1534 
1535 }
1536