/** * flickcurl_test_null: * @fc: flickcurl context * * Null test * * Implements flickr.test.null (1.0) * * Return value: non-0 on failure **/ int flickcurl_test_null(flickcurl* fc) { const char* parameters[7][2]; int count = 0; xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; parameters[count][0] = NULL; if(flickcurl_prepare(fc, "flickr.test.null", 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; } tidy: if(xpathCtx) xmlXPathFreeContext(xpathCtx); return fc->failed; }
/** * 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_photos_people_editCoords: * @fc: flickcurl context * @photo_id: The id of the photo to edit a person in. * @user_id: The NSID of the person to edit in a photo. * @person_x: The left-most pixel co-ordinate of the box around the person. * @person_y: The top-most pixel co-ordinate of the box around the person. * @person_w: The width (in pixels) of the box around the person. * @person_h: The height (in pixels) of the box around the person. * * Edit the bounding box of an existing person on a photo. * * Implements flickr.photos.people.editCoords (1.17) * * Announced 2010-01-21 * http://code.flickr.com/blog/2010/01/21/people-in-photos-the-api-methods/ * * Return value: non-0 on failure **/ int flickcurl_photos_people_editCoords(flickcurl* fc, const char* photo_id, const char* user_id, int person_x, int person_y, int person_w, int person_h) { xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; int rc = 0; char person_x_str[10]; char person_y_str[10]; char person_w_str[10]; char person_h_str[10]; flickcurl_init_params(fc, 1); if(!photo_id || !user_id || person_x < 0 || person_y < 0 || person_w <0 || person_h < 0) return 1; flickcurl_add_param(fc, "photo_id", photo_id); flickcurl_add_param(fc, "user_id", user_id); sprintf(person_x_str, "%d", person_x); flickcurl_add_param(fc, "person_x", person_x_str); sprintf(person_y_str, "%d", person_y); flickcurl_add_param(fc, "person_y", person_y_str); sprintf(person_w_str, "%d", person_w); flickcurl_add_param(fc, "person_w", person_w_str); sprintf(person_h_str, "%d", person_h); flickcurl_add_param(fc, "person_h", person_h_str); flickcurl_end_params(fc); if(flickcurl_prepare(fc, "flickr.photos.people.editCoords")) 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; } tidy: if(xpathCtx) xmlXPathFreeContext(xpathCtx); if(fc->failed) rc = 1; return rc; }
/** * 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_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_galleries_addPhoto: * @fc: flickcurl context * @gallery_id: The ID of the gallery to add a photo to as returned by flickcurl_galleries_getList() and flickcurl_galleries_getListForPhoto(). * @photo_id: The photo ID to add to the gallery. * @comment_text: A short comment or story to accompany the photo (or NULL). * * Add a photo to a gallery. * * Implements flickr.galleries.addPhoto (1.17) * * Return value: non-0 on failure **/ int flickcurl_galleries_addPhoto(flickcurl* fc, const char* gallery_id, const char* photo_id, const char* comment_text) { xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; void* result = NULL; flickcurl_init_params(fc); if(!gallery_id || !photo_id) return 1; flickcurl_add_param(fc, "gallery_id", gallery_id); flickcurl_add_param(fc, "photo_id", photo_id); if(comment_text) { flickcurl_add_param(fc, "comment", comment_text); } flickcurl_end_params(fc); if(flickcurl_prepare(fc, "flickr.galleries.addPhoto")) 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; } result = NULL; /* your code here */ tidy: if(xpathCtx) xmlXPathFreeContext(xpathCtx); if(fc->failed) result = NULL; return (result == NULL); }
/** * flickcurl_collections_getTree: * @fc: flickcurl context * @collection_id: The ID of the collection to fetch a tree for, or zero to fetch the root collection. Defaults to zero. (or NULL) * @user_id: The ID of the account to fetch the collection tree for. Deafults to the calling user. (or NULL) * * Returns a tree (or sub tree) of collections belonging to a given user. * * Implements flickr.collections.getTree (1.12) * * Return value: a collection or NULL on failure **/ flickcurl_collection* flickcurl_collections_getTree(flickcurl* fc, const char* collection_id, const char* user_id) { xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; flickcurl_collection* collection = NULL; flickcurl_init_params(fc, 0); if(collection_id) { flickcurl_add_param(fc, "collection_id", collection_id); } if(user_id) { flickcurl_add_param(fc, "user_id", user_id); } flickcurl_end_params(fc); if(flickcurl_prepare(fc, "flickr.collections.getTree")) 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; } collection = flickcurl_build_collection(fc, xpathCtx, (const xmlChar*)"/rsp/collections/collection"); tidy: if(xpathCtx) xmlXPathFreeContext(xpathCtx); if(fc->failed) { if(collection) flickcurl_free_collection(collection); collection = NULL; } return collection; }
/** * flickcurl_galleries_getInfo: * @fc: flickcurl context * @gallery_id: The gallery ID you are requesting information for. * * Get information for a gallery. * * Implements flickr.galleries.getInfo (1.18) * * Announced 2010-04-08 * http://code.flickr.com/blog/2010/04/08/galleries-apis/ * * Return value: gallery or NULL on failure **/ flickcurl_gallery* flickcurl_galleries_getInfo(flickcurl* fc, const char* gallery_id) { xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; flickcurl_gallery* gallery = NULL; flickcurl_gallery** galleries = NULL; flickcurl_init_params(fc); if(!gallery_id) return NULL; flickcurl_add_param(fc, "gallery_id", gallery_id); flickcurl_end_params(fc); if(flickcurl_prepare(fc, "flickr.galleries.getInfo")) 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; } galleries = flickcurl_build_galleries(fc, xpathCtx, (const xmlChar*)"/rsp/galleries/gallery", NULL); if(galleries) { gallery = galleries[0]; galleries[0] = NULL; flickcurl_free_galleries(galleries); } tidy: if(xpathCtx) xmlXPathFreeContext(xpathCtx); if(fc->failed) gallery = NULL; return gallery; }
/** * flickcurl_collections_getTree: * @fc: flickcurl context * @collection_id: The ID of the collection to fetch a tree for, or zero to fetch the root collection. Defaults to zero. (or NULL) * @user_id: The ID of the account to fetch the collection tree for. Deafults to the calling user. (or NULL) * * Returns a tree (or sub tree) of collections belonging to a given user. * * Implements flickr.collections.getTree (1.12) * * Return value: a collection or NULL on failure **/ flickcurl_collection* flickcurl_collections_getTree(flickcurl* fc, const char* collection_id, const char* user_id) { const char* parameters[9][2]; int count = 0; xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; flickcurl_collection* collection = NULL; if(collection_id) { parameters[count][0] = "collection_id"; parameters[count++][1]= collection_id; } if(user_id) { parameters[count][0] = "user_id"; parameters[count++][1]= user_id; } parameters[count][0] = NULL; if(flickcurl_prepare(fc, "flickr.collections.getTree", 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; } collection = flickcurl_build_collection(fc, xpathCtx, (const xmlChar*)"/rsp/collections/collection"); tidy: if(xpathCtx) xmlXPathFreeContext(xpathCtx); if(fc->failed) collection = NULL; return collection; }
/** * flickcurl_photos_geo_correctLocation: * @fc: flickcurl context * @photo_id: The ID of the photo whose WOE location is being corrected. * @place_id: A Flickr Places ID (or NULL) * @woe_id: A Where On Earth (WOE) ID (or NULL) * * Correct a photo location. * * You must pass either a valid Places ID in @place_id or a WOE ID in @woe_id. * * Implements flickr.photos.geo.correctLocation (1.8) * * Return value: non-0 on failure **/ int flickcurl_photos_geo_correctLocation(flickcurl* fc, const char* photo_id, const char* place_id, int woe_id) { xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; void* result = NULL; char woe_id_str[10]; flickcurl_init_params(fc, 0); if(!photo_id) return 1; flickcurl_add_param(fc, "photo_id", photo_id); flickcurl_add_param(fc, "place_id", place_id); if(woe_id > 0) { sprintf(woe_id_str, "%d", woe_id); flickcurl_add_param(fc, "woe_id", woe_id_str); } flickcurl_end_params(fc); if(flickcurl_prepare(fc, "flickr.photos.geo.correctLocation")) 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; } result = NULL; /* your code here */ tidy: if(xpathCtx) xmlXPathFreeContext(xpathCtx); if(fc->failed) result = NULL; return (result == NULL); }
/** * flickcurl_photos_geo_getPerms: * @fc: flickcurl context * @photo_id: The id of the photo to get permissions for. * * Get permissions for who may view geo data for a photo. * * Implements flickr.photos.geo.getPerms (0.12) * * Return value: non-0 on failure **/ flickcurl_perms* flickcurl_photos_geo_getPerms(flickcurl* fc, const char* photo_id) { xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; flickcurl_perms* perms = NULL; flickcurl_init_params(fc, 0); if(!photo_id) return NULL; flickcurl_add_param(fc, "photo_id", photo_id); flickcurl_end_params(fc); if(flickcurl_prepare(fc, "flickr.photos.geo.getPerms")) 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; } perms = flickcurl_build_perms(fc, xpathCtx, (const xmlChar*)"/rsp/perms"); tidy: if(xpathCtx) xmlXPathFreeContext(xpathCtx); if(fc->failed) { if(perms) flickcurl_free_perms(perms); perms = NULL; } return perms; }
/** * flickcurl_photos_geo_setContext: * @fc: flickcurl context * @photo_id: The id of the photo to set context data for. * @context: Context is a numeric value representing the photo's geotagginess beyond latitude and longitude. The current values are: 0: not defined, 1: indoors, 2: outdoors. * * Indicate the state of a photo's geotagginess beyond latitude and longitude. * * Note : photos passed to this method must already be geotagged * using the flickcurl_photos_geo_setLocation() method. * * Implements flickr.photos.geo.setContext (1.8) * * Return value: non-0 on failure **/ int flickcurl_photos_geo_setContext(flickcurl* fc, const char* photo_id, int context) { xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; char context_str[3]; void* result = NULL; flickcurl_init_params(fc, 1); if(!photo_id || context < 0 || context > 2) return 1; flickcurl_add_param(fc, "photo_id", photo_id); sprintf(context_str, "%d", context); flickcurl_add_param(fc, "context", context_str); flickcurl_end_params(fc); if(flickcurl_prepare(fc, "flickr.photos.geo.setContext")) 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; } result = NULL; /* your code here */ tidy: if(xpathCtx) xmlXPathFreeContext(xpathCtx); if(fc->failed) result = NULL; return (result == NULL); }
/** * 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_blogs_postPhoto: * @fc: flickcurl context * @blog_id: The id of the blog to post to * @photo_id: The id of the photo to blog * @title: The blog post title * @description: The blog post body * @blog_password: The password for the blog (used when the blog does not have a stored password) (or NULL) * * Post a photo to a blog/ * * Implements flickr.blogs.postPhoto (1.0) * * Return value: non-0 on failure **/ int flickcurl_blogs_postPhoto(flickcurl* fc, const char* blog_id, const char* photo_id, const char* title, const char* description, const char* blog_password) { xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; flickcurl_init_params(fc, 0); if(!blog_id || !photo_id || !title || !description) return 1; flickcurl_add_param(fc, "blog_id", blog_id); flickcurl_add_param(fc, "photo_id", photo_id); flickcurl_add_param(fc, "title", title); flickcurl_add_param(fc, "description", description); if(blog_password) { flickcurl_add_param(fc, "blog_password", blog_password); } flickcurl_end_params(fc); if(flickcurl_prepare(fc, "flickr.blogs.postPhoto")) 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; } tidy: if(xpathCtx) xmlXPathFreeContext(xpathCtx); return fc->failed; }
/** * flickcurl_tags_getClusters: * @fc: flickcurl context * @tag: The tag to fetch clusters for. * * Gives you a list of tag clusters for the given tag. * * Implements flickr.tags.getClusters (1.5) * * "There is no pagination for this method as the number of clusters * for a single tag is capped at 5 and each cluster may contain * between 1 - 50 tags (give or take)." * * As announced 2008-07-17 * http://tech.groups.yahoo.com/group/yws-flickr/message/4218 * * Return value: NULL on failure **/ flickcurl_tag_clusters* flickcurl_tags_getClusters(flickcurl* fc, const char* tag) { const char* parameters[8][2]; int count = 0; xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; flickcurl_tag_clusters* clusters = NULL; if(!tag) return NULL; parameters[count][0] = "tag"; parameters[count++][1]= tag; parameters[count][0] = NULL; if(flickcurl_prepare(fc, "flickr.tags.getClusters", 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; } clusters = flickcurl_build_tag_clusters(fc, xpathCtx, (const xmlChar*)"/rsp/clusters/cluster"); tidy: if(xpathCtx) xmlXPathFreeContext(xpathCtx); if(fc->failed) clusters = NULL; return clusters; }
/** * 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_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_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_photosets_getInfo: * @fc: flickcurl context * @photoset_id: The ID of the photoset to fetch information for. * * Gets information about a photoset. * * Implements flickr.photosets.getInfo (0.13) * * Return value: non-0 on failure **/ flickcurl_photoset* flickcurl_photosets_getInfo(flickcurl* fc, const char* photoset_id) { const char* parameters[8][2]; int count = 0; xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; flickcurl_photoset* photoset = NULL; if(!photoset_id) return NULL; parameters[count][0] = "photoset_id"; parameters[count++][1]= photoset_id; parameters[count][0] = NULL; if(flickcurl_prepare(fc, "flickr.photosets.getInfo", 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; } photoset = flickcurl_build_photoset(fc, xpathCtx); tidy: if(xpathCtx) xmlXPathFreeContext(xpathCtx); if(fc->failed) photoset = NULL; return photoset; }
/** * 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_tags_getClusters: * @fc: flickcurl context * @tag: The tag to fetch clusters for. * * Gives you a list of tag clusters for the given tag. * * Implements flickr.tags.getClusters (1.5) * * "There is no pagination for this method as the number of clusters * for a single tag is capped at 5 and each cluster may contain * between 1 - 50 tags (give or take)." * * As announced 2008-07-17 * http://tech.groups.yahoo.com/group/yws-flickr/message/4218 * * Return value: NULL on failure **/ flickcurl_tag_clusters* flickcurl_tags_getClusters(flickcurl* fc, const char* tag) { xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; flickcurl_tag_clusters* clusters = NULL; flickcurl_init_params(fc); if(!tag) return NULL; flickcurl_add_param(fc, "tag", tag); flickcurl_end_params(fc); if(flickcurl_prepare(fc, "flickr.tags.getClusters")) 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; } clusters = flickcurl_build_tag_clusters(fc, xpathCtx, (const xmlChar*)"/rsp/clusters/cluster"); tidy: if(xpathCtx) xmlXPathFreeContext(xpathCtx); if(fc->failed) clusters = NULL; return clusters; }
/** * flickcurl_photosets_getInfo: * @fc: flickcurl context * @photoset_id: The ID of the photoset to fetch information for. * * Gets information about a photoset. * * Implements flickr.photosets.getInfo (0.13) * * Return value: non-0 on failure **/ flickcurl_photoset* flickcurl_photosets_getInfo(flickcurl* fc, const char* photoset_id) { xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; flickcurl_photoset* photoset = NULL; flickcurl_init_params(fc); if(!photoset_id) return NULL; flickcurl_add_param(fc, "photoset_id", photoset_id); flickcurl_end_params(fc); if(flickcurl_prepare(fc, "flickr.photosets.getInfo")) 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; } photoset = flickcurl_build_photoset(fc, xpathCtx); tidy: if(xpathCtx) xmlXPathFreeContext(xpathCtx); if(fc->failed) photoset = NULL; return photoset; }
/** * flickcurl_photos_people_deleteCoords: * @fc: flickcurl context * @photo_id: The id of the photo to edit a person in. * @user_id: The NSID of the person whose bounding box you want to remove. * * Remove the bounding box from a person in a photo * * Implements flickr.photos.people.deleteCoords (1.17) * * Announced 2010-01-21 * http://code.flickr.com/blog/2010/01/21/people-in-photos-the-api-methods/ * * Return value: non-0 on failure **/ int flickcurl_photos_people_deleteCoords(flickcurl* fc, const char* photo_id, const char* user_id) { xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; void* result = NULL; flickcurl_init_params(fc, 1); if(!photo_id || !user_id) return 1; flickcurl_add_param(fc, "photo_id", photo_id); flickcurl_add_param(fc, "user_id", user_id); flickcurl_end_params(fc); if(flickcurl_prepare(fc, "flickr.photos.people.deleteCoords")) 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; } tidy: if(xpathCtx) xmlXPathFreeContext(xpathCtx); if(fc->failed) result = NULL; return (result == NULL); }
/** * flickcurl_people_getInfo - * @fc: flickcurl context * @user_id: user NSID * * Get information about a person * * Implements flickr.people.getInfo (0.6) * * NSID can be found by flickcurl_people_findByEmail() or * flickcurl_people_findByUsername(). * * Return value: #flickcurl_person object or NULL on failure **/ flickcurl_person* flickcurl_people_getInfo(flickcurl* fc, const char* user_id) { const char * parameters[6][2]; int count=0; xmlDocPtr doc=NULL; xmlXPathContextPtr xpathCtx=NULL; flickcurl_person* person=NULL; parameters[count][0] = "user_id"; parameters[count++][1]= user_id; parameters[count][0] = NULL; if(flickcurl_prepare(fc, "flickr.people.getInfo", 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; } person=flickcurl_build_person(fc, xpathCtx, (const xmlChar*)"/rsp/person"); tidy: if(xpathCtx) xmlXPathFreeContext(xpathCtx); if(fc->failed) person=NULL; return person; }
/** * 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_people_getInfo: * @fc: flickcurl context * @user_id: user NSID * * Get information about a person * * Implements flickr.people.getInfo (0.6) * * NSID can be found by flickcurl_people_findByEmail() or * flickcurl_people_findByUsername(). * * Return value: #flickcurl_person object or NULL on failure **/ flickcurl_person* flickcurl_people_getInfo(flickcurl* fc, const char* user_id) { xmlDocPtr doc = NULL; xmlXPathContextPtr xpathCtx = NULL; flickcurl_person* person = NULL; flickcurl_init_params(fc, 0); flickcurl_add_param(fc, "user_id", user_id); flickcurl_end_params(fc); if(flickcurl_prepare(fc, "flickr.people.getInfo")) 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; } person = flickcurl_build_person(fc, xpathCtx, (const xmlChar*)"/rsp/person"); tidy: if(xpathCtx) xmlXPathFreeContext(xpathCtx); if(fc->failed) person = NULL; return person; }
/** * flickcurl_people_getUploadStatus: * @fc: flickcurl context * * Returns information for the calling user related to photo uploads. * * Implements flickr.people.getUploadStatus (0.13) * * Return value: non-0 on failure **/ flickcurl_user_upload_status* flickcurl_people_getUploadStatus(flickcurl* fc) { const char* parameters[7][2]; int count=0; xmlDocPtr doc=NULL; xmlXPathContextPtr xpathCtx=NULL; flickcurl_user_upload_status* status=NULL; parameters[count][0] = NULL; if(flickcurl_prepare(fc, "flickr.people.getUploadStatus", 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_build_user_upload_status(fc, xpathCtx, (const xmlChar*)"/rsp/user/*"); tidy: if(xpathCtx) xmlXPathFreeContext(xpathCtx); if(fc->failed) status=NULL; return status; }
/* * 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_video* flickcurl_build_video(flickcurl* fc, xmlXPathContextPtr xpathCtx, const xmlChar* xpathExpr) { flickcurl_video* v = NULL; int nodes_count; int i; xmlXPathObjectPtr xpathObj = NULL; xmlNodeSetPtr nodes; int count = 0; /* Now do video */ xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx); if(!xpathObj) { flickcurl_error(fc, "Unable to evaluate XPath expression \"%s\"", xpathExpr); fc->failed = 1; goto tidy; } nodes = xpathObj->nodesetval; /* This is a max size - it can include nodes that are CDATA */ nodes_count = xmlXPathNodeSetGetLength(nodes); v = (flickcurl_video*)calloc(1, sizeof(flickcurl_video)); if(!v) { flickcurl_error(fc, "Unable to allocate the memory needed for video."); fc->failed = 1; goto tidy; } for(i = 0; i < nodes_count; i++) { xmlNodePtr node = nodes->nodeTab[i]; xmlAttr* attr; const char *node_name = (const char*)node->name; if(node->type != XML_ELEMENT_NODE) { flickcurl_error(fc, "Got unexpected node type %d", node->type); fc->failed = 1; break; } if(strcmp(node_name, "video")) continue; count++; for(attr = node->properties; attr; attr = attr->next) { const char *attr_name = (const char*)attr->name; int attr_value = atoi((const char*)attr->children->content); if(!strcmp(attr_name, "ready")) v->ready = attr_value; else if(!strcmp(attr_name, "failed")) v->failed = attr_value; else if(!strcmp(attr_name, "pending")) v->pending = attr_value; else if(!strcmp(attr_name, "duration")) v->duration = attr_value; else if(!strcmp(attr_name, "width")) v->width = attr_value; else if(!strcmp(attr_name, "height")) v->height = attr_value; } } /* for nodes */ if(!count) { flickcurl_free_video(v); v = NULL; } #if FLICKCURL_DEBUG > 1 else { fprintf(stderr, "video: ready %d failed %d pending %d duration %d width %d height %d\n", v->ready, v->failed, v->pending, v->duration, v->width, v->height); } #endif tidy: if(xpathObj) xmlXPathFreeObject(xpathObj); return v; }
flickcurl_location* flickcurl_build_location(flickcurl* fc, xmlXPathContextPtr xpathCtx, const xmlChar* xpathExpr) { flickcurl_location* location = NULL; int nodes_count; int i; xmlXPathObjectPtr xpathObj = NULL; xmlNodeSetPtr nodes; /* Now do location */ xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx); if(!xpathObj) { flickcurl_error(fc, "Unable to evaluate XPath expression \"%s\"", xpathExpr); fc->failed = 1; goto tidy; } nodes = xpathObj->nodesetval; /* This is a max size - it can include nodes that are CDATA */ nodes_count = xmlXPathNodeSetGetLength(nodes); for(i = 0; i < nodes_count; i++) { xmlNodePtr node = nodes->nodeTab[i]; xmlAttr* attr; if(node->type != XML_ELEMENT_NODE) { flickcurl_error(fc, "Got unexpected node type %d", node->type); fc->failed = 1; break; } location = (flickcurl_location*)calloc(sizeof(flickcurl_location), 1); for(attr = node->properties; attr; attr = attr->next) { const char *attr_name = (const char*)attr->name; char *attr_value; size_t attr_value_len = strlen((const char*)attr->children->content); attr_value = (char*)malloc(attr_value_len + 1); memcpy(attr_value, attr->children->content, attr_value_len + 1); if(!strcmp(attr_name, "latitude")) location->latitude = atof(attr_value); else if(!strcmp(attr_name, "longitude")) location->longitude = atof(attr_value); else if(!strcmp(attr_name, "accuracy")) location->accuracy = atoi(attr_value); free(attr_value); } #if FLICKCURL_DEBUG > 1 fprintf(stderr, "location: lat %f long %f accuracy %d\n", location->latitude, location->longitude, location->accuracy); #endif /* Handle only first perm */ break; } /* for nodes */ tidy: if(xpathObj) xmlXPathFreeObject(xpathObj); return location; }