1 /* -*- Mode: c; c-basic-offset: 2 -*-
2  *
3  * note.c - Flickcurl note functions
4  *
5  * Copyright (C) 2010, David Beckett http://www.dajobe.org/
6  *
7  * This file is licensed under the following three licenses as alternatives:
8  *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
9  *   2. GNU General Public License (GPL) V2 or any newer version
10  *   3. Apache License, V2.0 or any newer version
11  *
12  * You may not use this file except in compliance with at least one of
13  * the above three licenses.
14  *
15  * See LICENSE.html or LICENSE.txt at the top of this package for the
16  * complete terms and further detail along with the license texts for
17  * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
18  *
19  */
20 
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdarg.h>
24 
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28 
29 #ifdef WIN32
30 #include <win32_flickcurl_config.h>
31 #endif
32 
33 #include <flickcurl.h>
34 #include <flickcurl_internal.h>
35 
36 
37 /**
38  * flickcurl_free_note:
39  * @note: note object
40  *
41  * Destructor for note object
42  */
43 void
flickcurl_free_note(flickcurl_note * note)44 flickcurl_free_note(flickcurl_note *note)
45 {
46   FLICKCURL_ASSERT_OBJECT_POINTER_RETURN(note, flickcurl_note);
47 
48   if(note->author)
49     free(note->author);
50   if(note->authorname)
51     free(note->authorname);
52   if(note->text)
53     free(note->text);
54   free(note);
55 }
56 
57 
58 flickcurl_note**
flickcurl_build_notes(flickcurl * fc,flickcurl_photo * photo,xmlXPathContextPtr xpathCtx,const xmlChar * xpathExpr,int * note_count_p)59 flickcurl_build_notes(flickcurl* fc, flickcurl_photo* photo,
60                       xmlXPathContextPtr xpathCtx, const xmlChar* xpathExpr,
61                       int* note_count_p)
62 {
63   flickcurl_note** notes = NULL;
64   int nodes_count;
65   int note_count;
66   int i;
67   xmlXPathObjectPtr xpathObj = NULL;
68   xmlNodeSetPtr nodes;
69 
70   /* Now do notes */
71   xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx);
72   if(!xpathObj) {
73     flickcurl_error(fc, "Unable to evaluate XPath expression \"%s\"",
74                     xpathExpr);
75     fc->failed = 1;
76     goto tidy;
77   }
78 
79   nodes = xpathObj->nodesetval;
80   /* This is a max size - it can include nodes that are CDATA */
81   nodes_count = xmlXPathNodeSetGetLength(nodes);
82   notes = (flickcurl_note**)calloc(sizeof(flickcurl_note*), nodes_count+1);
83 
84   for(i = 0, note_count = 0; i < nodes_count; i++) {
85     xmlNodePtr node = nodes->nodeTab[i];
86     xmlAttr* attr;
87     flickcurl_note* n;
88     xmlNodePtr chnode;
89 
90     if(node->type != XML_ELEMENT_NODE) {
91       flickcurl_error(fc, "Got unexpected node type %d", node->type);
92       fc->failed = 1;
93       break;
94     }
95 
96     n = (flickcurl_note*)calloc(sizeof(flickcurl_note), 1);
97 
98     for(attr = node->properties; attr; attr = attr->next) {
99       size_t attr_len = strlen((const char*)attr->children->content);
100       const char *attr_name = (const char*)attr->name;
101       char *attr_value;
102 
103       attr_value = (char*)malloc(attr_len + 1);
104       memcpy(attr_value, attr->children->content, attr_len + 1);
105 
106       if(!strcmp(attr_name, "id")) {
107         n->id = atoi(attr_value);
108         free(attr_value);
109       } else if(!strcmp(attr_name, "author"))
110         n->author = attr_value;
111       else if(!strcmp(attr_name, "authorname"))
112         n->authorname = attr_value;
113       else if(!strcmp(attr_name, "x")) {
114         n->x = atoi(attr_value);
115         free(attr_value);
116       } else if(!strcmp(attr_name, "y")) {
117         n->y = atoi(attr_value);
118         free(attr_value);
119       } else if(!strcmp(attr_name, "w")) {
120         n->w = atoi(attr_value);
121         free(attr_value);
122       } else if(!strcmp(attr_name, "h")) {
123         n->h = atoi(attr_value);
124         free(attr_value);
125       } else
126         free(attr_value);
127     }
128 
129     /* Walk children nodes for text */
130     for(chnode = node->children; chnode; chnode = chnode->next) {
131       if(chnode->type == XML_TEXT_NODE) {
132         size_t len = strlen((const char*)chnode->content);
133         n->text = (char*)malloc(len + 1);
134         memcpy(n->text, chnode->content, len + 1);
135       }
136     }
137 
138 #if FLICKCURL_DEBUG > 1
139     fprintf(stderr, "note: id %d author ID %s name %s x %d y %d w %d h %d text '%s'\n",
140             n->id, n->author, n->authorname, n->x, n->y, n->w, n->h, n->text);
141 #endif
142 
143     notes[note_count++] = n;
144   } /* for nodes */
145 
146   if(note_count_p)
147     *note_count_p = note_count;
148 
149  tidy:
150   if(xpathObj)
151     xmlXPathFreeObject(xpathObj);
152 
153   return notes;
154 }
155