/** * flickcurl_galleries_create: * @fc: flickcurl context * @title: The name of the gallery * @description: A short description for the gallery * @primary_photo_id: The first photo to add to your gallery (or NULL) * @gallery_url_p: pointer to variable to store new gallery URL (or NULL) * * Create a new gallery for the calling user. * * Implements flickr.galleries.create (1.18) * * Announced 2010-04-08 * http://code.flickr.com/blog/2010/04/08/galleries-apis/ * * Return value: gallery ID or NULL on failure **/ char* flickcurl_galleries_create(flickcurl* fc, const char* title, const char* description, const char* primary_photo_id, char** gallery_url_p) { xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; char* gallery_id = NULL; flickcurl_init_params(fc); if(!title || !description) return NULL; flickcurl_add_param(fc, "title", title); flickcurl_add_param(fc, "description", description); if(primary_photo_id) { flickcurl_add_param(fc, "primary_photo_id", primary_photo_id); } flickcurl_end_params(fc); if(flickcurl_prepare(fc, "flickr.galleries.create")) goto tidy; flickcurl_set_write(fc, 1); flickcurl_set_data(fc, (void*)"", 0); doc = flickcurl_invoke(fc); if(!doc) goto tidy; xpathCtx = xmlXPathNewContext(doc); if(!xpathCtx) { flickcurl_error(fc, "Failed to create XPath context for document"); fc->failed = 1; goto tidy; } gallery_id = flickcurl_xpath_eval(fc, xpathCtx, (const xmlChar*)"/rsp/gallery/@id"); if(gallery_url_p) { *gallery_url_p = flickcurl_xpath_eval(fc, xpathCtx, (const xmlChar*)"/rsp/gallery/@url"); } tidy: if(xpathCtx) xmlXPathFreeContext(xpathCtx); if(fc->failed) gallery_id = NULL; return gallery_id; }
/** * flickcurl_photosets_create: * @fc: flickcurl context * @title: A title for the photoset. * @description: A description of the photoset which may contain limited html (or NULL) * @primary_photo_id: The id of the photo to represent this set. The photo must belong to the calling user. * @photoset_url_p: pointer to variable to store new photoset URL (or NULL) * * Create a new photoset for the calling user. * * Implements flickr.photosets.create (0.13) * * Return value: photoset ID or NULL on failure **/ char* flickcurl_photosets_create(flickcurl* fc, const char* title, const char* description, const char* primary_photo_id, char** photoset_url_p) { const char* parameters[10][2]; int count = 0; xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; char* photoset_id = NULL; if(!title || !primary_photo_id) return NULL; parameters[count][0] = "title"; parameters[count++][1]= title; if(description) { parameters[count][0] = "description"; parameters[count++][1]= description; } parameters[count][0] = "primary_photo_id"; parameters[count++][1]= primary_photo_id; parameters[count][0] = NULL; if(flickcurl_prepare(fc, "flickr.photosets.create", parameters, count)) goto tidy; flickcurl_set_write(fc, 1); flickcurl_set_data(fc, (void*)"", 0); doc = flickcurl_invoke(fc); if(!doc) goto tidy; xpathCtx = xmlXPathNewContext(doc); if(!xpathCtx) { flickcurl_error(fc, "Failed to create XPath context for document"); fc->failed = 1; goto tidy; } photoset_id = flickcurl_xpath_eval(fc, xpathCtx, (const xmlChar*)"/rsp/photoset/@id"); if(photoset_url_p) { *photoset_url_p = flickcurl_xpath_eval(fc, xpathCtx, (const xmlChar*)"/rsp/photoset/@url"); } tidy: if(xpathCtx) xmlXPathFreeContext(xpathCtx); if(fc->failed) photoset_id = NULL; return photoset_id; }
/** * flickcurl_auth_getToken: * @fc: flickcurl context * @frob: frob string * * Get the auth token for the given frob, if one has been attached. * * Implements flickr.auth.getToken (0.9) * Must be signed. * * Return value: token string or NULL on failure **/ char* flickcurl_auth_getToken(flickcurl* fc, const char* frob) { const char * parameters[6][2]; int count = 0; char *auth_token = NULL; xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; parameters[count][0] = "frob"; parameters[count++][1] = (char*)frob; parameters[count][0] = NULL; flickcurl_set_sign(fc); if(flickcurl_prepare(fc, "flickr.auth.getToken", parameters, count)) goto tidy; doc = flickcurl_invoke(fc); if(!doc) goto tidy; xpathCtx = xmlXPathNewContext(doc); if(xpathCtx) { auth_token = flickcurl_xpath_eval(fc, xpathCtx, (const xmlChar*)"/rsp/auth/token"); xmlXPathFreeContext(xpathCtx); } tidy: return auth_token; }
/** * flickcurl_auth_getFrob: * @fc: flickcurl context * * Get a frob to be used during authentication * * Implements flickr.auth.getFrob (0.9) * Must be signed. Does not require authentication. * * Return value: frob string or NULL on failure **/ char* flickcurl_auth_getFrob(flickcurl* fc) { const char * parameters[5][2]; int count = 0; char *frob = NULL; xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; parameters[count][0] = NULL; flickcurl_set_sign(fc); if(flickcurl_prepare(fc, "flickr.auth.getFrob", parameters, count)) goto tidy; doc = flickcurl_invoke(fc); if(!doc) goto tidy; xpathCtx = xmlXPathNewContext(doc); if(xpathCtx) { frob = flickcurl_xpath_eval(fc, xpathCtx, (const xmlChar*)"/rsp/frob"); xmlXPathFreeContext(xpathCtx); } tidy: return frob; }
/** * flickcurl_photos_notes_add: * @fc: flickcurl context * @photo_id: The id of the photo to add a note to * @note_x: The left coordinate of the note * @note_y: The top coordinate of the note * @note_w: The width of the note * @note_h: The height of the note * @note_text: The description of the note * * Add a note to a photo. * * Coordinates and sizes are in pixels, based on the 500px image size * shown on individual photo pages. * * Implements flickr.photos.notes.add (0.12) * * Return value: note ID or NULL on failure **/ char* flickcurl_photos_notes_add(flickcurl* fc, const char* photo_id, int note_x, int note_y, int note_w, int note_h, const char* note_text) { xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; char *id = NULL; char note_x_s[10]; char note_y_s[10]; char note_w_s[10]; char note_h_s[10]; flickcurl_init_params(fc); if(!photo_id || !note_text) return NULL; flickcurl_add_param(fc, "photo_id", photo_id); sprintf(note_x_s, "%d", note_x); flickcurl_add_param(fc, "note_x", note_x_s); sprintf(note_y_s, "%d", note_y); flickcurl_add_param(fc, "note_y", note_y_s); sprintf(note_w_s, "%d", note_w); flickcurl_add_param(fc, "note_w", note_w_s); sprintf(note_h_s, "%d", note_h); flickcurl_add_param(fc, "note_h", note_h_s); flickcurl_add_param(fc, "note_text", note_text); flickcurl_end_params(fc); if(flickcurl_prepare(fc, "flickr.photos.notes.add")) goto tidy; flickcurl_set_write(fc, 1); flickcurl_set_data(fc, (void*)"", 0); doc = flickcurl_invoke(fc); if(!doc) goto tidy; xpathCtx = xmlXPathNewContext(doc); if(!xpathCtx) { flickcurl_error(fc, "Failed to create XPath context for document"); fc->failed = 1; goto tidy; } id = flickcurl_xpath_eval(fc, xpathCtx, (const xmlChar*)"/rsp/note/@id"); tidy: if(xpathCtx) xmlXPathFreeContext(xpathCtx); if(fc->failed) id = NULL; return id; }
flickcurl_method* flickcurl_build_method(flickcurl* fc, xmlXPathContextPtr xpathCtx) { int expri; flickcurl_method* method = NULL; method = (flickcurl_method*)calloc(sizeof(flickcurl_method), 1); for(expri = 0; method_fields_table[expri].xpath; expri++) { char *string_value = flickcurl_xpath_eval(fc, xpathCtx, method_fields_table[expri].xpath); switch(method_fields_table[expri].field) { case METHOD_FIELD_name: method->name = string_value; break; case METHOD_FIELD_needslogin: method->needslogin = atoi(string_value); break; case METHOD_FIELD_description: method->description = string_value; break; case METHOD_FIELD_response: method->response = string_value; break; case METHOD_FIELD_explanation: method->explanation = string_value; break; default: abort(); } if(fc->failed) goto tidy; } /* As of 2007-04-15 - the response is different from the docs * There is no /method/arguments element */ method->args = flickcurl_build_args(fc, xpathCtx, (xmlChar*)"/rsp/arguments/argument", &method->args_count); tidy: if(fc->failed) { if(method) free(method); method = NULL; } return method; }
/** * flickcurl_photosets_comments_addComment: * @fc: flickcurl context * @photoset_id: The id of the photoset to add a comment to. * @comment_text: Text of the comment * * Add a comment to a photoset. * * Implements flickr.photosets.comments.addComment (0.10) * * Return value: new comment ID or non-NULL on failure **/ char* flickcurl_photosets_comments_addComment(flickcurl* fc, const char* photoset_id, const char* comment_text) { xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; char* id = NULL; flickcurl_init_params(fc, 1); if(!photoset_id || !comment_text) return NULL; flickcurl_add_param(fc, "photoset_id", photoset_id); flickcurl_add_param(fc, "comment_text", comment_text); flickcurl_end_params(fc); if(flickcurl_prepare(fc, "flickr.photosets.comments.addComment")) goto tidy; doc = flickcurl_invoke(fc); if(!doc) goto tidy; xpathCtx = xmlXPathNewContext(doc); if(!xpathCtx) { flickcurl_error(fc, "Failed to create XPath context for document"); fc->failed = 1; goto tidy; } id = flickcurl_xpath_eval(fc, xpathCtx, (const xmlChar*)"/rsp/comment/@id"); tidy: if(xpathCtx) xmlXPathFreeContext(xpathCtx); if(fc->failed) id = NULL; return id; }
/** * flickcurl_prefs_getPrivacy: * @fc: flickcurl context * * Returns the default privacy level preference for the user. * * Possible values are: Public (1), Friends only (2), Family only (3) * Friends and Family (4) and Private (5) * * Implements flickr.prefs.getPrivacy (1.3) * * Return value: privacy level or <0 on failure **/ int flickcurl_prefs_getPrivacy(flickcurl* fc) { xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; char* privacy_level_str= NULL; int privacy_level= -1; flickcurl_init_params(fc, 0); flickcurl_end_params(fc); if(flickcurl_prepare(fc, "flickr.prefs.getPrivacy")) goto tidy; doc = flickcurl_invoke(fc); if(!doc) goto tidy; xpathCtx = xmlXPathNewContext(doc); if(!xpathCtx) { flickcurl_error(fc, "Failed to create XPath context for document"); fc->failed = 1; goto tidy; } privacy_level_str = flickcurl_xpath_eval(fc, xpathCtx, (const xmlChar*)"/rsp/person/@privacy"); if(privacy_level_str) { privacy_level = atoi(privacy_level_str); free(privacy_level_str); } tidy: if(xpathCtx) xmlXPathFreeContext(xpathCtx); if(fc->failed) privacy_level= -1; return privacy_level; }
/** * flickcurl_prefs_getContentType: * @fc: flickcurl context * * Returns the default content type preference for the user. * * Implements flickr.prefs.getContentType (1.3) * * Return value: content type or <0 on failure **/ int flickcurl_prefs_getContentType(flickcurl* fc) { xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; char* content_type_str = NULL; int content_type= -1; flickcurl_init_params(fc, 0); flickcurl_end_params(fc); if(flickcurl_prepare(fc, "flickr.prefs.getContentType")) goto tidy; doc = flickcurl_invoke(fc); if(!doc) goto tidy; xpathCtx = xmlXPathNewContext(doc); if(!xpathCtx) { flickcurl_error(fc, "Failed to create XPath context for document"); fc->failed = 1; goto tidy; } content_type_str = flickcurl_xpath_eval(fc, xpathCtx, (const xmlChar*)"/rsp/person/@content_type"); if(content_type_str) { content_type = atoi(content_type_str); free(content_type_str); } tidy: if(xpathCtx) xmlXPathFreeContext(xpathCtx); if(fc->failed) content_type= -1; return content_type; }
/** * flickcurl_prefs_getHidden: * @fc: flickcurl context * * Returns the default hidden preference for the user. * * Implements flickr.prefs.getHidden (1.3) * * Return value: non-0 on failure **/ int flickcurl_prefs_getHidden(flickcurl* fc) { xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; char* hidden_str = NULL; int hidden= -1; flickcurl_init_params(fc, 0); flickcurl_end_params(fc); if(flickcurl_prepare(fc, "flickr.prefs.getHidden")) goto tidy; doc = flickcurl_invoke(fc); if(!doc) goto tidy; xpathCtx = xmlXPathNewContext(doc); if(!xpathCtx) { flickcurl_error(fc, "Failed to create XPath context for document"); fc->failed = 1; goto tidy; } hidden_str = flickcurl_xpath_eval(fc, xpathCtx, (const xmlChar*)"/rsp/person/@hidden"); if(hidden_str) { hidden = atoi(hidden_str); free(hidden_str); } tidy: if(xpathCtx) xmlXPathFreeContext(xpathCtx); if(fc->failed) hidden= -1; return hidden; }
/** * flickcurl_prefs_getSafetyLevel: * @fc: flickcurl context * * Returns the default safety level preference for the user. * * Implements flickr.prefs.getSafetyLevel (1.3) * * Return value: safety level or <0 on failure **/ int flickcurl_prefs_getSafetyLevel(flickcurl* fc) { const char* parameters[7][2]; int count = 0; xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; char* safety_level_str= NULL; int safety_level= -1; parameters[count][0] = NULL; if(flickcurl_prepare(fc, "flickr.prefs.getSafetyLevel", parameters, count)) goto tidy; doc = flickcurl_invoke(fc); if(!doc) goto tidy; xpathCtx = xmlXPathNewContext(doc); if(!xpathCtx) { flickcurl_error(fc, "Failed to create XPath context for document"); fc->failed = 1; goto tidy; } safety_level_str = flickcurl_xpath_eval(fc, xpathCtx, (const xmlChar*)"/rsp/person/@safety_level"); if(safety_level_str) { safety_level = atoi(safety_level_str); free(safety_level_str); } tidy: if(xpathCtx) xmlXPathFreeContext(xpathCtx); if(fc->failed) safety_level= -1; return safety_level; }
/** * flickcurl_test_login: * @fc: flickcurl context * * A testing method which checks if the caller is logged in then * returns their username. * * Implements flickr.test.login (1.0) * * Return value: username or NULL on failure **/ char* flickcurl_test_login(flickcurl* fc) { const char* parameters[7][2]; int count = 0; xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; char* username = NULL; parameters[count][0] = NULL; if(flickcurl_prepare(fc, "flickr.test.login", parameters, count)) goto tidy; doc = flickcurl_invoke(fc); if(!doc) goto tidy; xpathCtx = xmlXPathNewContext(doc); if(!xpathCtx) { flickcurl_error(fc, "Failed to create XPath context for document"); fc->failed = 1; goto tidy; } username = flickcurl_xpath_eval(fc, xpathCtx, (const xmlChar*)"/rsp/user/username"); tidy: if(xpathCtx) xmlXPathFreeContext(xpathCtx); if(fc->failed) username = NULL; return username; }
/** * flickcurl_auth_checkToken: * @fc: flickcurl context * @token: token string * * Get the credentials attached to an authentication token. * * Implements flickr.auth.checkToken (0.9) * Must be signed. * * FIXME: Cannot confirm this works, get intermittent results. * * Return value: permissions string or NULL on failure **/ char* flickcurl_auth_checkToken(flickcurl* fc, const char* token) { const char * parameters[6][2]; int count = 0; char *perms = NULL; xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; if(!token) return NULL; parameters[count][0] = "auth_token"; parameters[count++][1] = (char*)token; parameters[count][0] = NULL; flickcurl_set_sign(fc); if(flickcurl_prepare(fc, "flickr.auth.checkToken", parameters, count)) goto tidy; doc = flickcurl_invoke(fc); if(!doc) goto tidy; xpathCtx = xmlXPathNewContext(doc); if(xpathCtx) { perms = flickcurl_xpath_eval(fc, xpathCtx, (const xmlChar*)"/rsp/auth/perms"); xmlXPathFreeContext(xpathCtx); } tidy: return perms; }
/* * flickcurl_invoke_photos_list: * @fc: Flickcurl context * @xpathExpr: Xpath to the list of photos e.g. '/rsp/photos' or '/rsp/gallery'. The /photos suffix is added internally. * @format: result format wanted * * INTERNAL - Build photos list from XML or get format content result from web service response document * * Return value: new photos list or NULL on failure */ flickcurl_photos_list* flickcurl_invoke_photos_list(flickcurl* fc, const xmlChar* xpathExpr, const char* format) { flickcurl_photos_list* photos_list = NULL; xmlXPathContextPtr xpathCtx = NULL; xmlXPathObjectPtr xpathObj = NULL; xmlXPathContextPtr xpathNodeCtx = NULL; const char *nformat; size_t format_len; photos_list = (flickcurl_photos_list*)calloc(1, sizeof(*photos_list)); if(!photos_list) { fc->failed = 1; goto tidy; } photos_list->page = -1; photos_list->per_page = -1; photos_list->total_count = -1; if(format) { nformat = format; format_len = strlen(format); photos_list->content = flickcurl_invoke_get_content(fc, &photos_list->content_length); if(!photos_list->content) { fc->failed = 1; goto tidy; } } else { xmlDocPtr doc = NULL; xmlNodePtr photos_node; size_t xpathExprLen = strlen((const char*)xpathExpr); char* value; xmlChar* photosXpathExpr; #define SUFFIX "/photo" #define SUFFIX_LEN 6 nformat = "xml"; format_len = 3; doc = flickcurl_invoke(fc); if(!doc) goto tidy; xpathCtx = xmlXPathNewContext(doc); if(!xpathCtx) { flickcurl_error(fc, "Failed to create XPath context for document"); fc->failed = 1; goto tidy; } /* set up a new XPath context for the top level list-of-photos * XML element. It may be <photos> or <gallery> or ... - the * code does not care. */ xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx); if(!xpathObj) { flickcurl_error(fc, "Unable to evaluate XPath expression \"%s\"", xpathExpr); fc->failed = 1; goto tidy; } if(!xpathObj->nodesetval || !xpathObj->nodesetval->nodeTab) { /* No <photo> elements found in content - not a failure */ goto tidy; } photos_node = xpathObj->nodesetval->nodeTab[0]; xpathNodeCtx = xmlXPathNewContext(xpathCtx->doc); if(!xpathNodeCtx) { flickcurl_error(fc, "Unable to create XPath context for XPath \"%s\"", xpathExpr); fc->failed = 1; goto tidy; } xpathNodeCtx->node = photos_node; value = flickcurl_xpath_eval(fc, xpathNodeCtx, (const xmlChar*)"./@page"); if(value) { photos_list->page = atoi(value); free(value); } value = flickcurl_xpath_eval(fc, xpathNodeCtx, (const xmlChar*)"./@perpage"); if(value) { photos_list->per_page = atoi(value); free(value); } value = flickcurl_xpath_eval(fc, xpathNodeCtx, (const xmlChar*)"./@total"); if(value) { photos_list->total_count = atoi(value); free(value); } /* finished with these */ xmlXPathFreeContext(xpathNodeCtx); xpathNodeCtx = NULL; xmlXPathFreeObject(xpathObj); xpathObj = NULL; photosXpathExpr = (xmlChar*)malloc(xpathExprLen + SUFFIX_LEN + 1); memcpy(photosXpathExpr, xpathExpr, xpathExprLen); memcpy(photosXpathExpr + xpathExprLen, SUFFIX, SUFFIX_LEN + 1); photos_list->photos = flickcurl_build_photos(fc, xpathCtx, photosXpathExpr, &photos_list->photos_count); if(!photos_list->photos) { fc->failed = 1; goto tidy; } } photos_list->format = (char*)malloc(format_len+1); if(!photos_list->format) { fc->failed = 1; goto tidy; } memcpy(photos_list->format, nformat, format_len+1); tidy: if(xpathNodeCtx) xmlXPathFreeContext(xpathNodeCtx); if(xpathObj) xmlXPathFreeObject(xpathObj); if(xpathCtx) xmlXPathFreeContext(xpathCtx); if(fc->failed) { if(photos_list) flickcurl_free_photos_list(photos_list); photos_list = NULL; } return photos_list; }
/** * flickcurl_photos_upload_params: * @fc: flickcurl context * @params: upload parameters * * Uploads a photo with safety level and content type * * Return value: #flickcurl_upload_status or NULL on failure **/ flickcurl_upload_status* flickcurl_photos_upload_params(flickcurl* fc, flickcurl_upload_params* params) { xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; flickcurl_upload_status* status = NULL; char is_public_s[2]; char is_friend_s[2]; char is_family_s[2]; char safety_level_s[2]; char content_type_s[2]; char hidden_s[2]; flickcurl_init_params(fc); if(!params->photo_file) return NULL; if(access((const char*)params->photo_file, R_OK)) { flickcurl_error(fc, "Photo file %s cannot be read: %s", params->photo_file, strerror(errno)); return NULL; } is_public_s[0] = params->is_public ? '1' : '0'; is_public_s[1] = '\0'; is_friend_s[0] = params->is_friend ? '1' : '0'; is_friend_s[1] = '\0'; is_family_s[0] = params->is_family ? '1' : '0'; is_family_s[1] = '\0'; if(params->safety_level >= 1 && params->safety_level <= 3) { safety_level_s[0] = '0' + params->safety_level; safety_level_s[1] = '\0'; } else params->safety_level = -1; if(params->content_type >= 1 && params->content_type <= 3) { content_type_s[0] = '0' + params->content_type; content_type_s[1] = '\0'; } else params->content_type = -1; if(params->hidden >= 1 && params->hidden <= 2 ) { hidden_s[0] = '0' + params->hidden; hidden_s[1] = '\0'; } else { params->hidden = -1; } if(params->title) { flickcurl_add_param(fc, "title", params->title); } if(params->description) { flickcurl_add_param(fc, "description", params->description); } if(params->tags) { flickcurl_add_param(fc, "tags", params->tags); } if(params->safety_level >= 0) { flickcurl_add_param(fc, "safety_level", safety_level_s); } if(params->content_type >= 0) { flickcurl_add_param(fc, "content_type", content_type_s); } flickcurl_add_param(fc, "is_public", is_public_s); flickcurl_add_param(fc, "is_friend", is_friend_s); flickcurl_add_param(fc, "is_family", is_family_s); if(params->hidden >= 0) { flickcurl_add_param(fc, "hidden", hidden_s); } flickcurl_end_params(fc); if(flickcurl_prepare_upload(fc, fc->upload_service_uri, "photo", params->photo_file)) goto tidy; doc = flickcurl_invoke(fc); if(!doc) goto tidy; xpathCtx = xmlXPathNewContext(doc); if(!xpathCtx) { flickcurl_error(fc, "Failed to create XPath context for document"); fc->failed = 1; goto tidy; } status = (flickcurl_upload_status*)calloc(1, sizeof(flickcurl_upload_status)); status->photoid = flickcurl_xpath_eval(fc, xpathCtx, (const xmlChar*)"/rsp/photoid"); /* when async is true */ status->ticketid = flickcurl_xpath_eval(fc, xpathCtx, (const xmlChar*)"/rsp/ticketid"); tidy: if(xpathCtx) xmlXPathFreeContext(xpathCtx); if(fc->failed) { if(status) free(status); status = NULL; } return status; }
/** * flickcurl_photos_replace: * @fc: flickcurl context * @photo_file: photo filename * @photo_id: photo ID to replace * @async: upload asynchronously boolean (non-0 true) * * Replace a photo with a new file. * * Implements Replacing Photos (0.10) * Implements Asynchronous Uploading (0.10) * * Return value: #flickcurl_upload_status or NULL on failure **/ flickcurl_upload_status* flickcurl_photos_replace(flickcurl* fc, const char* photo_file, const char *photo_id, int async) { xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; flickcurl_upload_status* status = NULL; char async_s[2]; flickcurl_init_params(fc); if(!photo_file || !photo_id) return NULL; if(access((const char*)photo_file, R_OK)) { flickcurl_error(fc, "Photo file %s cannot be read: %s", photo_file, strerror(errno)); return NULL; } async_s[0] = async ? '1' : '0'; async_s[1] = '\0'; flickcurl_add_param(fc, "photo_id", photo_id); flickcurl_add_param(fc, "async", async_s); flickcurl_end_params(fc); if(flickcurl_prepare_upload(fc, fc->replace_service_uri, "photo", photo_file)) goto tidy; doc = flickcurl_invoke(fc); if(!doc) goto tidy; xpathCtx = xmlXPathNewContext(doc); if(!xpathCtx) { flickcurl_error(fc, "Failed to create XPath context for document"); fc->failed = 1; goto tidy; } status = (flickcurl_upload_status*)calloc(1, sizeof(flickcurl_upload_status)); status->secret = flickcurl_xpath_eval(fc, xpathCtx, (const xmlChar*)"/rsp/photoid/@secret"); status->originalsecret = flickcurl_xpath_eval(fc, xpathCtx, (const xmlChar*)"/rsp/photoid/@originalsecret"); /* when async is true */ status->ticketid = flickcurl_xpath_eval(fc, xpathCtx, (const xmlChar*)"/rsp/ticketid"); tidy: if(xpathCtx) xmlXPathFreeContext(xpathCtx); if(fc->failed) { if(status) free(status); status = NULL; } return status; }
/** * flickcurl_photos_upload_params: * @fc: flickcurl context * @params: upload parameters * * Uploads a photo with safety level and content type * * Return value: #flickcurl_upload_status or NULL on failure **/ flickcurl_upload_status* flickcurl_photos_upload_params(flickcurl* fc, flickcurl_upload_params* params) { const char* parameters[12][2]; int count = 0; xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; flickcurl_upload_status* status = NULL; char is_public_s[2]; char is_friend_s[2]; char is_family_s[2]; char safety_level_s[2]; char content_type_s[2]; if(!params->photo_file) return NULL; if(access((const char*)params->photo_file, R_OK)) { flickcurl_error(fc, "Photo file %s cannot be read: %s", params->photo_file, strerror(errno)); return NULL; } is_public_s[0] = params->is_public ? '1' : '0'; is_public_s[1] = '\0'; is_friend_s[0] = params->is_friend ? '1' : '0'; is_friend_s[1] = '\0'; is_family_s[0] = params->is_family ? '1' : '0'; is_family_s[1] = '\0'; if(params->safety_level >= 1 && params->safety_level <= 3) { safety_level_s[0] = '0' + params->safety_level; safety_level_s[1] = '\0'; } else params->safety_level= -1; if(params->content_type >= 1 && params->content_type <= 3) { content_type_s[0] = '0' + params->content_type; content_type_s[1] = '\0'; } else params->content_type= -1; if(params->title) { parameters[count][0] = "title"; parameters[count++][1]= params->title; } if(params->description) { parameters[count][0] = "description"; parameters[count++][1]= params->description; } if(params->tags) { parameters[count][0] = "tags"; parameters[count++][1]= params->tags; } if(params->safety_level >= 0) { parameters[count][0] = "safety_level"; parameters[count++][1]= safety_level_s; } if(params->content_type >= 0) { parameters[count][0] = "content_type"; parameters[count++][1]= content_type_s; } parameters[count][0] = "is_public"; parameters[count++][1]= is_public_s; parameters[count][0] = "is_friend"; parameters[count++][1]= is_friend_s; parameters[count][0] = "is_family"; parameters[count++][1]= is_family_s; parameters[count][0] = NULL; if(flickcurl_prepare_upload(fc, fc->upload_service_uri, "photo", params->photo_file, parameters, count)) goto tidy; doc = flickcurl_invoke(fc); if(!doc) goto tidy; xpathCtx = xmlXPathNewContext(doc); if(!xpathCtx) { flickcurl_error(fc, "Failed to create XPath context for document"); fc->failed = 1; goto tidy; } status = (flickcurl_upload_status*)calloc(1, sizeof(flickcurl_upload_status)); status->photoid = flickcurl_xpath_eval(fc, xpathCtx, (const xmlChar*)"/rsp/photoid"); /* when async is true */ status->ticketid = flickcurl_xpath_eval(fc, xpathCtx, (const xmlChar*)"/rsp/ticketid"); tidy: if(xpathCtx) xmlXPathFreeContext(xpathCtx); if(fc->failed) status = NULL; return status; }