File indexing completed on 2025-01-05 04:27:02

0001  /*
0002  * Copyright (C) 2008 MP3tunes, LLC
0003  *
0004  * This library is free software; you can redistribute it and/or
0005  * modify it under the terms of the GNU Lesser General Public
0006  * License as published by the Free Software Foundation; either
0007  * version 2.1 of the License, or (at your option) any later version.
0008  *
0009  * This library is distributed in the hope that it will be useful,
0010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012  * Lesser General Public License for more details.
0013  *
0014  * You should have received a copy of the GNU Lesser General Public
0015  * License along with this library; if not, write to the Free Software
0016  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
0017 */
0018 
0019 #ifndef _GNU_SOURCE
0020 #define _GNU_SOURCE
0021 #endif
0022 #include <string.h>
0023 #include <stdlib.h>
0024 #include <sys/stat.h>
0025 #include <fcntl.h>
0026 #include <unistd.h>
0027 #include <curl/curl.h>
0028 #include <libxml/encoding.h>
0029 #include <libxml/xmlwriter.h>
0030 #include <libxml/xmlreader.h>
0031 #include <libxml/xpath.h>
0032 #include "locker.h"
0033 #include "md5.h"
0034 
0035 typedef struct {
0036     char *data;
0037     size_t size;
0038     int offset;
0039 } chunk_t;
0040 
0041 typedef struct {
0042     CURL *curl;
0043     char *url;
0044 } request_t;
0045 
0046 void chunk_init(chunk_t** chunk) {
0047     chunk_t *c = *chunk = (chunk_t*)malloc(sizeof(chunk_t));
0048     c->data = NULL;
0049     c->size = 0;
0050 }
0051 
0052 void chunk_set_data(chunk_t* chunk, char* data) {
0053     chunk->data = data;
0054     chunk->size = strlen(data);
0055 }
0056 
0057 void chunk_deinit(chunk_t** chunk) {
0058     chunk_t *c = *chunk;
0059     free(c->data);
0060     free(c);
0061 }
0062 
0063 struct xml_xpath_s {
0064     xmlDocPtr document;
0065     xmlXPathContextPtr xpath_ctx;
0066     xmlNodePtr context;
0067 };
0068 
0069 typedef struct xml_xpath_s xml_xpath_t;
0070 
0071 size_t write_chunk_callback( void *ptr, size_t size, size_t nmemb, void *data ) {
0072     size_t realsize = size * nmemb;
0073     chunk_t *chunk = (chunk_t *)data;
0074     chunk->data = (char *)realloc( chunk->data, chunk->size + realsize + 1 );
0075     if( chunk->data != NULL ) {
0076         memcpy( &(chunk->data[ chunk->size ]), ptr, realsize );
0077         chunk->size += realsize;
0078         chunk->data[ chunk->size ] = 0;
0079     }
0080 
0081     return realsize;
0082 }
0083 
0084 xml_xpath_t* xml_xpath_init(xmlDocPtr document) {
0085     xml_xpath_t *result = malloc(sizeof(xml_xpath_t));
0086     if (result == NULL)
0087         return NULL;
0088 
0089     result->document = document;
0090     result->xpath_ctx = xmlXPathNewContext(result->document);
0091     if(result->xpath_ctx == NULL) {
0092         xmlFreeDoc(result->document);
0093         free(result);
0094         return NULL;
0095     }
0096     result->context = NULL;
0097 
0098     return result;
0099 }
0100 
0101 xml_xpath_t* xml_xpath_context_init(xml_xpath_t* xml_xpath, xmlNodePtr node) {
0102     xml_xpath_t *result = malloc(sizeof(xml_xpath_t));
0103     if (result == NULL)
0104         return NULL;
0105 
0106     result->document = xml_xpath->document;
0107     result->xpath_ctx = xmlXPathNewContext(result->document);
0108     if(result->xpath_ctx == NULL) {
0109         xmlFreeDoc(result->document);
0110         free(result);
0111         return NULL;
0112     }
0113     result->xpath_ctx->node = node;
0114     result->context = node;
0115 
0116     return result;
0117 }
0118 
0119 void xml_xpath_deinit(xml_xpath_t* xml_xpath) {
0120     xmlXPathFreeContext(xml_xpath->xpath_ctx);
0121     if (xml_xpath->context == NULL) {
0122         xmlFreeDoc(xml_xpath->document);
0123     }
0124     free(xml_xpath);
0125 }
0126 
0127 xmlXPathObjectPtr xml_xpath_query(xml_xpath_t *xml_xpath, const char* xpath_expression) {
0128     xmlXPathObjectPtr xpath_obj;
0129 
0130     xpath_obj = xmlXPathEvalExpression((xmlChar*)xpath_expression, xml_xpath->xpath_ctx);
0131     if (xpath_obj == NULL) {
0132         return NULL;
0133     }
0134     if (xpath_obj->type != XPATH_NODESET) {
0135         xmlXPathFreeObject(xpath_obj);
0136         return NULL;
0137     }
0138     return xpath_obj;
0139 }
0140 
0141 char* xml_get_text_from_nodeset(xmlNodeSetPtr nodeset) {
0142     xmlNodePtr node;
0143     xmlNodePtr child;
0144     int total_nodes;
0145     char* result = NULL;
0146     total_nodes = (nodeset) ? nodeset->nodeNr : 0;
0147 
0148     if (total_nodes != 1) {
0149         return NULL;
0150     }
0151 
0152     if (nodeset->nodeTab[0]->type != XML_ELEMENT_NODE) {
0153         return NULL;
0154     }
0155 
0156     node = nodeset->nodeTab[0];
0157     child = node->children;
0158     while (child && (XML_TEXT_NODE != child->type))
0159         child = child->next;
0160     if (child && (XML_TEXT_NODE == child->type)) {
0161         result = strdup((char*)child->content);
0162     }
0163     return result;
0164 }
0165 
0166 static char* xml_xpath_get_string(xml_xpath_t *xml_xpath, const char* xpath_expression) {
0167     xmlXPathObjectPtr xpath_obj;
0168     char* result = NULL;
0169 
0170     xpath_obj = xml_xpath_query(xml_xpath, xpath_expression);
0171     if (xpath_obj == NULL)
0172         return NULL;
0173 
0174     result = xml_get_text_from_nodeset(xpath_obj->nodesetval);
0175 
0176     xmlXPathFreeObject(xpath_obj);
0177 
0178     return result;
0179 }
0180 
0181 int xml_xpath_get_integer(xml_xpath_t *xml_xpath, const char* xpath_expression) {
0182     int result = 0;
0183     char* str = xml_xpath_get_string(xml_xpath, xpath_expression);
0184     if (str != NULL) {
0185         result = atoi(str);
0186     }
0187     free(str);
0188     return result;
0189 }
0190 
0191 float xml_xpath_get_float(xml_xpath_t *xml_xpath, const char* xpath_expression) {
0192     float result = 0.0;
0193     char* str = xml_xpath_get_string(xml_xpath, xpath_expression);
0194     if (str != NULL) {
0195         result = atof(str);
0196     }
0197     free(str);
0198     return result;
0199 }
0200 
0201 int mp3tunes_locker_init( mp3tunes_locker_object_t **obj, const char *partner_token ) {
0202     mp3tunes_locker_object_t *o = *obj = (mp3tunes_locker_object_t*)malloc(sizeof(mp3tunes_locker_object_t));
0203     memset(o, 0, sizeof(*o));
0204 
0205     o->partner_token = strdup(partner_token);
0206     o->session_id = NULL;
0207     o->error_message = NULL;
0208 
0209     o->server_api = getenv("MP3TUNES_SERVER_API");
0210     if(o->server_api == NULL) {
0211         o->server_api = strdup(MP3TUNES_SERVER_API_URL);
0212     }
0213 
0214     o->server_content = getenv("MP3TUNES_SERVER_CONTENT");
0215     if(o->server_content == NULL) {
0216         o->server_content = strdup(MP3TUNES_SERVER_CONTENT_URL);
0217     }
0218 
0219     o->server_login = getenv("MP3TUNES_SERVER_LOGIN");
0220     if(o->server_login == NULL) {
0221         o->server_login = strdup(MP3TUNES_SERVER_LOGIN_URL);
0222     }
0223 
0224     return TRUE;
0225 }
0226 
0227 int mp3tunes_locker_deinit( mp3tunes_locker_object_t **obj ) {
0228     mp3tunes_locker_object_t *o = *obj;
0229     free(o->partner_token);
0230     free(o->session_id);
0231     free(o->error_message);
0232     free(o);
0233     return TRUE;
0234 }
0235 
0236 void mp3tunes_request_init(request_t **request) {
0237     request_t *r = *request = malloc(sizeof(request_t));
0238     r->curl = curl_easy_init();
0239     r->url = NULL;
0240 }
0241 
0242 void mp3tunes_request_deinit(request_t **request) {
0243     request_t *r = *request;
0244     curl_easy_cleanup(r->curl);
0245     free(r->url);
0246     free(r);
0247 }
0248 
0249 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) {
0250     request_t *request;
0251     char *server_url;
0252     char *name, *value;
0253     char *encoded_name, *encoded_value;
0254 
0255     mp3tunes_request_init(&request);
0256 
0257     switch (server) {
0258         case MP3TUNES_SERVER_LOGIN:
0259             server_url = obj->server_login;
0260             break;
0261         case MP3TUNES_SERVER_CONTENT:
0262             server_url = obj->server_content;
0263             break;
0264         case MP3TUNES_SERVER_API:
0265             server_url = obj->server_api;
0266             break;
0267         default:
0268             mp3tunes_request_deinit(&request);
0269             return NULL;
0270             break;
0271     }
0272 
0273     char *url = 0;
0274     size_t url_size = asprintf(&url, "http://%s/%s?", server_url, path) +1;
0275     name = (char*) first_name;
0276     while (name) {
0277         char *url_part;
0278 
0279         value = va_arg(argp, char*);
0280 
0281         encoded_name = curl_easy_escape(request->curl, name, 0);
0282         encoded_value = curl_easy_escape(request->curl, value, 0);
0283         size_t url_part_size = asprintf(&url_part, "%s=%s&", encoded_name, encoded_value);
0284         curl_free(encoded_name);
0285         curl_free(encoded_value);
0286 
0287     url = realloc(url, url_size += url_part_size);
0288         strcat(url, url_part);
0289 
0290         name = va_arg(argp, char*);
0291     }
0292 
0293     char *end_url_part = NULL;
0294     size_t end_url_part_size = 0;
0295     if (server != MP3TUNES_SERVER_LOGIN) {
0296         if (obj->session_id != NULL) {
0297             if (server == MP3TUNES_SERVER_API) {
0298                 end_url_part_size = asprintf(&end_url_part, "output=xml&sid=%s&partner_token=%s", obj->session_id, obj->partner_token);
0299             } else {
0300                 end_url_part_size = asprintf(&end_url_part, "sid=%s&partner_token=%s", obj->session_id, obj->partner_token);
0301             }
0302         } else {
0303             printf("Failed because of no session id\n");
0304             free(url);
0305             mp3tunes_request_deinit(&request);
0306             return NULL;
0307         }
0308     } else {
0309         end_url_part_size = asprintf(&end_url_part, "output=xml&partner_token=%s", obj->partner_token);
0310     }
0311     url = realloc(url, url_size += end_url_part_size);
0312     strcat(url, end_url_part);
0313 
0314     request->url = url;
0315     return request;
0316 
0317 }
0318 
0319 static request_t* mp3tunes_locker_api_generate_request(mp3tunes_locker_object_t *obj, int server, const char* path, const char* first_name, ...) {
0320     va_list argp;
0321     request_t *request;
0322     va_start(argp, first_name);
0323     request = mp3tunes_locker_api_generate_request_valist(obj, server, path, first_name, argp);
0324     va_end(argp);
0325     return request;
0326 }
0327 
0328 static xml_xpath_t* mp3tunes_locker_api_simple_fetch(mp3tunes_locker_object_t *obj, int server, const char* path, const char* first_name, ...) {
0329     request_t *request;
0330     CURLcode res;
0331     chunk_t *chunk;
0332     va_list argp;
0333 
0334     chunk_init(&chunk);
0335 
0336     va_start(argp, first_name);
0337 
0338     request = mp3tunes_locker_api_generate_request_valist(obj, server, path, first_name, argp);
0339 
0340     va_end(argp);
0341 
0342     if (request == NULL) {
0343         chunk_deinit(&chunk);
0344         return NULL;
0345     }
0346 
0347     curl_easy_setopt( request->curl, CURLOPT_URL, request->url );
0348     curl_easy_setopt( request->curl, CURLOPT_WRITEFUNCTION, write_chunk_callback );
0349     curl_easy_setopt( request->curl, CURLOPT_WRITEDATA, (void *)chunk );
0350     curl_easy_setopt( request->curl, CURLOPT_USERAGENT, "liboboe/1.0" );
0351     curl_easy_setopt( request->curl, CURLOPT_NOPROGRESS, 1 );
0352 
0353     res = curl_easy_perform(request->curl);
0354 /*    curl_easy_cleanup(request->curl); */
0355     mp3tunes_request_deinit(&request);
0356 
0357     if (res != CURLE_OK) {
0358         chunk_deinit(&chunk);
0359         return NULL;
0360     }
0361 
0362     if (chunk->data == NULL) {
0363         return NULL;
0364     }
0365 
0366     /*printf("Fetch result:\n%s\n", chunk->data);*/
0367 
0368     xmlDocPtr document = xmlParseDoc((xmlChar*)chunk->data);
0369 
0370     chunk_deinit(&chunk);
0371 
0372     if (document == NULL) {
0373         return NULL;
0374     }
0375 
0376     return xml_xpath_init(document);
0377 }
0378 
0379 static xml_xpath_t* mp3tunes_locker_api_post_fetch(mp3tunes_locker_object_t *obj, int server, const char* path, char* post_data) {
0380     request_t *request;
0381     CURLcode res;
0382     chunk_t *chunk;
0383 
0384     chunk_init(&chunk);
0385 
0386     request = mp3tunes_locker_api_generate_request(obj, server, path, NULL);
0387     if (request == NULL) {
0388         chunk_deinit(&chunk);
0389         return NULL;
0390     }
0391 
0392     curl_easy_setopt( request->curl, CURLOPT_URL, request->url );
0393     curl_easy_setopt( request->curl, CURLOPT_WRITEFUNCTION, write_chunk_callback );
0394     curl_easy_setopt( request->curl, CURLOPT_WRITEDATA, (void *)chunk );
0395     curl_easy_setopt( request->curl, CURLOPT_USERAGENT, "liboboe/1.0" );
0396     curl_easy_setopt( request->curl, CURLOPT_POSTFIELDS, post_data);
0397     curl_easy_setopt( request->curl, CURLOPT_NOPROGRESS, 1 );
0398 
0399     res = curl_easy_perform(request->curl);
0400 /*    curl_easy_cleanup(request->curl); */
0401     mp3tunes_request_deinit(&request);
0402 
0403     if (res != CURLE_OK) {
0404         chunk_deinit(&chunk);
0405         return NULL;
0406     }
0407 
0408     if (chunk->data == NULL) {
0409         return NULL;
0410     }
0411 
0412     printf("Fetch result:\n%s\n", chunk->data);
0413 
0414     xmlDocPtr document = xmlParseDoc((xmlChar*)chunk->data);
0415 
0416     chunk_deinit(&chunk);
0417 
0418     if (document == NULL) {
0419         return NULL;
0420     }
0421 
0422     return xml_xpath_init(document);
0423 }
0424 
0425 char* mp3tunes_locker_generate_download_url_from_file_key(mp3tunes_locker_object_t *obj, char *file_key) {
0426     request_t *request;
0427     char *path = malloc(256*sizeof(char));
0428     char *ret;
0429     snprintf(path, 256, "storage/lockerget/%s", file_key);
0430     request = mp3tunes_locker_api_generate_request(obj, MP3TUNES_SERVER_CONTENT, path, NULL);
0431     ret = request->url; request->url = NULL;
0432     free(path);
0433     mp3tunes_request_deinit(&request);
0434     return ret;
0435 }
0436 
0437 char* mp3tunes_locker_generate_download_url_from_file_key_and_bitrate(mp3tunes_locker_object_t *obj, char *file_key, char* bitrate) {
0438     request_t *request;
0439     char *path = malloc(256*sizeof(char));
0440     char *ret;
0441     snprintf(path, 256, "storage/lockerget/%s", file_key);
0442     request = mp3tunes_locker_api_generate_request(obj, MP3TUNES_SERVER_CONTENT, path, "bitrate", bitrate, NULL);
0443     ret = request->url; request->url = NULL;
0444     free(path);
0445     mp3tunes_request_deinit(&request);
0446     return ret;
0447 }
0448 
0449 
0450 int mp3tunes_locker_login(mp3tunes_locker_object_t *obj, const char* username, const char* password) {
0451     xml_xpath_t* xml_xpath;
0452     char *status, *session_id;
0453 
0454     xml_xpath = mp3tunes_locker_api_simple_fetch(obj, MP3TUNES_SERVER_LOGIN, "api/v1/login/", "username", username, "password", password, NULL);
0455 
0456     if (xml_xpath == NULL) {
0457         return -2;
0458     }
0459 
0460     status = xml_xpath_get_string(xml_xpath, "/mp3tunes/status");
0461 
0462     if (status[0] != '1') {
0463       /*printf("status is %s\n", status);*/
0464         char* error = xml_xpath_get_string(xml_xpath, "/mp3tunes/errorMessage");
0465         /*printf("error is %s\n", error);*/
0466         obj->error_message = error;
0467         free(status);
0468         xml_xpath_deinit(xml_xpath);
0469         return -1;
0470     }
0471     free(status);
0472 
0473     session_id = xml_xpath_get_string(xml_xpath, "/mp3tunes/session_id");
0474     obj->username = strdup(username);
0475     obj->password = strdup(password);
0476     obj->session_id = session_id;
0477     xml_xpath_deinit(xml_xpath);
0478 
0479     return 0;
0480 }
0481 
0482 int mp3tunes_locker_session_valid(mp3tunes_locker_object_t *obj) {
0483 
0484     request_t *request;
0485     CURLcode res;
0486     chunk_t *chunk;
0487 
0488     chunk_init(&chunk);
0489 
0490     request = mp3tunes_locker_api_generate_request(obj, MP3TUNES_SERVER_API, "api/v1/accountData", NULL);
0491     if (request == NULL) {
0492         chunk_deinit(&chunk);
0493         return -1;
0494     }
0495 
0496     curl_easy_setopt( request->curl, CURLOPT_URL, request->url );
0497     curl_easy_setopt( request->curl, CURLOPT_WRITEFUNCTION, write_chunk_callback );
0498     curl_easy_setopt( request->curl, CURLOPT_WRITEDATA, (void *)chunk );
0499     curl_easy_setopt( request->curl, CURLOPT_NOBODY, 1 );
0500     curl_easy_setopt( request->curl, CURLOPT_USERAGENT, "liboboe/1.0" );
0501     curl_easy_setopt( request->curl, CURLOPT_HEADER, 1 );
0502     curl_easy_setopt( request->curl, CURLOPT_NOPROGRESS, 1 );
0503 
0504     res = curl_easy_perform(request->curl);
0505 /*    curl_easy_cleanup(request->curl); */
0506     mp3tunes_request_deinit(&request);
0507 
0508     if (res != CURLE_OK) {
0509         chunk_deinit(&chunk);
0510         return -1;
0511     }
0512 
0513     if (chunk->data == NULL) {
0514         return -1;
0515     }
0516 
0517     char name[] = "X-MP3tunes-ErrorNo";
0518     char value[] = "401001";
0519     char *result = strstr (chunk->data, name);
0520     if (result != 0)
0521     {
0522         int i = strcspn(result, "\n");
0523         char *result1 = malloc(i + 1);
0524         if (result1 == NULL)
0525             return -1;
0526 
0527         /* ensure result1 is null-terminated */
0528         snprintf(result1, i+1, "%s", result);
0529         /*printf("Header String: %s\n", result1);*/
0530         result = strstr(result1, value);
0531         free(result1);
0532         if (result != 0) /* i.e., value could not be located hence there is no 404 error. */
0533             return -1; /* session is invalid*/
0534     }
0535 
0536     /*printf("Fetch result:\n%s\n", chunk->data);*/
0537     return 0; /* session is valid*/
0538 }
0539 
0540 int mp3tunes_locker_list_init(struct mp3tunes_locker_list_s **list) {
0541     struct mp3tunes_locker_list_s *l = *list = (struct mp3tunes_locker_list_s*)malloc(sizeof(struct mp3tunes_locker_list_s));
0542     l->last_id = 0;
0543     l->first = l->last = NULL;
0544     return 0;
0545 }
0546 
0547 int mp3tunes_locker_track_list_init(mp3tunes_locker_track_list_t **list) {
0548     return mp3tunes_locker_list_init((struct mp3tunes_locker_list_s**)list);
0549 }
0550 
0551 int mp3tunes_locker_artist_list_init(mp3tunes_locker_artist_list_t **list) {
0552     return mp3tunes_locker_list_init((struct mp3tunes_locker_list_s**)list);
0553 }
0554 
0555 int mp3tunes_locker_album_list_init(mp3tunes_locker_album_list_t **list) {
0556     return mp3tunes_locker_list_init((struct mp3tunes_locker_list_s**)list);
0557 }
0558 
0559 int mp3tunes_locker_playlist_list_init(mp3tunes_locker_playlist_list_t **list) {
0560     return mp3tunes_locker_list_init((struct mp3tunes_locker_list_s**)list);
0561 }
0562 
0563 int mp3tunes_locker_list_add(struct mp3tunes_locker_list_s **list, void* value) {
0564     struct mp3tunes_locker_list_s *l = *list;
0565     mp3tunes_locker_list_item_t *item = (mp3tunes_locker_list_item_t*)malloc(sizeof(mp3tunes_locker_list_item_t));
0566     item->id = l->last_id++;
0567     item->prev = l->last;
0568     item->next = NULL;
0569     item->value = value;
0570 
0571     if (l->first) {
0572         l->last = item->prev->next = item;
0573     } else {
0574         l->first = l->last = item;
0575     }
0576 
0577     return 0;
0578 }
0579 
0580 int mp3tunes_locker_track_list_add(mp3tunes_locker_track_list_t **list, mp3tunes_locker_track_t *track) {
0581     return mp3tunes_locker_list_add((struct mp3tunes_locker_list_s**)list, (void*)track);
0582 }
0583 
0584 int mp3tunes_locker_artist_list_add(mp3tunes_locker_artist_list_t **list, mp3tunes_locker_artist_t *artist) {
0585     return mp3tunes_locker_list_add((struct mp3tunes_locker_list_s**)list, (void*)artist);
0586 }
0587 
0588 int mp3tunes_locker_album_list_add(mp3tunes_locker_album_list_t **list, mp3tunes_locker_album_t *album) {
0589     return mp3tunes_locker_list_add((struct mp3tunes_locker_list_s**)list, (void*)album);
0590 }
0591 
0592 int mp3tunes_locker_playlist_list_add(mp3tunes_locker_playlist_list_t **list, mp3tunes_locker_playlist_t *album) {
0593     return mp3tunes_locker_list_add((struct mp3tunes_locker_list_s**)list, (void*)album);
0594 }
0595 
0596 int mp3tunes_locker_list_deinit(struct mp3tunes_locker_list_s **list) {
0597     struct mp3tunes_locker_list_s *l = *list;
0598     if (l) {
0599         mp3tunes_locker_list_item_t *list_item = l->first;
0600         while(l->first) {
0601             list_item = l->first->next;
0602             free(l->first);
0603             l->first = list_item;
0604         }
0605         free(l);
0606         return 0;
0607     }
0608     return -1;
0609 }
0610 
0611 int mp3tunes_locker_track_list_deinit(mp3tunes_locker_track_list_t **track_list) {
0612     mp3tunes_locker_track_list_t *list = *track_list;
0613     mp3tunes_locker_list_item_t *track_item = list->first;
0614     mp3tunes_locker_track_t *track;
0615 
0616     while (track_item != NULL) {
0617         track = (mp3tunes_locker_track_t*)track_item->value;
0618         free(track->trackTitle);
0619         free(track->trackFileName);
0620         free(track->trackFileKey);
0621         free(track->downloadURL);
0622         free(track->playURL);
0623         free(track->albumTitle);
0624         free(track->artistName);
0625 
0626         free(track);
0627         track_item = track_item->next;
0628     }
0629     return mp3tunes_locker_list_deinit((struct mp3tunes_locker_list_s**)track_list);
0630 }
0631 
0632 int mp3tunes_locker_artist_list_deinit(mp3tunes_locker_artist_list_t **artist_list) {
0633     mp3tunes_locker_artist_list_t *list = *artist_list;
0634     mp3tunes_locker_list_item_t *artist_item = list->first;
0635     mp3tunes_locker_artist_t *artist;
0636 
0637     while (artist_item != NULL) {
0638         artist = (mp3tunes_locker_artist_t*)artist_item->value;
0639         free(artist->artistName);
0640 
0641         free(artist);
0642         artist_item = artist_item->next;
0643     }
0644     return mp3tunes_locker_list_deinit((struct mp3tunes_locker_list_s**)artist_list);
0645 }
0646 
0647 int mp3tunes_locker_album_list_deinit(mp3tunes_locker_album_list_t **album_list) {
0648     mp3tunes_locker_album_list_t *list = *album_list;
0649     mp3tunes_locker_list_item_t *album_item = list->first;
0650     mp3tunes_locker_album_t *album;
0651 
0652     while (album_item != NULL) {
0653         album = (mp3tunes_locker_album_t*)album_item->value;
0654         free(album->albumTitle);
0655         free(album->artistName);
0656 
0657         free(album);
0658         album_item = album_item->next;
0659     }
0660     return mp3tunes_locker_list_deinit((struct mp3tunes_locker_list_s**)album_list);
0661 }
0662 
0663 int mp3tunes_locker_playlist_list_deinit(mp3tunes_locker_playlist_list_t **playlist_list) {
0664     mp3tunes_locker_playlist_list_t *list = *playlist_list;
0665     mp3tunes_locker_list_item_t *playlist_item = list->first;
0666     mp3tunes_locker_playlist_t *playlist;
0667 
0668     while (playlist_item != NULL) {
0669         playlist = (mp3tunes_locker_playlist_t*)playlist_item->value;
0670         free(playlist->playlistId);
0671         free(playlist->playlistTitle);
0672         free(playlist->title);
0673         free(playlist->fileName);
0674 
0675         free(playlist);
0676         playlist_item = playlist_item->next;
0677     }
0678     return mp3tunes_locker_list_deinit((struct mp3tunes_locker_list_s**)playlist_list);
0679 }
0680 
0681 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) {
0682     xml_xpath_t* xml_xpath;
0683     xmlXPathObjectPtr xpath_obj;
0684     xmlNodeSetPtr nodeset;
0685     xmlNodePtr node;
0686     int i;
0687     char artist_id_s[15];
0688     char album_id_s[15];
0689 
0690     if (playlist_id == NULL) {
0691         if (artist_id == -1 && album_id == -1) {
0692             xml_xpath = mp3tunes_locker_api_simple_fetch(obj, MP3TUNES_SERVER_API, "api/v1/lockerData/", "type", "track", NULL);
0693         } else if (artist_id != -1 && album_id == -1) {
0694             snprintf(artist_id_s, 15, "%d", artist_id);
0695             xml_xpath = mp3tunes_locker_api_simple_fetch(obj, MP3TUNES_SERVER_API, "api/v1/lockerData/", "type", "track", "artist_id", artist_id_s, NULL);
0696         } else if (artist_id == -1 && album_id != -1) {
0697             snprintf(album_id_s, 15, "%d", album_id);
0698             xml_xpath = mp3tunes_locker_api_simple_fetch(obj, MP3TUNES_SERVER_API, "api/v1/lockerData/", "type", "track", "album_id", album_id_s, NULL);
0699         } else {
0700             snprintf(artist_id_s, 15, "%d", artist_id);
0701             snprintf(album_id_s, 15, "%d", album_id);
0702             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);
0703         }
0704     } else {
0705         xml_xpath = mp3tunes_locker_api_simple_fetch(obj, MP3TUNES_SERVER_API, "api/v1/lockerData/", "type", "track", "playlist_id", playlist_id, NULL);
0706     }
0707 
0708     mp3tunes_locker_track_list_init(tracks);
0709 
0710     if (xml_xpath == NULL) {
0711         return -1;
0712     }
0713 
0714     xpath_obj = xml_xpath_query(xml_xpath, "/mp3tunes/trackList/item");
0715 
0716     if (xpath_obj == NULL) {
0717         return -1;
0718     }
0719 
0720     nodeset = xpath_obj->nodesetval;
0721 
0722     for (i = 0; i < nodeset->nodeNr; i++) {
0723         node = nodeset->nodeTab[i];
0724         xml_xpath_t* xml_xpath_context = xml_xpath_context_init(xml_xpath, node);
0725         mp3tunes_locker_track_t *track = (mp3tunes_locker_track_t*)malloc(sizeof(mp3tunes_locker_track_t));
0726         memset(track, 0, sizeof(mp3tunes_locker_track_t));
0727 
0728         track->trackId = xml_xpath_get_integer(xml_xpath_context, "trackId");
0729         track->trackTitle = xml_xpath_get_string(xml_xpath_context, "trackTitle");
0730         track->trackNumber = xml_xpath_get_integer(xml_xpath_context, "trackNumber");
0731         track->trackLength = xml_xpath_get_float(xml_xpath_context, "trackLength");
0732         track->trackFileName = xml_xpath_get_string(xml_xpath_context, "trackFileName");
0733         track->trackFileKey = xml_xpath_get_string(xml_xpath_context, "trackFileKey");
0734         track->trackFileSize = xml_xpath_get_integer(xml_xpath_context, "trackFileSize");
0735         track->downloadURL = xml_xpath_get_string(xml_xpath_context, "downloadURL");
0736         track->playURL = xml_xpath_get_string(xml_xpath_context, "playURL");
0737         track->albumId = xml_xpath_get_integer(xml_xpath_context, "albumId");
0738         track->albumTitle = xml_xpath_get_string(xml_xpath_context, "albumTitle");
0739         track->albumYear = xml_xpath_get_integer(xml_xpath_context, "albumYear");
0740         track->artistName = xml_xpath_get_string(xml_xpath_context, "artistName");
0741         track->artistId = xml_xpath_get_integer(xml_xpath_context, "artistId");
0742 
0743         mp3tunes_locker_track_list_add(tracks, track);
0744         xml_xpath_deinit(xml_xpath_context);
0745     }
0746     xmlXPathFreeObject(xpath_obj);
0747     xml_xpath_deinit(xml_xpath);
0748     return 0;
0749 }
0750 
0751 int mp3tunes_locker_tracks_search( mp3tunes_locker_object_t *obj, mp3tunes_locker_track_list_t **tracks, char *search) {
0752     xml_xpath_t* xml_xpath;
0753     xmlXPathObjectPtr xpath_obj;
0754     xmlNodeSetPtr nodeset;
0755     xmlNodePtr node;
0756     int i;
0757 
0758     xml_xpath = mp3tunes_locker_api_simple_fetch(obj, MP3TUNES_SERVER_API, "api/v1/lockerSearch", "type", "track", "s", search, NULL);
0759 
0760     mp3tunes_locker_track_list_init(tracks);
0761 
0762     if (xml_xpath == NULL) {
0763         return -1;
0764     }
0765 
0766     xpath_obj = xml_xpath_query(xml_xpath, "/mp3tunes/trackList/item");
0767 
0768     if (xpath_obj == NULL) {
0769         return -1;
0770     }
0771 
0772     nodeset = xpath_obj->nodesetval;
0773 
0774     for (i = 0; i < nodeset->nodeNr; i++) {
0775         node = nodeset->nodeTab[i];
0776         xml_xpath_t* xml_xpath_context = xml_xpath_context_init(xml_xpath, node);
0777         mp3tunes_locker_track_t *track = (mp3tunes_locker_track_t*)malloc(sizeof(mp3tunes_locker_track_t));
0778         memset(track, 0, sizeof(mp3tunes_locker_track_t));
0779 
0780         track->trackId = xml_xpath_get_integer(xml_xpath_context, "trackId");
0781         track->trackTitle = xml_xpath_get_string(xml_xpath_context, "trackTitle");
0782         track->trackNumber = xml_xpath_get_integer(xml_xpath_context, "trackNumber");
0783         track->trackLength = xml_xpath_get_float(xml_xpath_context, "trackLength");
0784         track->trackFileName = xml_xpath_get_string(xml_xpath_context, "trackFileName");
0785         track->trackFileKey = xml_xpath_get_string(xml_xpath_context, "trackFileKey");
0786         track->trackFileSize = xml_xpath_get_integer(xml_xpath_context, "trackFileSize");
0787         track->downloadURL = xml_xpath_get_string(xml_xpath_context, "downloadURL");
0788         track->playURL = xml_xpath_get_string(xml_xpath_context, "playURL");
0789         track->albumId = xml_xpath_get_integer(xml_xpath_context, "albumId");
0790         track->albumTitle = xml_xpath_get_string(xml_xpath_context, "albumTitle");
0791         track->albumYear = xml_xpath_get_integer(xml_xpath_context, "albumYear");
0792         track->artistName = xml_xpath_get_string(xml_xpath_context, "artistName");
0793         track->artistId = xml_xpath_get_integer(xml_xpath_context, "artistId");
0794 
0795         mp3tunes_locker_track_list_add(tracks, track);
0796         xml_xpath_deinit(xml_xpath_context);
0797     }
0798     xmlXPathFreeObject(xpath_obj);
0799     xml_xpath_deinit(xml_xpath);
0800     return 0;
0801 }
0802 
0803 
0804 int mp3tunes_locker_tracks(mp3tunes_locker_object_t *obj, mp3tunes_locker_track_list_t **tracks) {
0805     return _mp3tunes_locker_tracks(obj, tracks, -1, -1, NULL);
0806 }
0807 
0808 int mp3tunes_locker_tracks_with_artist_id(mp3tunes_locker_object_t *obj, mp3tunes_locker_track_list_t **tracks, int artist_id) {
0809     return _mp3tunes_locker_tracks(obj, tracks, artist_id, -1, NULL);
0810 }
0811 
0812 int mp3tunes_locker_tracks_with_album_id(mp3tunes_locker_object_t *obj, mp3tunes_locker_track_list_t **tracks, int album_id) {
0813     return _mp3tunes_locker_tracks(obj, tracks, -1, album_id, NULL);
0814 }
0815 
0816 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) {
0817     return _mp3tunes_locker_tracks(obj, tracks, artist_id, album_id, NULL);
0818 }
0819 
0820 int mp3tunes_locker_tracks_with_playlist_id(mp3tunes_locker_object_t *obj, mp3tunes_locker_track_list_t **tracks, const char* playlist_id) {
0821     return _mp3tunes_locker_tracks(obj, tracks, -1, -1, playlist_id);
0822 }
0823 
0824 int mp3tunes_locker_tracks_with_file_key( mp3tunes_locker_object_t *obj, const char *file_keys, mp3tunes_locker_track_list_t **tracks ) {
0825     xml_xpath_t* xml_xpath;
0826     xmlXPathObjectPtr xpath_obj;
0827     xmlNodeSetPtr nodeset;
0828     xmlNodePtr node;
0829     int i;
0830 
0831     xml_xpath = mp3tunes_locker_api_simple_fetch(obj, MP3TUNES_SERVER_API, "api/v1/lockerData/", "type", "track", "key", file_keys, NULL);
0832 
0833     mp3tunes_locker_track_list_init(tracks);
0834 
0835     if (xml_xpath == NULL) {
0836         return -1;
0837     }
0838 
0839     xpath_obj = xml_xpath_query(xml_xpath, "/mp3tunes/trackList/item");
0840 
0841     if (xpath_obj == NULL) {
0842         return -1;
0843     }
0844 
0845     nodeset = xpath_obj->nodesetval;
0846 
0847     for (i = 0; i < nodeset->nodeNr; i++) {
0848         node = nodeset->nodeTab[i];
0849         xml_xpath_t* xml_xpath_context = xml_xpath_context_init(xml_xpath, node);
0850         mp3tunes_locker_track_t *track = (mp3tunes_locker_track_t*)malloc(sizeof(mp3tunes_locker_track_t));
0851         memset(track, 0, sizeof(mp3tunes_locker_track_t));
0852 
0853         track->trackId = xml_xpath_get_integer(xml_xpath_context, "trackId");
0854         track->trackTitle = xml_xpath_get_string(xml_xpath_context, "trackTitle");
0855         track->trackNumber = xml_xpath_get_integer(xml_xpath_context, "trackNumber");
0856         track->trackLength = xml_xpath_get_float(xml_xpath_context, "trackLength");
0857         track->trackFileName = xml_xpath_get_string(xml_xpath_context, "trackFileName");
0858         track->trackFileKey = xml_xpath_get_string(xml_xpath_context, "trackFileKey");
0859         track->trackFileSize = xml_xpath_get_integer(xml_xpath_context, "trackFileSize");
0860         track->downloadURL = xml_xpath_get_string(xml_xpath_context, "downloadURL");
0861         track->playURL = xml_xpath_get_string(xml_xpath_context, "playURL");
0862         track->albumId = xml_xpath_get_integer(xml_xpath_context, "albumId");
0863         track->albumTitle = xml_xpath_get_string(xml_xpath_context, "albumTitle");
0864         track->albumYear = xml_xpath_get_integer(xml_xpath_context, "albumYear");
0865         track->artistName = xml_xpath_get_string(xml_xpath_context, "artistName");
0866         track->artistId = xml_xpath_get_integer(xml_xpath_context, "artistId");
0867 
0868         mp3tunes_locker_track_list_add(tracks, track);
0869         xml_xpath_deinit(xml_xpath_context);
0870     }
0871     xmlXPathFreeObject(xpath_obj);
0872     xml_xpath_deinit(xml_xpath);
0873     return 0;   
0874 
0875 }
0876 
0877 int mp3tunes_locker_track_with_file_key( mp3tunes_locker_object_t *obj, const char *file_key, mp3tunes_locker_track_t **track ) {
0878     xml_xpath_t* xml_xpath;
0879     xmlXPathObjectPtr xpath_obj;
0880     xmlNodeSetPtr nodeset;
0881     xmlNodePtr node;
0882 
0883     xml_xpath = mp3tunes_locker_api_simple_fetch(obj, MP3TUNES_SERVER_API, "api/v1/lockerData/", "type", "track", "key", file_key, NULL);
0884 
0885     if (xml_xpath == NULL) {
0886         return -1;
0887     }
0888 
0889     xpath_obj = xml_xpath_query(xml_xpath, "/mp3tunes/trackList/item");
0890 
0891     if (xpath_obj == NULL) {
0892         return -1;
0893     }
0894 
0895     nodeset = xpath_obj->nodesetval;
0896     if ( nodeset->nodeNr == 1) {
0897         node = nodeset->nodeTab[0];
0898 
0899         xml_xpath_t* xml_xpath_context = xml_xpath_context_init(xml_xpath, node);
0900         mp3tunes_locker_track_t *t = *track = (mp3tunes_locker_track_t*)malloc(sizeof(mp3tunes_locker_track_t));
0901 
0902         t->trackId = xml_xpath_get_integer(xml_xpath_context, "trackId");
0903         t->trackTitle = xml_xpath_get_string(xml_xpath_context, "trackTitle");
0904         t->trackNumber = xml_xpath_get_integer(xml_xpath_context, "trackNumber");
0905         t->trackLength = xml_xpath_get_float(xml_xpath_context, "trackLength");
0906         t->trackFileName = xml_xpath_get_string(xml_xpath_context, "trackFileName");
0907         t->trackFileKey = xml_xpath_get_string(xml_xpath_context, "trackFileKey");
0908         t->trackFileSize = xml_xpath_get_integer(xml_xpath_context, "trackFileSize");
0909         t->downloadURL = xml_xpath_get_string(xml_xpath_context, "downloadURL");
0910         t->playURL = xml_xpath_get_string(xml_xpath_context, "playURL");
0911         t->albumId = xml_xpath_get_integer(xml_xpath_context, "albumId");
0912         t->albumTitle = xml_xpath_get_string(xml_xpath_context, "albumTitle");
0913         t->albumYear = xml_xpath_get_integer(xml_xpath_context, "albumYear");
0914         t->artistName = xml_xpath_get_string(xml_xpath_context, "artistName");
0915         t->artistId = xml_xpath_get_integer(xml_xpath_context, "artistId");
0916 
0917         xml_xpath_deinit(xml_xpath_context);
0918         xmlXPathFreeObject(xpath_obj);
0919         xml_xpath_deinit(xml_xpath);
0920         return 0;
0921     }
0922     xmlXPathFreeObject(xpath_obj);
0923     xml_xpath_deinit(xml_xpath);
0924     return -1;   
0925 }
0926 
0927 int mp3tunes_locker_artists(mp3tunes_locker_object_t *obj, mp3tunes_locker_artist_list_t **artists) {
0928     xml_xpath_t* xml_xpath;
0929     xmlXPathObjectPtr xpath_obj;
0930     xmlNodeSetPtr nodeset;
0931     xmlNodePtr node;
0932     int i;
0933 
0934     xml_xpath = mp3tunes_locker_api_simple_fetch(obj, MP3TUNES_SERVER_API, "api/v1/lockerData/", "type", "artist", NULL);
0935 
0936     mp3tunes_locker_artist_list_init(artists);
0937 
0938     if (xml_xpath == NULL) {
0939         return -1;
0940     }
0941 
0942     xpath_obj = xml_xpath_query(xml_xpath, "/mp3tunes/artistList/item");
0943     if (xpath_obj == NULL) {
0944         return -1;
0945     }
0946 
0947     nodeset = xpath_obj->nodesetval;
0948 
0949     for (i = 0; i < nodeset->nodeNr; i++) {
0950         node = nodeset->nodeTab[i];
0951         xml_xpath_t* xml_xpath_context = xml_xpath_context_init(xml_xpath, node);
0952         mp3tunes_locker_artist_t *artist = (mp3tunes_locker_artist_t*)malloc(sizeof(mp3tunes_locker_artist_t));
0953         memset(artist, 0, sizeof(mp3tunes_locker_artist_t));
0954 
0955         artist->artistId = xml_xpath_get_integer(xml_xpath_context, "artistId");
0956         artist->artistName = xml_xpath_get_string(xml_xpath_context, "artistName");
0957         artist->artistSize = xml_xpath_get_integer(xml_xpath_context, "artistSize");
0958         artist->albumCount = xml_xpath_get_integer(xml_xpath_context, "albumCount");
0959         artist->trackCount = xml_xpath_get_integer(xml_xpath_context, "trackCount");
0960 
0961         mp3tunes_locker_artist_list_add(artists, artist);
0962         xml_xpath_deinit(xml_xpath_context);
0963     }
0964     xmlXPathFreeObject(xpath_obj);
0965     xml_xpath_deinit(xml_xpath);
0966     return 0;
0967 }
0968 
0969 int mp3tunes_locker_artists_search( mp3tunes_locker_object_t *obj, mp3tunes_locker_artist_list_t **artists, char *search) {
0970     xml_xpath_t* xml_xpath;
0971     xmlXPathObjectPtr xpath_obj;
0972     xmlNodeSetPtr nodeset;
0973     xmlNodePtr node;
0974     int i;
0975 
0976     xml_xpath = mp3tunes_locker_api_simple_fetch(obj, MP3TUNES_SERVER_API, "api/v1/lockerSearch", "type", "artist", "s", search, NULL);
0977     mp3tunes_locker_artist_list_init(artists);
0978 
0979     if (xml_xpath == NULL) {
0980         return -1;
0981     }
0982 
0983     xpath_obj = xml_xpath_query(xml_xpath, "/mp3tunes/artistList/item");
0984     if (xpath_obj == NULL) {
0985         return -1;
0986     }
0987 
0988     nodeset = xpath_obj->nodesetval;
0989 
0990     for (i = 0; i < nodeset->nodeNr; i++) {
0991         node = nodeset->nodeTab[i];
0992         xml_xpath_t* xml_xpath_context = xml_xpath_context_init(xml_xpath, node);
0993         mp3tunes_locker_artist_t *artist = (mp3tunes_locker_artist_t*)malloc(sizeof(mp3tunes_locker_artist_t));
0994         memset(artist, 0, sizeof(mp3tunes_locker_artist_t));
0995 
0996         artist->artistId = xml_xpath_get_integer(xml_xpath_context, "artistId");
0997         artist->artistName = xml_xpath_get_string(xml_xpath_context, "artistName");
0998         artist->artistSize = xml_xpath_get_integer(xml_xpath_context, "artistSize");
0999         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 
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 
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 
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 
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 
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 
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 
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 
1455 char* mp3tunes_locker_generate_filekey(const char *filename) {
1456   return md5_calc_file_signature(filename);
1457 }
1458 
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 
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 }