Logo Search packages:      
Sourcecode: afflib version File versions  Download package

afxml.cpp

/*
 * afxml.cpp:
 *
 * print AFF information as an XML
 */

/*
 * Copyright (c) 2005
 *    Simson L. Garfinkel and Basis Technology, Inc. 
 *      All rights reserved.
 *
 * This code is derrived from software contributed by
 * Simson L. Garfinkel
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    This product includes software developed by Simson L. Garfinkel
 *    and Basis Technology Corp.
 * 4. Neither the name of Simson Garfinkel, Basis Technology, or other
 *    contributors to this program may be used to endorse or promote
 *    products derived from this software without specific prior written
 *    permission.
 *
 * THIS SOFTWARE IS PROVIDED BY SIMSON GARFINKEL, BASIS TECHNOLOGY,
 * AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL SIMSON GARFINKEL, BAIS TECHNOLOGy,
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.  
 */


#include "afflib.h"
#include "afflib_i.h"
#include "base64.h"
#include "quads.h"

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <err.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <limits.h>
#include <string.h>
#include <zlib.h>
#include <openssl/md5.h>
#include <openssl/sha.h>
#include <assert.h>
#include <curses.h>
#include <term.h>

char *progname = "afxml";

int opt_x = 0;
char **opt_j = 0;
int opt_j_count = 0;

#define xstr(s) str(s)
#define str(s) #s


void usage()
{
    printf("%s version %s\n",progname,xstr(AFFLIB_VERSION));
    printf("usage: %s [options] infile... \n",progname);
    printf("   -v         =   Just print the version number and exit\n");
    printf("   -x         =   Don't include infile in output.\n");
    printf("   -j segname =   Just print segname for the file.\n");
    printf("                  (may be repeated)\n");
    exit(0);
}



/* Return true if segname is in the optj list */
bool in_opt_j_list(char *segname)
{
    for(int i=0;i<opt_j_count;i++){
      if(strcmp(segname,opt_j[i])==0) return true;
    }
    return false;
}

int xml_info(const char *infile)
{
    AFFILE *af = af_open(infile,O_RDONLY,0);
    if(!af){
      warn(infile);
      return -1;
    }

    printf("<!-- XML generated by afxml version %s -->\n",xstr(AFFLIB_VERSION));
    printf("<affinfo");
    if(!opt_x) printf(" name='%s'",infile);
    printf(">\n");


    af_rewind_seg(af);              // start at the beginning

    char segname[AF_MAX_NAME_LEN];
    char segname2[AF_MAX_NAME_LEN];
    size_t datalen = 0;
    unsigned long arg;
    int pages = 0;
    
    while(af_get_next_seg(af,segname,sizeof(segname),&arg,0,&datalen)==0){
      if(segname[0]==0) continue;   // segment to ignore
      if(strcmp(segname,AF_DIRECTORY)==0) continue; // don't output the directories

      /* See if it is a data segment */
      int64 page_num = af_segname_page_number(segname);
      if(page_num>=0){
          pages += 1;
          continue;
      }

      /* check optj */
      if(opt_j_count > 0 && in_opt_j_list(segname)==false){
          continue;
      }

      /* Backspace, get the data and print it */
      /* Special case for 64-bit values */
      af_backspace(af);
      unsigned char *data= (unsigned char *)malloc(datalen);
      if(af_get_next_seg(af,segname2,sizeof(segname2),&arg,data,&datalen)!=0){
          warn("af_get_next_seg #2 failed");
          break;
      }

      /* Change '/' to '_' in segname if present */
      for(char *cc=segname;*cc;cc++){
          if(*cc=='/') *cc = '_';
      }

      if(datalen==8 && (arg & AF_SEG_QUADWORD || display_as_quad(segname))){
          /* Print it as a 64-bit value.
           * The strcmp is there because early AF_IMAGESIZE segs didn't set
           * AF_SEG_QUADWORD...
           */
          printf("    <%s>%qd</%s>\n",segname,af_decode_q(data),segname);
          free(data);
          continue;
      }

      /* If arg is present and datasize datalen==0,
       * just print the arg as an unsigned number
       */
      if(datalen==0){
          printf("    <%s>%ld</%s>\n",segname,arg,segname);
          free(data);
          continue;
      }

      /* Just handle it as binhex ... */
      printf("    <%s",segname);
      if(datalen==0){
          printf(" arg='%lu' />\n",arg);
      }
      else{
          int  b64size = datalen*2+2;
          char *b64buf = (char *)malloc(b64size);

          int  b64size_real = b64_ntop(data,datalen,b64buf,b64size);
          b64buf[b64size_real] = 000; // null-terminate

          printf(" coding='base64'>");
          fputs(b64buf,stdout);
          printf("</%s>\n",segname);
          free(b64buf);
      }
      free(data);
    }
    af_close(af);
    printf("    <pages>%d</pages>\n",pages); // tell how many pages we have

    printf("</affinfo>\n");
    return 0;
}
       

int main(int argc,char **argv)
{
    int bflag, ch;
    const char *infile;

    /* Figure out how many cols the screen has... */

    bflag = 0;
    while ((ch = getopt(argc, argv, "xj:h?v")) != -1) {
      switch (ch) {
      case 'j':
          if(opt_j==0) opt_j = (char **)malloc(0);
          opt_j_count++;
          opt_j = (char **)realloc(opt_j,sizeof(char *)*opt_j_count);
          opt_j[opt_j_count-1] = strdup(optarg); // make a copy
      case 'x':
          opt_x++;
          break;
      case 'h':
      case '?':
      default:
          usage();
          break;
      case 'v':
          printf("%s version %s\n",progname,xstr(AFFLIB_VERSION));
          exit(0);
      }
    }
    argc -= optind;
    argv += optind;

    if(argc<1){
      usage();
    }


    /* Loop through all of the files */
    printf("<?xml version='1.0' encoding='UTF-8'?>\n");
    printf("<affobjects>\n");
    while(*argv){
      infile = *argv++;       // get the file
      argc--;                       // decrement argument counter
       
      xml_info(infile);
    }
    printf("</affobjects>\n");
    return 0;
}



Generated by  Doxygen 1.6.0   Back to index