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     }
00113     d->schema = CCN_NO_SCHEMA;
00114     d->tagdict = dtags->dict;
00115     d->tagdict_count = dtags->count;
00116     d->formatting_flags = formatting_flags;
00117     d->annotation = NULL;
00118     return(d);
00119 }
00120 
00121 void
00122 ccn_decoder_set_callback(struct ccn_decoder *d, ccn_decoder_callback c, void *data)
00123 {
00124     d->callback = c;
00125     if (c == NULL) {
00126         d->callbackdata = NULL;
00127     } else {
00128         d->callbackdata = data;
00129         c(d, CALLBACK_INITIAL, data);
00130     }
00131 }
00132 
00133 struct ccn_decoder_stack_item *
00134 ccn_decoder_push(struct ccn_decoder *d)
00135 {
00136     struct ccn_decoder_stack_item *s;
00137     s = calloc(1, sizeof(*s));
00138     if (s != NULL) {
00139         s->link = d->stack;
00140         s->savedss = d->stringstack->length;
00141         s->saved_schema = d->schema;
00142         s->saved_schema_state = d->sstate;
00143         d->stack = s;
00144     }
00145     return(s);
00146 }
00147 
00148 void
00149 ccn_decoder_pop(struct ccn_decoder *d)
00150 {
00151     struct ccn_decoder_stack_item *s = d->stack;
00152     if (s != NULL) {
00153         d->stack = s->link;
00154         d->stringstack->length = s->savedss;
00155         d->schema = s->saved_schema;
00156         d->sstate = s->saved_schema_state;
00157         free(s);
00158     }
00159 }
00160 
00161 void
00162 ccn_decoder_destroy(struct ccn_decoder **dp)
00163 {
00164     struct ccn_decoder *d = *dp;
00165     if (d != NULL) {
00166         if (d->callback != NULL) {
00167             d->callback(d, CALLBACK_FINAL, d->callbackdata);
00168         }
00169         while (d->stack != NULL) {
00170             ccn_decoder_pop(d);
00171         }
00172         ccn_charbuf_destroy(&(d->stringstack));
00173         free(d);
00174         *dp = NULL;
00175     }
00176 }
00177 
00178 static const char *
00179 dict_name_from_number(int ndx, const struct ccn_dict_entry *dict, int n)
00180 {
00181     int i;
00182     for (i = 0; i < n; i++)
00183         if (ndx == dict[i].index)
00184             return (dict[i].name);
00185     return (NULL);
00186 }
00187 
00188 static const char Base64[] =
00189   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00190 
00191 static int
00192 is_text_encodable(unsigned char p[], size_t start, size_t length)
00193 {
00194     size_t i;
00195 
00196     if (length == 0) return (0);
00197     for (i = 0; i < length; i++) {
00198         char c = p[start + i];
00199         if (c < ' ' || c > '~') return (0);
00200         if (c == '<' || c == '>' || c == '&') return (0);
00201     }
00202     return (1);
00203 }
00204 
00205 /* c.f. ccn_uri_append_percentescaped */
00206 static void
00207 print_percent_escaped(const unsigned char *data, size_t size)
00208 {
00209     size_t i;
00210     unsigned char ch;
00211     for (i = 0; i < size && data[i] == '.'; i++)
00212         continue;
00213     /* For a component that consists solely of zero or more dots, add 3 more */
00214     if (i == size)
00215         printf("...");
00216     for (i = 0; i < size; i++) {
00217         ch = data[i];
00218         /*
00219          * Leave unescaped only the generic URI unreserved characters.
00220          * See RFC 3986. Here we assume the compiler uses ASCII.
00221          */
00222         if (('a' <= ch && ch <= 'z') ||
00223             ('A' <= ch && ch <= 'Z') ||
00224             ('0' <= ch && ch <= '9') ||
00225             ch == '-' || ch == '.' || ch == '_' || ch == '~')
00226             printf("%c", ch);
00227         else
00228             printf("%%%02X", (unsigned)ch);
00229     }
00230 }
00231 
00232 size_t
00233 ccn_decoder_decode(struct ccn_decoder *d, unsigned char p[], size_t n)
00234 {
00235     int state = d->state;
00236     int tagstate = 0;
00237     size_t numval = d->numval;
00238     size_t i = 0;
00239     unsigned char c;
00240     size_t chunk;
00241     struct ccn_decoder_stack_item *s;
00242     const char *tagname;
00243     while (i < n) {
00244         switch (state) {
00245             case 0: /* start new thing */
00246                 if (tagstate > 1 && tagstate-- == 2) {
00247                     printf("\""); /* close off the attribute value */
00248                     ccn_decoder_pop(d);
00249                 } 
00250                 if (p[i] == CCN_CLOSE) {
00251                     i++;
00252                     s = d->stack;
00253                     if (s == NULL || tagstate > 1) {
00254                         state = -__LINE__;
00255                         break;
00256                     }
00257                     if (tagstate == 1) {
00258                         tagstate = 0;
00259                         printf("/>");
00260                     }
00261                     else if (d->schema == -1-CCN_PROCESSING_INSTRUCTIONS) {
00262                         printf("?>");
00263                         if (d->sstate != 2) {
00264                             state = -__LINE__;
00265                             break;
00266                         }
00267                     }
00268                     else {
00269                         printf("</%s>", d->stringstack->buf + s->nameindex);
00270                     }
00271                     if (d->annotation != NULL) {
00272                         if (d->annotation->length > 0) {
00273                             printf("<!--       ");
00274                             print_percent_escaped(d->annotation->buf, d->annotation->length);
00275                             printf(" -->");
00276                         }
00277                         ccn_charbuf_destroy(&d->annotation);
00278                     }
00279                     ccn_decoder_pop(d);
00280                     if (d->stack == NULL) {
00281                         if (d->callback != NULL)
00282                             d->callback(d, CALLBACK_OBJECTEND, d->callbackdata);
00283                         else
00284                             printf("\n");
00285                     }
00286                     break;
00287                 }
00288                 numval = 0;
00289                 state = 1;
00290                 /* FALLTHRU */
00291             case 1: /* parsing numval */
00292                 c = p[i++];
00293                 if ((c & CCN_TT_HBIT) == CCN_CLOSE) {
00294                     if (numval > (numval << 7)) {
00295                         state = 9;
00296                         d->bignumval = numval;
00297                         i--;
00298                         continue;
00299                     }
00300                     numval = (numval << 7) + (c & 127);
00301                     if (numval > (numval << (7-CCN_TT_BITS))) {
00302                         state = 9;
00303                         d->bignumval = numval;
00304                     }
00305                 }
00306                 else {
00307                     numval = (numval << (7-CCN_TT_BITS)) +
00308                              ((c >> CCN_TT_BITS) & CCN_MAX_TINY);
00309                     c &= CCN_TT_MASK;
00310                     switch (c) {
00311                         case CCN_EXT:
00312                             if (tagstate == 1) {
00313                                 tagstate = 0;
00314                                 printf(">");
00315                             }
00316                             s = ccn_decoder_push(d);
00317                             s->nameindex = d->stringstack->length;
00318                             d->schema = -1-numval;
00319                             d->sstate = 0;
00320                             switch (numval) {
00321                                 case CCN_PROCESSING_INSTRUCTIONS:
00322                                     printf("<?");
00323                                     break;
00324                                 default:
00325                                     state = -__LINE__;
00326                             }
00327                             state = 0;
00328                             break;
00329                         case CCN_DTAG:
00330                             if (tagstate == 1) {
00331                                 tagstate = 0;
00332                                 printf(">");
00333                             }
00334                             s = ccn_decoder_push(d);
00335                             s->nameindex = d->stringstack->length;
00336                             d->schema = numval;
00337                             d->sstate = 0;
00338                             tagname = NULL;
00339                             if (numval <= INT_MAX)
00340                                 tagname = dict_name_from_number(numval, d->tagdict, d->tagdict_count);
00341                             if (tagname == NULL) {
00342                                 fprintf(stderr,
00343                                         "*** Warning: unrecognized DTAG %lu\n",
00344                                         (unsigned long)numval);
00345                                 ccn_charbuf_append(d->stringstack,
00346                                                    "UNKNOWN_DTAG",
00347                                                    sizeof("UNKNOWN_DTAG"));
00348                                 printf("<%s code=\"%lu\"",
00349                                        d->stringstack->buf + s->nameindex,
00350                                        (unsigned long)d->schema);
00351                                 d->schema = CCN_UNKNOWN_SCHEMA;
00352                             }
00353                             else {
00354                                 ccn_charbuf_append(d->stringstack, tagname, strlen(tagname)+1);
00355                                 printf("<%s", tagname);
00356                             }
00357                             if ((d->formatting_flags & VERBOSE_DECODE) != 0) {
00358                                 if (d->annotation != NULL)
00359                                     abort();
00360                                 if (numval == 15 /* Component */)
00361                                     d->annotation = ccn_charbuf_create();
00362                             }
00363                             tagstate = 1;
00364                             state = 0;
00365                             break;
00366                         case CCN_BLOB:
00367                             if (numval > n - i) {
00368                                 state = -__LINE__;
00369                                 break;
00370                             }                                                        
00371                             if (tagstate == 1) {
00372                                 tagstate = 0;
00373                                 if ((d->formatting_flags & FORCE_BINARY) == 0 && is_text_encodable(p, i, numval)) {
00374                                     printf(" ccnbencoding=\"text\">");
00375                                     state =  6;
00376                                 }
00377                                 else if ((d->formatting_flags & PREFER_HEX) != 0) {
00378                                     printf(" ccnbencoding=\"hexBinary\">");
00379                                     state = 2;
00380                                 }
00381                                 else {
00382                                     printf(" ccnbencoding=\"base64Binary\">");
00383                                     state = 10;
00384                                 }
00385                             }
00386                             else {
00387                                 fprintf(stderr, "blob not tagged in xml output\n");
00388                                 state = 10;
00389                             }
00390                             state = (numval == 0) ? 0 : state;
00391                             d->base64_char_count = 0;
00392                             break;
00393                         case CCN_UDATA:
00394                             if (tagstate == 1) {
00395                                 tagstate = 0;
00396                                 printf(">");
00397                             }
00398                             state = 3;
00399                             if (d->schema == -1-CCN_PROCESSING_INSTRUCTIONS) {
00400                                 if (d->sstate > 0) {
00401                                     printf(" ");
00402                                 }
00403                                 state = 6;
00404                                 d->sstate += 1;
00405                             }
00406                             if (numval == 0)
00407                                 state = 0;
00408                             break;
00409                         case CCN_DATTR:
00410                             if (tagstate != 1) {
00411                                 state = -__LINE__;
00412                                 break;
00413                             }
00414                             s = ccn_decoder_push(d);
00415                             ccn_charbuf_reserve(d->stringstack, 1);
00416                             s->nameindex = d->stringstack->length;
00417                             printf(" UNKNOWN_DATTR_%lu=\"", (unsigned long)numval);
00418                             tagstate = 3;
00419                             state = 0;
00420                             break;
00421                         case CCN_ATTR:
00422                             if (tagstate != 1) {
00423                                 state = -__LINE__;
00424                                 break;
00425                             }
00426                             if (numval >= n - i) {
00427                                 state = -__LINE__;
00428                                 break;
00429                             }                            
00430                             numval += 1; /* encoded as length-1 */
00431                             s = ccn_decoder_push(d);
00432                             ccn_charbuf_reserve(d->stringstack, numval + 1);
00433                             s->nameindex = d->stringstack->length;
00434                             state = 5;
00435                             break;
00436                         case CCN_TAG:
00437                             if (tagstate == 1) {
00438                                 tagstate = 0;
00439                                 printf(">");
00440                             }
00441                             if (numval >= n - i) {
00442                                 state = -__LINE__;
00443                                 break;
00444                             }                                                        
00445                             numval += 1; /* encoded as length-1 */
00446                             s = ccn_decoder_push(d);
00447                             ccn_charbuf_reserve(d->stringstack, numval + 1);
00448                             s->nameindex = d->stringstack->length;
00449                             state = 4;
00450                             break;
00451                         default:
00452                             state = -__LINE__;
00453                     }
00454                 }
00455                 break;
00456             case 2: /* hex BLOB */
00457                 c = p[i++];
00458                 if (d->annotation != NULL)
00459                     ccn_charbuf_append_value(d->annotation, c, 1);
00460                 printf("%02X", c);
00461                 if (--numval == 0) {
00462                     state = 0;
00463                 }
00464                 break;
00465             case 3: /* utf-8 data */
00466                 c = p[i++];
00467                 if (--numval == 0) {
00468                     state = 0;
00469                 }
00470                 switch (c) {
00471                     case 0:
00472                         state = -__LINE__;
00473                         break;
00474                     case '&':
00475                         printf("&amp;");
00476                         break;
00477                     case '<':
00478                         printf("&lt;");
00479                         break;
00480                     case '>':
00481                         printf("&gt;");
00482                         break;
00483                     case '"':
00484                         printf("&quot;");
00485                         break;
00486                     default:
00487                         printf("%c", c);
00488                 }
00489                 break;
00490             case 4: /* parsing tag name */
00491             case 5: /* parsing attribute name */
00492                 chunk = n - i;
00493                 if (chunk > numval) {
00494                     chunk = numval;
00495                 }
00496                 if (chunk == 0) {
00497                     state = -__LINE__;
00498                     break;
00499                 }
00500                 ccn_charbuf_append(d->stringstack, p + i, chunk);
00501                 numval -= chunk;
00502                 i += chunk;
00503                 if (numval == 0) {
00504                     ccn_charbuf_append(d->stringstack, (const unsigned char *)"\0", 1);
00505                     s = d->stack;
00506                     if (s == NULL ||
00507                         strlen((char*)d->stringstack->buf + s->nameindex) != 
00508                             d->stringstack->length -1 - s->nameindex) {
00509                         state = -__LINE__;
00510                         break;
00511                     }
00512                     if (state == 4) {
00513                         printf("<%s", d->stringstack->buf + s->nameindex);
00514                         tagstate = 1;
00515                     }
00516                     else {
00517                         printf(" %s=\"", d->stringstack->buf + s->nameindex);
00518                         tagstate = 3;
00519                     }
00520                     state = 0;
00521                 }
00522                 break;
00523             case 6: /* processing instructions and text blobs */
00524                 c = p[i++];
00525                 if (--numval == 0) {
00526                     state = 0;
00527                 }
00528                 printf("%c", c);
00529                 break;
00530             case 9: /* parsing big numval - cannot be a length anymore */
00531                 c = p[i++];
00532                 if ((c & CCN_TT_HBIT) == CCN_CLOSE) {
00533                     d->bignumval = (d->bignumval << 7) + (c & 127);
00534                 }
00535                 else {
00536                     d->bignumval = (d->bignumval << (7-CCN_TT_BITS)) +
00537                                    ((c >> CCN_TT_BITS) & CCN_MAX_TINY);
00538                     c &= CCN_TT_MASK;
00539                     if (tagstate == 1) {
00540                         tagstate = 0;
00541                         printf(">");
00542                     }
00543                     /*
00544                      * There's nothing that we actually need the bignumval
00545                      * for, so we can probably GC this whole state and
00546                      * give up earlier.
00547                      */
00548                     switch (c) {
00549                         default:
00550                             state = -__LINE__;
00551                     }
00552                 }
00553                 break;
00554             case 10: /* base 64 BLOB - phase 0 */
00555                 c = p[i++];
00556                 if (d->annotation != NULL)
00557                     ccn_charbuf_append_value(d->annotation, c, 1);
00558                 printf("%c", Base64[c >> 2]);
00559                 d->base64_char_count++;
00560                 if (--numval == 0) {
00561                     printf("%c==", Base64[(c & 3) << 4]);
00562                     state = 0;
00563                     d->base64_char_count += 3;
00564                 }
00565                 else {
00566                     d->bits = (c & 3);
00567                     state = 11;
00568                 }
00569                 if ((d->formatting_flags & FORCE_BINARY) == 0 && d->base64_char_count >= 64) {
00570                     d->base64_char_count = 0;
00571                     printf("\n");
00572                 }
00573                 break;
00574             case 11: /* base 64 BLOB - phase 1 */
00575                 c = p[i++];
00576                 if (d->annotation != NULL)
00577                     ccn_charbuf_append_value(d->annotation, c, 1);
00578                 printf("%c", Base64[((d->bits & 3) << 4) + (c >> 4)]);
00579                 d->base64_char_count++;
00580                 if (--numval == 0) {
00581                     printf("%c=", Base64[(c & 0xF) << 2]);
00582                     state = 0;
00583                     d->base64_char_count += 2;
00584                 }
00585                 else {
00586                     d->bits = (c & 0xF);
00587                     state = 12;
00588                 }
00589                 if ((d->formatting_flags & FORCE_BINARY) == 0 && d->base64_char_count >= 64) {
00590                     d->base64_char_count = 0;
00591                     printf("\n");
00592                 }
00593                 break;
00594             case 12: /* base 64 BLOB - phase 2 */
00595                 c = p[i++];
00596                 if (d->annotation != NULL)
00597                     ccn_charbuf_append_value(d->annotation, c, 1);
00598                 printf("%c%c", Base64[((d->bits & 0xF) << 2) + (c >> 6)],
00599                                Base64[c & 0x3F]);
00600                 d->base64_char_count += 2;
00601                 if (--numval == 0) {
00602                     state = 0;
00603                 }
00604                 else {
00605                     state = 10;
00606                 }
00607                 if ((d->formatting_flags & FORCE_BINARY) == 0 && d->base64_char_count >= 64) {
00608                     d->base64_char_count = 0;
00609                     printf("\n");
00610                 }
00611                 break;
00612             default:
00613                 n = i;
00614         }
00615     }
00616     d->state = state;
00617     d->tagstate = tagstate;
00618     d->numval = numval;
00619     return(i);
00620 }
00621 
00622 static int
00623 process_data(struct ccn_decoder *d, unsigned char *data, size_t n)
00624 {
00625     int res = 0;
00626     size_t s;
00627     printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
00628     s = ccn_decoder_decode(d, data, n);
00629     if (d->state != 0 || s < n || d->stack != NULL || d->tagstate != 0) {
00630         res = 1;
00631         fprintf(stderr, "error state %d after %d of %d chars\n",
00632             (int)d->state, (int)s, (int)n);
00633     }
00634     return(res);
00635 }
00636 
00637 static int
00638 process_fd(struct ccn_decoder *d, int fd)
00639 {
00640     struct ccn_charbuf *c = ccn_charbuf_create();
00641     ssize_t len;
00642     int res = 0;
00643     for (;;) {
00644         unsigned char *p = ccn_charbuf_reserve(c, 80);
00645         if (p == NULL) {
00646             perror("ccn_charbuf_reserve");
00647             res = 1;
00648             break;
00649         }
00650         len = read(fd, p, c->limit - c->length);
00651         if (len <= 0) {
00652             if (len == -1) {
00653                 perror("read");
00654                 res = 1;
00655             }
00656             break;
00657         }
00658         c->length += len;
00659     }
00660     fprintf(stderr, " <!-- input is %6lu bytes -->\n", (unsigned long)c->length);
00661     res |= process_data(d, c->buf, c->length);
00662     ccn_charbuf_destroy(&c);
00663     return(res);
00664 }
00665 
00666 
00667 static int
00668 process_file(char *path, int formatting_flags, const struct ccn_dict *dtags)
00669 {
00670     int fd = 0;
00671     int res = 0;
00672     struct ccn_decoder *d;
00673 
00674     if (0 != strcmp(path, "-")) {
00675         fd = open(path, O_RDONLY);
00676         if (-1 == fd) {
00677             perror(path);
00678             return(1);
00679         }
00680     }
00681 
00682     d = ccn_decoder_create(formatting_flags, dtags);
00683     res = process_fd(d, fd);
00684     ccn_decoder_destroy(&d);
00685 
00686     if (fd > 0)
00687         close(fd);
00688     return(res);
00689 }
00690 
00691 struct callback_state {
00692     int fragment;
00693     char *fileprefix;
00694 };
00695 
00696 static void
00697 set_stdout(struct ccn_decoder *d, enum callback_kind kind, void *data)
00698 {
00699     struct callback_state *cs = (struct callback_state *)data;
00700     char filename[256];
00701     FILE *fp;
00702     switch (kind) {
00703     case CALLBACK_INITIAL:
00704     case CALLBACK_OBJECTEND:
00705         snprintf(filename, sizeof(filename), "%s%05d.xml", cs->fileprefix, cs->fragment++);
00706         fprintf(stderr, " <!-- attaching stdout to %s --!>\n", filename);
00707         fp = freopen(filename, "w+", stdout);
00708         if (fp == NULL)
00709             perror(filename);
00710         break;
00711     case CALLBACK_FINAL:
00712         fflush(stdout);
00713         fclose(stdout);
00714         free(cs);
00715         break;
00716     }
00717 }
00718 
00719 static int
00720 process_split_file(char *base, char *path, int formatting_flags,
00721                    const struct ccn_dict *dtags, int *suffix)
00722 {
00723     int fd = 0;
00724     int res = 0;
00725     struct ccn_decoder *d;
00726     struct callback_state *cs;
00727 
00728     if (0 != strcmp(path, "-")) {
00729         fd = open(path, O_RDONLY);
00730         if (-1 == fd) {
00731             perror(path);
00732             return(1);
00733         }
00734     }
00735     
00736     cs = calloc(1, sizeof(*cs));
00737     cs->fileprefix = base;
00738     cs->fragment = *suffix;
00739     d = ccn_decoder_create(formatting_flags, dtags);
00740     ccn_decoder_set_callback(d, set_stdout, cs);
00741     res = process_fd(d, fd);
00742     *suffix = cs->fragment;
00743     ccn_decoder_destroy(&d);
00744     if (fd > 0)
00745         close(fd);
00746     return(res);
00747 }
00748 
00749 #define L (CCN_TT_HBIT & ~CCN_CLOSE)
00750 unsigned char test1[] = {
00751     (2 << CCN_TT_BITS) + CCN_TAG + L, 'F', 'o', 'o',
00752     (0 << CCN_TT_BITS) + CCN_TAG + L, 'a',
00753     (1 << CCN_TT_BITS) + CCN_UDATA + L, 'X',
00754                CCN_CLOSE,
00755     (0 << CCN_TT_BITS) + CCN_TAG + L, 'b',
00756     (3 << CCN_TT_BITS) + CCN_ATTR + L, 't', 'y', 'p', 'e',
00757     (5 << CCN_TT_BITS) + CCN_UDATA + L, 'e', 'm', 'p', 't', 'y',
00758                CCN_CLOSE,
00759     (2 << CCN_TT_BITS) + CCN_TAG + L, 'b', 'i', 'n',
00760     (4 << CCN_TT_BITS) + CCN_BLOB + L, 1, 0x23, 0x45, 0x67,
00761                CCN_CLOSE,
00762     (CCN_CLOSE + ((20-1) >> (7-CCN_TT_BITS))),
00763     (((20-1) & CCN_TT_MASK) << CCN_TT_BITS) + CCN_TAG + L,
00764         'a', 'b', 'c', 'd',  'a', 'b', 'c', 'd', 
00765         'a', 'b', 'c', 'd',  'a', 'b', 'c', 'd',
00766         'a', 'b', 'c', 'd',
00767                CCN_CLOSE,
00768     (2 << CCN_TT_BITS) + CCN_TAG + L, 'i', 'n', 't',
00769     (3 << CCN_TT_BITS) + CCN_ATTR + L, 't', 'y', 'p', 'e',
00770     (3 << CCN_TT_BITS) + CCN_UDATA + L, 'B', 'I', 'G',
00771                CCN_CLOSE,
00772     (6 << CCN_TT_BITS) + CCN_UDATA + L,
00773     'H','i','&','b','y','e',
00774                CCN_CLOSE,
00775 };
00776 
00777 int
00778 main(int argc, char **argv)
00779 {
00780     extern char *optarg;
00781     extern int optind, optopt;
00782     int opt;
00783     int tflag = 0, formatting_flags = 0, errflag = 0;
00784     char *sarg = NULL;
00785     int res = 0;
00786     int suffix = 0;
00787     struct ccn_decoder *d;
00788     struct ccn_dict *dtags = (struct ccn_dict *)&ccn_dtag_dict;
00789 
00790     while ((opt = getopt(argc, argv, ":hbd:s:tvx")) != -1) {
00791         switch (opt) {
00792             case 'h':
00793                 usage(argv[0]);
00794                 break;
00795             case 'b':
00796                 formatting_flags |= FORCE_BINARY;
00797                 break;
00798             case 'd':
00799                 if (0 != ccn_extend_dict(optarg, dtags, &dtags)) {
00800                     fprintf(stderr, "Unable to load dtag dictionary %s\n", optarg);
00801                     errflag = 1;
00802                 }
00803                 break;
00804             case 's':
00805                 sarg = optarg;
00806                 break;
00807             case 't':
00808                 tflag = 1;
00809                 break;
00810             case 'v':
00811                 formatting_flags |= VERBOSE_DECODE;
00812                 break;
00813             case 'x':
00814                 formatting_flags |= PREFER_HEX;
00815                 break;
00816             case '?':
00817                 fprintf(stderr, "Unrecognized option: -%c\n", optopt);
00818                 errflag = 1;
00819         }
00820     }
00821     if (tflag && (sarg != NULL || formatting_flags != 0))
00822         errflag = 1;
00823 
00824     if (errflag || (tflag && (optind < argc)))
00825         usage(argv[0]);
00826     
00827     if (tflag) {
00828             d = ccn_decoder_create(1, &ccn_dtag_dict);
00829             res |= process_data(d, test1, sizeof(test1));
00830             ccn_decoder_destroy(&d);
00831             return (res);
00832     }
00833 
00834     for (suffix = 0; optind < argc; optind++) {
00835         if (sarg) {
00836             fprintf(stderr, "<!-- Processing %s into %s -->\n", argv[optind], sarg);
00837             res |= process_split_file(sarg, argv[optind], formatting_flags,
00838                                       dtags, &suffix);
00839         }
00840         else {
00841             fprintf(stderr, "<!-- Processing %s -->\n", argv[optind]);
00842             res |= process_file(argv[optind], formatting_flags, dtags);
00843         }
00844     }
00845     return(res);
00846 }
00847 
Generated on Fri May 13 16:27:01 2011 for Content-Centric Networking in C by  doxygen 1.6.3