ccn_ccnbtoxml.c

Go to the documentation of this file.
00001 /**
00002  * @file ccn_ccnbtoxml.c
00003  * Utility to convert ccn binary encoded data into XML form.
00004  *
00005  * A CCNx command-line utility.
00006  *
00007  * Copyright (C) 2008-2010 Palo Alto Research Center, Inc.
00008  *
00009  * This work is free software; you can redistribute it and/or modify it under
00010  * the terms of the GNU General Public License version 2 as published by the
00011  * Free Software Foundation.
00012  * This work is distributed in the hope that it will be useful, but WITHOUT ANY
00013  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
00015  * for more details. You should have received a copy of the GNU General Public
00016  * License along with this program; if not, write to the
00017  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019  */
00020 
00021 #include <fcntl.h>
00022 #include <limits.h>
00023 #include <stddef.h>
00024 #include <stdio.h>
00025 #include <stdint.h>
00026 #include <stdlib.h>
00027 #include <string.h>
00028 #include <unistd.h>
00029 #include <ctype.h>
00030 
00031 #include <ccn/charbuf.h>
00032 #include <ccn/coding.h>
00033 #include <ccn/extend_dict.h>
00034 
00035 static void
00036 usage(const char *progname)
00037 {
00038     fprintf(stderr,
00039             "usage: %s [-h] [-b] [-t] [-v] [-x] [-s prefix] [-d dict]* file ...\n"
00040             " Utility to convert ccn binary encoded data into XML form.\n"
00041             "  -b      force (base64 or hex) Binary output instead of text\n"
00042             "  -t      test, when specified, should be only switch\n"
00043             "  -v      verbose - do extra decoding as comments\n"
00044             "  -x      prefer hex output to base64\n"
00045             "  -s pat  provide a single pattern to be used when "
00046             "splitting one or more input files\n"
00047             "  -d dict use this option one or more times to specify additional\n"
00048             "          csv format dictionary files that extend the builtin dtag table\n"
00049             " switches may not be mixed with file name arguments\n"
00050             " use - for file to specify stdin\n"
00051             " in absence of -s option, result is on stdout\n",
00052             progname);
00053     exit(1);
00054 }
00055 
00056 #define CCN_NO_SCHEMA INT_MIN
00057 #define CCN_UNKNOWN_SCHEMA (INT_MIN+1)
00058 
00059 struct ccn_decoder_stack_item {
00060     size_t nameindex; /* byte index into stringstack */
00061     size_t savedss;
00062     int saved_schema;
00063     int saved_schema_state;
00064     struct ccn_decoder_stack_item *link;
00065 };
00066 
00067 struct ccn_decoder;
00068 enum callback_kind {
00069     CALLBACK_INITIAL,
00070     CALLBACK_OBJECTEND,
00071     CALLBACK_FINAL
00072 };
00073 
00074 typedef void (*ccn_decoder_callback)(
00075     struct ccn_decoder *d,
00076     enum callback_kind kind,
00077     void *data
00078 );
00079 
00080 struct ccn_decoder {
00081     int state;
00082     int tagstate;
00083     int bits;
00084     size_t numval;
00085     uintmax_t bignumval;
00086     int schema;
00087     int sstate;
00088     struct ccn_decoder_stack_item *stack;
00089     struct ccn_charbuf *stringstack;
00090     const struct ccn_dict_entry *tagdict;
00091     int tagdict_count;
00092     ccn_decoder_callback callback;
00093     void *callbackdata;
00094     int formatting_flags;
00095     int base64_char_count;
00096     struct ccn_charbuf *annotation;
00097 };
00098 /* formatting_flags */
00099 #define FORCE_BINARY   (1 << 0)
00100 #define PREFER_HEX     (1 << 1)
00101 #define VERBOSE_DECODE (1 << 2)
00102 
00103 struct ccn_decoder *
00104 ccn_decoder_create(int formatting_flags, const struct ccn_dict *dtags)
00105 {
00106     struct ccn_decoder *d;
00107     d = calloc(1, sizeof(*d));
00108     d->stringstack = ccn_charbuf_create();
00109     if (d->stringstack == NULL) {
00110         free(d);
00111         d = NULL;
00112         return(NULL);
00113     }
00114     d->schema = CCN_NO_SCHEMA;
00115     d->tagdict = dtags->dict;
00116     d->tagdict_count = dtags->count;
00117     d->formatting_flags = formatting_flags;
00118     d->annotation = NULL;
00119     return(d);
00120 }
00121 
00122 void
00123 ccn_decoder_set_callback(struct ccn_decoder *d, ccn_decoder_callback c, void *data)
00124 {
00125     d->callback = c;
00126     if (c == NULL) {
00127         d->callbackdata = NULL;
00128     } else {
00129         d->callbackdata = data;
00130         c(d, CALLBACK_INITIAL, data);
00131     }
00132 }
00133 
00134 struct ccn_decoder_stack_item *
00135 ccn_decoder_push(struct ccn_decoder *d)
00136 {
00137     struct ccn_decoder_stack_item *s;
00138     s = calloc(1, sizeof(*s));
00139     if (s != NULL) {
00140         s->link = d->stack;
00141         s->savedss = d->stringstack->length;
00142         s->saved_schema = d->schema;
00143         s->saved_schema_state = d->sstate;
00144         d->stack = s;
00145     }
00146     return(s);
00147 }
00148 
00149 void
00150 ccn_decoder_pop(struct ccn_decoder *d)
00151 {
00152     struct ccn_decoder_stack_item *s = d->stack;
00153     if (s != NULL) {
00154         d->stack = s->link;
00155         d->stringstack->length = s->savedss;
00156         d->schema = s->saved_schema;
00157         d->sstate = s->saved_schema_state;
00158         free(s);
00159     }
00160 }
00161 
00162 void
00163 ccn_decoder_destroy(struct ccn_decoder **dp)
00164 {
00165     struct ccn_decoder *d = *dp;
00166     if (d != NULL) {
00167         if (d->callback != NULL) {
00168             d->callback(d, CALLBACK_FINAL, d->callbackdata);
00169         }
00170         while (d->stack != NULL) {
00171             ccn_decoder_pop(d);
00172         }
00173         ccn_charbuf_destroy(&(d->stringstack));
00174         free(d);
00175         *dp = NULL;
00176     }
00177 }
00178 
00179 static const char *
00180 dict_name_from_number(int ndx, const struct ccn_dict_entry *dict, int n)
00181 {
00182     int i;
00183     for (i = 0; i < n; i++)
00184         if (ndx == dict[i].index)
00185             return (dict[i].name);
00186     return (NULL);
00187 }
00188 
00189 static const char Base64[] =
00190   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00191 
00192 static int
00193 is_text_encodable(unsigned char p[], size_t start, size_t length)
00194 {
00195     size_t i;
00196 
00197     if (length == 0) return (0);
00198     for (i = 0; i < length; i++) {
00199         char c = p[start + i];
00200         if (c < ' ' || c > '~') return (0);
00201         if (c == '<' || c == '>' || c == '&') return (0);
00202     }
00203     return (1);
00204 }
00205 
00206 /* c.f. ccn_uri_append_percentescaped */
00207 static void
00208 print_percent_escaped(const unsigned char *data, size_t size)
00209 {
00210     size_t i;
00211     unsigned char ch;
00212     for (i = 0; i < size && data[i] == '.'; i++)
00213         continue;
00214     /* For a component that consists solely of zero or more dots, add 3 more */
00215     if (i == size)
00216         printf("...");
00217     for (i = 0; i < size; i++) {
00218         ch = data[i];
00219         /*
00220          * Leave unescaped only the generic URI unreserved characters.
00221          * See RFC 3986. Here we assume the compiler uses ASCII.
00222          */
00223         if (('a' <= ch && ch <= 'z') ||
00224             ('A' <= ch && ch <= 'Z') ||
00225             ('0' <= ch && ch <= '9') ||
00226             ch == '-' || ch == '.' || ch == '_' || ch == '~')
00227             printf("%c", ch);
00228         else
00229             printf("%%%02X", (unsigned)ch);
00230     }
00231 }
00232 
00233 size_t
00234 ccn_decoder_decode(struct ccn_decoder *d, unsigned char p[], size_t n)
00235 {
00236     int state = d->state;
00237     int tagstate = 0;
00238     size_t numval = d->numval;
00239     size_t i = 0;
00240     unsigned char c;
00241     size_t chunk;
00242     struct ccn_decoder_stack_item *s;
00243     const char *tagname;
00244     while (i < n) {
00245         switch (state) {
00246             case 0: /* start new thing */
00247                 if (tagstate > 1 && tagstate-- == 2) {
00248                     printf("\""); /* close off the attribute value */
00249                     ccn_decoder_pop(d);
00250                 } 
00251                 if (p[i] == CCN_CLOSE) {
00252                     i++;
00253                     s = d->stack;
00254                     if (s == NULL || tagstate > 1) {
00255                         state = -__LINE__;
00256                         break;
00257                     }
00258                     if (tagstate == 1) {
00259                         tagstate = 0;
00260                         printf("/>");
00261                     }
00262                     else if (d->schema == -1-CCN_PROCESSING_INSTRUCTIONS) {
00263                         printf("?>");
00264                         if (d->sstate != 2) {
00265                             state = -__LINE__;
00266                             break;
00267                         }
00268                     }
00269                     else {
00270                         printf("</%s>", d->stringstack->buf + s->nameindex);
00271                     }
00272                     if (d->annotation != NULL) {
00273                         if (d->annotation->length > 0) {
00274                             printf("<!--       ");
00275                             print_percent_escaped(d->annotation->buf, d->annotation->length);
00276                             printf(" -->");
00277                         }
00278                         ccn_charbuf_destroy(&d->annotation);
00279                     }
00280                     ccn_decoder_pop(d);
00281                     if (d->stack == NULL) {
00282                         if (d->callback != NULL)
00283                             d->callback(d, CALLBACK_OBJECTEND, d->callbackdata);
00284                         else
00285                             printf("\n");
00286                     }
00287                     break;
00288                 }
00289                 numval = 0;
00290                 state = 1;
00291                 /* FALLTHRU */
00292             case 1: /* parsing numval */
00293                 c = p[i++];
00294                 if ((c & CCN_TT_HBIT) == CCN_CLOSE) {
00295                     if (numval > (numval << 7)) {
00296                         state = 9;
00297                         d->bignumval = numval;
00298                         i--;
00299                         continue;
00300                     }
00301                     numval = (numval << 7) + (c & 127);
00302                     if (numval > (numval << (7-CCN_TT_BITS))) {
00303                         state = 9;
00304                         d->bignumval = numval;
00305                     }
00306                 }
00307                 else {
00308                     numval = (numval << (7-CCN_TT_BITS)) +
00309                              ((c >> CCN_TT_BITS) & CCN_MAX_TINY);
00310                     c &= CCN_TT_MASK;
00311                     switch (c) {
00312                         case CCN_EXT:
00313                             if (tagstate == 1) {
00314                                 tagstate = 0;
00315                                 printf(">");
00316                             }
00317                             s = ccn_decoder_push(d);
00318                             s->nameindex = d->stringstack->length;
00319                             d->schema = -1-numval;
00320                             d->sstate = 0;
00321                             switch (numval) {
00322                                 case CCN_PROCESSING_INSTRUCTIONS:
00323                                     printf("<?");
00324                                     break;
00325                                 default:
00326                                     state = -__LINE__;
00327                             }
00328                             state = 0;
00329                             break;
00330                         case CCN_DTAG:
00331                             if (tagstate == 1) {
00332                                 tagstate = 0;
00333                                 printf(">");
00334                             }
00335                             s = ccn_decoder_push(d);
00336                             s->nameindex = d->stringstack->length;
00337                             d->schema = numval;
00338                             d->sstate = 0;
00339                             tagname = NULL;
00340                             if (numval <= INT_MAX)
00341                                 tagname = dict_name_from_number(numval, d->tagdict, d->tagdict_count);
00342                             if (tagname == NULL) {
00343                                 fprintf(stderr,
00344                                         "*** Warning: unrecognized DTAG %lu\n",
00345                                         (unsigned long)numval);
00346                                 ccn_charbuf_append(d->stringstack,
00347                                                    "UNKNOWN_DTAG",
00348                                                    sizeof("UNKNOWN_DTAG"));
00349                                 printf("<%s code=\"%lu\"",
00350                                        d->stringstack->buf + s->nameindex,
00351                                        (unsigned long)d->schema);
00352                                 d->schema = CCN_UNKNOWN_SCHEMA;
00353                             }
00354                             else {
00355                                 ccn_charbuf_append(d->stringstack, tagname, strlen(tagname)+1);
00356                                 printf("<%s", tagname);
00357                             }
00358                             if ((d->formatting_flags & VERBOSE_DECODE) != 0) {
00359                                 if (d->annotation != NULL)
00360                                     abort();
00361                                 if (numval == 15 /* Component */)
00362                                     d->annotation = ccn_charbuf_create();
00363                             }
00364                             tagstate = 1;
00365                             state = 0;
00366                             break;
00367                         case CCN_BLOB:
00368                             if (numval > n - i) {
00369                                 state = -__LINE__;
00370                                 break;
00371                             }                                                        
00372                             if (tagstate == 1) {
00373                                 tagstate = 0;
00374                                 if ((d->formatting_flags & FORCE_BINARY) == 0 && is_text_encodable(p, i, numval)) {
00375                                     printf(" ccnbencoding=\"text\">");
00376                                     state =  6;
00377                                 }
00378                                 else if ((d->formatting_flags & PREFER_HEX) != 0) {
00379                                     printf(" ccnbencoding=\"hexBinary\">");
00380                                     state = 2;
00381                                 }
00382                                 else {
00383                                     printf(" ccnbencoding=\"base64Binary\">");
00384                                     state = 10;
00385                                 }
00386                             }
00387                             else {
00388                                 fprintf(stderr, "blob not tagged in xml output\n");
00389                                 state = 10;
00390                             }
00391                             state = (numval == 0) ? 0 : state;
00392                             d->base64_char_count = 0;
00393                             break;
00394                         case CCN_UDATA:
00395                             if (tagstate == 1) {
00396                                 tagstate = 0;
00397                                 printf(">");
00398                             }
00399                             state = 3;
00400                             if (d->schema == -1-CCN_PROCESSING_INSTRUCTIONS) {
00401                                 if (d->sstate > 0) {
00402                                     printf(" ");
00403                                 }
00404                                 state = 6;
00405                                 d->sstate += 1;
00406                             }
00407                             if (numval == 0)
00408                                 state = 0;
00409                             break;
00410                         case CCN_DATTR:
00411                             if (tagstate != 1) {
00412                                 state = -__LINE__;
00413                                 break;
00414                             }
00415                             s = ccn_decoder_push(d);
00416                             ccn_charbuf_reserve(d->stringstack, 1);
00417                             s->nameindex = d->stringstack->length;
00418                             printf(" UNKNOWN_DATTR_%lu=\"", (unsigned long)numval);
00419                             tagstate = 3;
00420                             state = 0;
00421                             break;
00422                         case CCN_ATTR:
00423                             if (tagstate != 1) {
00424                                 state = -__LINE__;
00425                                 break;
00426                             }
00427                             if (numval >= n - i) {
00428                                 state = -__LINE__;
00429                                 break;
00430                             }                            
00431                             numval += 1; /* encoded as length-1 */
00432                             s = ccn_decoder_push(d);
00433                             ccn_charbuf_reserve(d->stringstack, numval + 1);
00434                             s->nameindex = d->stringstack->length;
00435                             state = 5;
00436                             break;
00437                         case CCN_TAG:
00438                             if (tagstate == 1) {
00439                                 tagstate = 0;
00440                                 printf(">");
00441                             }
00442                             if (numval >= n - i) {
00443                                 state = -__LINE__;
00444                                 break;
00445                             }                                                        
00446                             numval += 1; /* encoded as length-1 */
00447                             s = ccn_decoder_push(d);
00448                             ccn_charbuf_reserve(d->stringstack, numval + 1);
00449                             s->nameindex = d->stringstack->length;
00450                             state = 4;
00451                             break;
00452                         default:
00453                             state = -__LINE__;
00454                     }
00455                 }
00456                 break;
00457             case 2: /* hex BLOB */
00458                 c = p[i++];
00459                 if (d->annotation != NULL)
00460                     ccn_charbuf_append_value(d->annotation, c, 1);
00461                 printf("%02X", c);
00462                 if (--numval == 0) {
00463                     state = 0;
00464                 }
00465                 break;
00466             case 3: /* utf-8 data */
00467                 c = p[i++];
00468                 if (--numval == 0) {
00469                     state = 0;
00470                 }
00471                 switch (c) {
00472                     case 0:
00473                         state = -__LINE__;
00474                         break;
00475                     case '&':
00476                         printf("&amp;");
00477                         break;
00478                     case '<':
00479                         printf("&lt;");
00480                         break;
00481                     case '>':
00482                         printf("&gt;");
00483                         break;
00484                     case '"':
00485                         printf("&quot;");
00486                         break;
00487                     default:
00488                         printf("%c", c);
00489                 }
00490                 break;
00491             case 4: /* parsing tag name */
00492             case 5: /* parsing attribute name */
00493                 chunk = n - i;
00494                 if (chunk > numval) {
00495                     chunk = numval;
00496                 }
00497                 if (chunk == 0) {
00498                     state = -__LINE__;
00499                     break;
00500                 }
00501                 ccn_charbuf_append(d->stringstack, p + i, chunk);
00502                 numval -= chunk;
00503                 i += chunk;
00504                 if (numval == 0) {
00505                     ccn_charbuf_append(d->stringstack, (const unsigned char *)"\0", 1);
00506                     s = d->stack;
00507                     if (s == NULL ||
00508                         strlen((char*)d->stringstack->buf + s->nameindex) != 
00509                             d->stringstack->length -1 - s->nameindex) {
00510                         state = -__LINE__;
00511                         break;
00512                     }
00513                     if (state == 4) {
00514                         printf("<%s", d->stringstack->buf + s->nameindex);
00515                         tagstate = 1;
00516                     }
00517                     else {
00518                         printf(" %s=\"", d->stringstack->buf + s->nameindex);
00519                         tagstate = 3;
00520                     }
00521                     state = 0;
00522                 }
00523                 break;
00524             case 6: /* processing instructions and text blobs */
00525                 c = p[i++];
00526                 if (--numval == 0) {
00527                     state = 0;
00528                 }
00529                 printf("%c", c);
00530                 break;
00531             case 9: /* parsing big numval - cannot be a length anymore */
00532                 c = p[i++];
00533                 if ((c & CCN_TT_HBIT) == CCN_CLOSE) {
00534                     d->bignumval = (d->bignumval << 7) + (c & 127);
00535                 }
00536                 else {
00537                     d->bignumval = (d->bignumval << (7-CCN_TT_BITS)) +
00538                                    ((c >> CCN_TT_BITS) & CCN_MAX_TINY);
00539                     c &= CCN_TT_MASK;
00540                     if (tagstate == 1) {
00541                         tagstate = 0;
00542                         printf(">");
00543                     }
00544                     /*
00545                      * There's nothing that we actually need the bignumval
00546                      * for, so we can probably GC this whole state and
00547                      * give up earlier.
00548                      */
00549                     switch (c) {
00550                         default:
00551                             state = -__LINE__;
00552                     }
00553                 }
00554                 break;
00555             case 10: /* base 64 BLOB - phase 0 */
00556                 c = p[i++];
00557                 if (d->annotation != NULL)
00558                     ccn_charbuf_append_value(d->annotation, c, 1);
00559                 printf("%c", Base64[c >> 2]);
00560                 d->base64_char_count++;
00561                 if (--numval == 0) {
00562                     printf("%c==", Base64[(c & 3) << 4]);
00563                     state = 0;
00564                     d->base64_char_count += 3;
00565                 }
00566                 else {
00567                     d->bits = (c & 3);
00568                     state = 11;
00569                 }
00570                 if ((d->formatting_flags & FORCE_BINARY) == 0 && d->base64_char_count >= 64) {
00571                     d->base64_char_count = 0;
00572                     printf("\n");
00573                 }
00574                 break;
00575             case 11: /* base 64 BLOB - phase 1 */
00576                 c = p[i++];
00577                 if (d->annotation != NULL)
00578                     ccn_charbuf_append_value(d->annotation, c, 1);
00579                 printf("%c", Base64[((d->bits & 3) << 4) + (c >> 4)]);
00580                 d->base64_char_count++;
00581                 if (--numval == 0) {
00582                     printf("%c=", Base64[(c & 0xF) << 2]);
00583                     state = 0;
00584                     d->base64_char_count += 2;
00585                 }
00586                 else {
00587                     d->bits = (c & 0xF);
00588                     state = 12;
00589                 }
00590                 if ((d->formatting_flags & FORCE_BINARY) == 0 && d->base64_char_count >= 64) {
00591                     d->base64_char_count = 0;
00592                     printf("\n");
00593                 }
00594                 break;
00595             case 12: /* base 64 BLOB - phase 2 */
00596                 c = p[i++];
00597                 if (d->annotation != NULL)
00598                     ccn_charbuf_append_value(d->annotation, c, 1);
00599                 printf("%c%c", Base64[((d->bits & 0xF) << 2) + (c >> 6)],
00600                                Base64[c & 0x3F]);
00601                 d->base64_char_count += 2;
00602                 if (--numval == 0) {
00603                     state = 0;
00604                 }
00605                 else {
00606                     state = 10;
00607                 }
00608                 if ((d->formatting_flags & FORCE_BINARY) == 0 && d->base64_char_count >= 64) {
00609                     d->base64_char_count = 0;
00610                     printf("\n");
00611                 }
00612                 break;
00613             default:
00614                 n = i;
00615         }
00616     }
00617     d->state = state;
00618     d->tagstate = tagstate;
00619     d->numval = numval;
00620     return(i);
00621 }
00622 
00623 static int
00624 process_data(struct ccn_decoder *d, unsigned char *data, size_t n)
00625 {
00626     int res = 0;
00627     size_t s;
00628     printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
00629     s = ccn_decoder_decode(d, data, n);
00630     if (d->state != 0 || s < n || d->stack != NULL || d->tagstate != 0) {
00631         res = 1;
00632         fprintf(stderr, "error state %d after %d of %d chars\n",
00633             (int)d->state, (int)s, (int)n);
00634     }
00635     return(res);
00636 }
00637 
00638 static int
00639 process_fd(struct ccn_decoder *d, int fd)
00640 {
00641     struct ccn_charbuf *c = ccn_charbuf_create();
00642     ssize_t len;
00643     int res = 0;
00644     for (;;) {
00645         unsigned char *p = ccn_charbuf_reserve(c, 80);
00646         if (p == NULL) {
00647             perror("ccn_charbuf_reserve");
00648             res = 1;
00649             break;
00650         }
00651         len = read(fd, p, c->limit - c->length);
00652         if (len <= 0) {
00653             if (len == -1) {
00654                 perror("read");
00655                 res = 1;
00656             }
00657             break;
00658         }
00659         c->length += len;
00660     }
00661     fprintf(stderr, " <!-- input is %6lu bytes -->\n", (unsigned long)c->length);
00662     res |= process_data(d, c->buf, c->length);
00663     ccn_charbuf_destroy(&c);
00664     return(res);
00665 }
00666 
00667 
00668 static int
00669 process_file(char *path, int formatting_flags, const struct ccn_dict *dtags)
00670 {
00671     int fd = 0;
00672     int res = 0;
00673     struct ccn_decoder *d;
00674 
00675     if (0 != strcmp(path, "-")) {
00676         fd = open(path, O_RDONLY);
00677         if (-1 == fd) {
00678             perror(path);
00679             return(1);
00680         }
00681     }
00682 
00683     d = ccn_decoder_create(formatting_flags, dtags);
00684     if (d == NULL) {
00685         fprintf(stderr, "Unable to allocate decoder\n");
00686         return(1);
00687     }
00688     res = process_fd(d, fd);
00689     ccn_decoder_destroy(&d);
00690 
00691     if (fd > 0)
00692         close(fd);
00693     return(res);
00694 }
00695 
00696 struct callback_state {
00697     int fragment;
00698     char *fileprefix;
00699 };
00700 
00701 static void
00702 set_stdout(struct ccn_decoder *d, enum callback_kind kind, void *data)
00703 {
00704     struct callback_state *cs = (struct callback_state *)data;
00705     char filename[256];
00706     FILE *fp;
00707     switch (kind) {
00708     case CALLBACK_INITIAL:
00709     case CALLBACK_OBJECTEND:
00710         snprintf(filename, sizeof(filename), "%s%05d.xml", cs->fileprefix, cs->fragment++);
00711         fprintf(stderr, " <!-- attaching stdout to %s --!>\n", filename);
00712         fp = freopen(filename, "w+", stdout);
00713         if (fp == NULL)
00714             perror(filename);
00715         break;
00716     case CALLBACK_FINAL:
00717         fflush(stdout);
00718         fclose(stdout);
00719         free(cs);
00720         break;
00721     }
00722 }
00723 
00724 static int
00725 process_split_file(char *base, char *path, int formatting_flags,
00726                    const struct ccn_dict *dtags, int *suffix)
00727 {
00728     int fd = 0;
00729     int res = 0;
00730     struct ccn_decoder *d;
00731     struct callback_state *cs;
00732 
00733     if (0 != strcmp(path, "-")) {
00734         fd = open(path, O_RDONLY);
00735         if (-1 == fd) {
00736             perror(path);
00737             return(1);
00738         }
00739     }
00740     
00741     cs = calloc(1, sizeof(*cs));
00742     cs->fileprefix = base;
00743     cs->fragment = *suffix;
00744     d = ccn_decoder_create(formatting_flags, dtags);
00745     if (d == NULL) {
00746         fprintf(stderr, "Unable to allocate decoder\n");
00747         return(1);
00748     }
00749     ccn_decoder_set_callback(d, set_stdout, cs);
00750     res = process_fd(d, fd);
00751     *suffix = cs->fragment;
00752     ccn_decoder_destroy(&d);
00753     if (fd > 0)
00754         close(fd);
00755     return(res);
00756 }
00757 
00758 #define L (CCN_TT_HBIT & ~CCN_CLOSE)
00759 unsigned char test1[] = {
00760     (2 << CCN_TT_BITS) + CCN_TAG + L, 'F', 'o', 'o',
00761     (0 << CCN_TT_BITS) + CCN_TAG + L, 'a',
00762     (1 << CCN_TT_BITS) + CCN_UDATA + L, 'X',
00763                CCN_CLOSE,
00764     (0 << CCN_TT_BITS) + CCN_TAG + L, 'b',
00765     (3 << CCN_TT_BITS) + CCN_ATTR + L, 't', 'y', 'p', 'e',
00766     (5 << CCN_TT_BITS) + CCN_UDATA + L, 'e', 'm', 'p', 't', 'y',
00767                CCN_CLOSE,
00768     (2 << CCN_TT_BITS) + CCN_TAG + L, 'b', 'i', 'n',
00769     (4 << CCN_TT_BITS) + CCN_BLOB + L, 1, 0x23, 0x45, 0x67,
00770                CCN_CLOSE,
00771     (CCN_CLOSE + ((20-1) >> (7-CCN_TT_BITS))),
00772     (((20-1) & CCN_TT_MASK) << CCN_TT_BITS) + CCN_TAG + L,
00773         'a', 'b', 'c', 'd',  'a', 'b', 'c', 'd', 
00774         'a', 'b', 'c', 'd',  'a', 'b', 'c', 'd',
00775         'a', 'b', 'c', 'd',
00776                CCN_CLOSE,
00777     (2 << CCN_TT_BITS) + CCN_TAG + L, 'i', 'n', 't',
00778     (3 << CCN_TT_BITS) + CCN_ATTR + L, 't', 'y', 'p', 'e',
00779     (3 << CCN_TT_BITS) + CCN_UDATA + L, 'B', 'I', 'G',
00780                CCN_CLOSE,
00781     (6 << CCN_TT_BITS) + CCN_UDATA + L,
00782     'H','i','&','b','y','e',
00783                CCN_CLOSE,
00784 };
00785 
00786 int
00787 main(int argc, char **argv)
00788 {
00789     extern char *optarg;
00790     extern int optind, optopt;
00791     int opt;
00792     int tflag = 0, formatting_flags = 0, errflag = 0;
00793     char *sarg = NULL;
00794     int res = 0;
00795     int suffix = 0;
00796     struct ccn_decoder *d;
00797     struct ccn_dict *dtags = (struct ccn_dict *)&ccn_dtag_dict;
00798 
00799     while ((opt = getopt(argc, argv, ":hbd:s:tvx")) != -1) {
00800         switch (opt) {
00801             case 'h':
00802                 usage(argv[0]);
00803                 break;
00804             case 'b':
00805                 formatting_flags |= FORCE_BINARY;
00806                 break;
00807             case 'd':
00808                 if (0 != ccn_extend_dict(optarg, dtags, &dtags)) {
00809                     fprintf(stderr, "Unable to load dtag dictionary %s\n", optarg);
00810                     errflag = 1;
00811                 }
00812                 break;
00813             case 's':
00814                 sarg = optarg;
00815                 break;
00816             case 't':
00817                 tflag = 1;
00818                 break;
00819             case 'v':
00820                 formatting_flags |= VERBOSE_DECODE;
00821                 break;
00822             case 'x':
00823                 formatting_flags |= PREFER_HEX;
00824                 break;
00825             case '?':
00826                 fprintf(stderr, "Unrecognized option: -%c\n", optopt);
00827                 errflag = 1;
00828         }
00829     }
00830     if (tflag && (sarg != NULL || formatting_flags != 0))
00831         errflag = 1;
00832 
00833     if (errflag || (tflag && (optind < argc)))
00834         usage(argv[0]);
00835     
00836     if (tflag) {
00837         d = ccn_decoder_create(1, &ccn_dtag_dict);
00838         if (d == NULL) {
00839             fprintf(stderr, "Unable to allocate decoder\n");
00840             exit(1);
00841         }
00842         res |= process_data(d, test1, sizeof(test1));
00843         ccn_decoder_destroy(&d);
00844         return (res);
00845     }
00846     
00847     for (suffix = 0; optind < argc; optind++) {
00848         if (sarg) {
00849             fprintf(stderr, "<!-- Processing %s into %s -->\n", argv[optind], sarg);
00850             res |= process_split_file(sarg, argv[optind], formatting_flags,
00851                                       dtags, &suffix);
00852         }
00853         else {
00854             fprintf(stderr, "<!-- Processing %s -->\n", argv[optind]);
00855             res |= process_file(argv[optind], formatting_flags, dtags);
00856         }
00857     }
00858     return(res);
00859 }
00860 

Generated on Thu Feb 16 00:43:58 2012 for Content-Centric Networking in C by  doxygen 1.5.6