1 /*
  2  * XmlUtil.c
  3  *
  4  *  Created on: Jul 28, 2008
  5  *      Author: mr@marcelruff.info
  6  */
  7 #include <stdio.h> /* fseek etc */
  8 #include <string.h>
  9 #include <stdlib.h>
 10 #include <util/helper.h>
 11 #include <util/msgUtil.h>
 12 #include "XmlUtil.h"
 13 
 14 static const char * const AMP = "&amp;";
 15 static const char * const LT = "&lt;";
 16 static const char * const GT = "&gt;";
 17 static const char * const QUOT = "&quot;";
 18 static const char * const APOS = "&apos;";
 19 
 20 static const char * const SLASH_R = "&#x0D;";
 21 static const char * const NULL_ = "&#x0;";
 22 
 23 static const char * const COMMA = "&comma;";
 24 
 25 
 26 /**
 27  * <p k="Hello">
 28  * @param attributeValue if not 0 it must match as well
 29  * @param start out parameter for pos of 'H', -1 if not found
 30  * @param end out parameter for pos of '"' after 'o'
 31  *
 32  */
 33 static void xmlBlasterExtractAttributePos(const char * const xml,
 34       const char * const tag, const char * const attributeName,
 35       const char * const attributeValue, int *start, int *end) {
 36    *start = -1;
 37    *end = -1;
 38    if (xml == 0 || tag == 0 || attributeName == 0)
 39       return;
 40    {
 41       bool insideTag = false;
 42       int i;
 43       int len = (int)strlen(xml);
 44       char *startTag = strcpyAlloc("<");
 45       char *attrToken = strcpyAlloc(attributeName);
 46       startTag = strcatAlloc(&startTag, tag);
 47       attrToken = strcatAlloc(&attrToken, "=");
 48       for (i = 0; i < len; i++) {
 49          if (xml[i] == '>') {
 50             insideTag = false;
 51             continue;
 52          }
 53          if (insideTag) {
 54             if (startsWith(xml + i, attrToken)) {
 55                int pos = i + (int)strlen(attrToken);
 56                char apos = xml[pos];
 57                int curr = 0;
 58                *start = pos + 1;
 59                i = pos + 1;
 60                for (; i < len; i++, curr++) {
 61                   if (xml[i] == apos) {
 62                      *end = i;
 63                      xmlBlasterFree(startTag);
 64                      xmlBlasterFree(attrToken);
 65                      return;
 66                   }
 67                   if (attributeValue != 0) {
 68                      if (xml[i] != attributeValue[curr]) {
 69                         insideTag = false;
 70                         break;
 71                      }
 72                   }
 73                }
 74             }
 75             continue;
 76          }
 77          if (startsWith(xml + i, startTag)) {
 78             insideTag = true;
 79             continue;
 80          }
 81       }
 82       xmlBlasterFree(startTag);
 83       xmlBlasterFree(attrToken);
 84       *start = -1;
 85    }
 86 }
 87 
 88 Dll_Export char *xmlBlasterExtractAttributeValue(const char * const xml,
 89       const char * const tag, const char * const attributeName) {
 90    if (xml == 0 || tag == 0 || attributeName == 0)
 91       return 0;
 92    {
 93       int start, end;
 94       xmlBlasterExtractAttributePos(xml, tag, attributeName, 0, &start, &end);
 95       if (start >= 0) {
 96          int count = end - start;
 97          char *ret = (char *) malloc((count + 1) * sizeof(char));
 98          int j;
 99          ret[count] = 0;
100          for (j = 0; j < count; j++) {
101             ret[j] = xml[start + j];
102          }
103          return ret;
104       }
105    }
106    return 0;
107 }
108 
109 Dll_Export long xmlBlasterExtractAttributeLong(const char * const xml,
110       const char * const tag, const char * const attributeName, long defaultValue) {
111    long val = defaultValue;
112    char *valP = xmlBlasterExtractAttributeValue(xml, tag, attributeName);
113    if (valP == 0)
114       return defaultValue;
115 #  if _MSC_VER >= 1400 && !defined(WINCE)
116       if (sscanf_s(valP, "%ld", &val) == 1)
117 #  else
118       if (sscanf(valP, "%ld", &val) == 1)
119 #  endif
120       return val;
121    return defaultValue;
122 }
123 
124 Dll_Export char *xmlBlasterExtractTagValueWithAttribute(const char * const xml,
125       const char * const tag, const char * const attributeName,
126       const char * const attributeValue) {
127    if (xml == 0 || tag == 0 || attributeName == 0)
128       return 0;
129    {
130       int startAttr, endAttr;
131       xmlBlasterExtractAttributePos(xml, tag, attributeName, attributeValue,
132             &startAttr, &endAttr);
133       if (startAttr >= 0) {
134          int i;
135          int len = (int)strlen(xml);
136          for (i = endAttr; i < len; i++) {
137             if (xml[i] == '>') {
138                if (i == len - 1)
139                   return strcpyAlloc("");
140                {
141                   const char *p = strstr(xml + i, "<");
142                   int startVal = i + 1;
143                   int endTag = (p == 0) ? len : len - (int)strlen(p);
144                   int count = endTag - startVal;
145                   char *ret = (char *) malloc((count + 1) * sizeof(char));
146                   int j;
147                   ret[count] = '\0';
148                   for (j = 0; j < count; j++) {
149                      ret[j] = xml[startVal + j];
150                   }
151                   return ret;
152                }
153             }
154          }
155       }
156       return 0;
157    }
158 }
159 
160 Dll_Export char *xmlBlasterExtractTagValue(const char * const xml,
161       const char * const tag) {
162    if (xml == 0 || tag == 0)
163       return 0;
164    {
165       const char *startP = 0;
166       char *tagP = strcpyAlloc("<");
167       strcatAlloc(&tagP, tag);
168       startP = strstr(xml, tagP);
169       if (startP != 0) {
170          int i;
171          int start = -1, end = -1;
172          int len = (int)strlen(startP);
173          for (i = 1; i < len; i++) {
174             if (startP[i] == '>') {
175                start = i+1;
176             }
177             else if (startP[i] == '<') {
178                end = i;
179                break;
180             }
181          }
182          if (start >= 0 && end >= start) {
183             int j = 0;
184             int newLen = 0;
185             char *ret = (char *)malloc((end-start+1)*sizeof(char));
186             for (i = start; i < end; i++, j++) {
187                ret[j] = startP[i];
188             }
189             ret[end-start] = 0;
190             xmlBlasterFree(tagP);
191             return xmlBlasterUnEscapeXml(ret, &newLen);
192          }
193       }
194       xmlBlasterFree(tagP);
195       return 0;
196    }
197 }
198 
199 Dll_Export char* xmlBlasterEscapeXml(const char *xml) {
200    if (xml == 0)
201       return strcpyAlloc("");
202    return xmlBlasterEscapeXmlBytes((int)strlen(xml), xml);
203 }
204 
205 Dll_Export char* xmlBlasterEscapeXmlBytes(int len, const char *bytes) {
206    int i, newLen, pos;
207    char *res;
208    if (bytes == 0 || *bytes == 0 || len < 1)
209       return strcpyAlloc("");
210    newLen = len + 100;
211    res = (char *) malloc(newLen * sizeof(char));
212    memset(res, 0, newLen * sizeof(char));
213    pos = 0; /* new index */
214    for (i = 0; i < len; i++, pos++) {
215       /* Guarantee more space of at least strlen(&comma;) */
216       if (pos >= (newLen-10)) {
217          newLen += (len < 1000) ? 100 : len/10;
218          res = (char *)realloc(res, newLen * sizeof(char));
219          memset(res+pos, '\0', (size_t)(newLen-pos));
220       }
221       if (bytes[i] == '&') {
222          strcat(res + pos, AMP);
223          pos += (int)strlen(AMP)-1;
224       } else if (bytes[i] == '<') {
225          strcat(res + pos, LT);
226          pos += (int)strlen(LT)-1;
227       } else if (bytes[i] == '>') {
228          strcat(res + pos, GT);
229          pos += (int)strlen(GT)-1;
230       } else if (bytes[i] == '"') {
231          strcat(res + pos, QUOT);
232          pos += (int)strlen(QUOT)-1;
233       } else if (bytes[i] == '\'') {
234          strcat(res + pos, APOS);
235          pos += (int)strlen(APOS)-1;
236       } else if (bytes[i] == '\r') {
237          strcat(res + pos, SLASH_R);
238          pos += (int)strlen(SLASH_R)-1;
239       } else if (bytes[i] == '\0') {
240          strcat(res + pos, NULL_);
241          pos += (int)strlen(NULL_)-1;
242       } else {
243          res[pos] = bytes[i];
244       }
245    }
246    *(res + pos) = 0;
247    return res;
248 }
249 
250 Dll_Export char *xmlBlasterUnEscapeXml(char * const xml, int *newLen) {
251    int i, len, pos;
252    *newLen = 0;
253    if (xml == 0)
254       return xml;
255    len = (int)strlen(xml);
256    pos = 0; /* new index */
257    for (i = 0; i < len; i++, pos++) {
258       if (xml[i] != '&') {
259          xml[pos] = xml[i];
260          continue;
261       }
262       if (startsWith(xml + i, AMP)) {
263          xml[pos] = '&';
264          i += (int)strlen(AMP) - 1;
265       } else if (startsWith(xml + i, LT)) {
266          xml[pos] = '<';
267          i += (int)strlen(LT) - 1;
268       } else if (startsWith(xml + i, GT)) {
269          xml[pos] = '>';
270          i += (int)strlen(GT) - 1;
271       } else if (startsWith(xml + i, QUOT)) {
272          xml[pos] = '"';
273          i += (int)strlen(QUOT) - 1;
274       } else if (startsWith(xml + i, APOS)) {
275          xml[pos] = '\'';
276          i += (int)strlen(APOS) - 1;
277       } else if (startsWith(xml + i, SLASH_R)) {
278          xml[pos] = '\r';
279          i += (int)strlen(SLASH_R) - 1;
280       } else if (startsWith(xml + i, NULL_)) {
281          xml[pos] = '\0';
282          i += (int)strlen(NULL_) - 1;
283       }
284    }
285    *(xml + pos) = 0;
286    *newLen = pos;
287    return xml;
288 }
289 
290 Dll_Export char* xmlBlasterEscapeCSV(const char *csv) {
291    int i, len, pos;
292    char *res;
293    if (csv == 0 || *csv == 0)
294       return strcpyAlloc("");
295    len = (int)strlen(csv);
296    res = (char *) malloc(5 * len * sizeof(char));
297    memset(res, 0, 5 * len * sizeof(char));
298    pos = 0; /* new index */
299    for (i = 0; i < len; i++, pos++) {
300       if (csv[i] == ',') {
301          strcat(res + pos, COMMA);
302          pos += (int)strlen(COMMA)-1;
303       } else {
304          res[pos] = csv[i];
305       }
306    }
307    *(res + pos) = 0;
308    return res;
309 }
310 
311 Dll_Export char *xmlBlasterUnEscapeCSV(char * const csv, int *newLen) {
312    int i, len, pos;
313    *newLen = 0;
314    if (csv == 0)
315       return csv;
316    len = (int)strlen(csv);
317    pos = 0; /* new index */
318    for (i = 0; i < len; i++, pos++) {
319       if (csv[i] != '&') {
320          csv[pos] = csv[i];
321          continue;
322       }
323       if (startsWith(csv + i, COMMA)) {
324          csv[pos] = ',';
325          i += (int)strlen(COMMA) - 1;
326       }
327    }
328    *(csv + pos) = 0;
329    *newLen = pos;
330    return csv;
331 }
332 
333 Dll_Export char *xmlBlasterReadBinaryFile(const char *name, int *len)
334 {
335    FILE *file;
336    char *buffer = 0;
337    unsigned long fileLen;
338 
339    *len = 0;
340 
341    file = fopen(name, "rb");
342    if (!file)
343    {
344       fprintf(stderr, "xmlBlasterReadBinaryFile: Unable to open file %s\n", name);
345       return 0;
346    }
347 
348    /*Get file length*/
349    fseek(file, 0, SEEK_END);
350    fileLen=ftell(file);
351    fseek(file, 0, SEEK_SET);
352 
353    buffer=(char *)malloc(fileLen+1);
354    if (!buffer)
355    {
356       fprintf(stderr, "xmlBlasterReadBinaryFile: Memory error!\n");
357                                 fclose(file);
358       return 0;
359    }
360 
361    *len = (int)fread(buffer, 1, fileLen, file);
362    fclose(file);
363 
364    return buffer;
365 }


syntax highlighted by Code2HTML, v. 0.9.1