xml_attached_file.c
author ali@yendor.vm.bytemark.co.uk
Thu Nov 16 08:30:26 2006 +0000 (2006-11-16)
changeset 0 ae7b3fa753dc
permissions -rw-r--r--
First cut. Distintly raw around the edges:
* Assumes it will be running in /home/ali/wk/slashem/web.scripts
* Assumes cache directory will be in topdir
* No build system (simple compiling and linking against libxml2)
* No configure system (eg., tagsoup)
* Output XML untested
* Doesn't set bugzilla maintainer or exporter
* Handling of artifact priorities and resolution is suspect
ali@0
     1
/*
ali@0
     2
 * This program converts an attached file (which has previously been
ali@0
     3
 * downloaded from sourceforge) into bugzilla-style XML.
ali@0
     4
 */
ali@0
     5
ali@0
     6
#include <stdlib.h>
ali@0
     7
#include <stdio.h>
ali@0
     8
#include <string.h>
ali@0
     9
#ifdef __linux__
ali@0
    10
#include <getopt.h>
ali@0
    11
#endif
ali@0
    12
ali@0
    13
#ifdef __linux__
ali@0
    14
static struct option long_options[] = {
ali@0
    15
    {"type", 1, 0, 't'},
ali@0
    16
    {"id", 1, 0, 'i'},
ali@0
    17
    {"patch", 0, 0, 'p'},
ali@0
    18
    {0, 0, 0, 0}
ali@0
    19
};
ali@0
    20
ali@0
    21
static char *long_option_str(char opt)
ali@0
    22
{
ali@0
    23
    int i;
ali@0
    24
    static char buf[100];
ali@0
    25
    for(i=0;long_options[i].name;i++)
ali@0
    26
	if (long_options[i].val==opt)
ali@0
    27
	{
ali@0
    28
	    sprintf(buf,", --%s",long_options[i].name);
ali@0
    29
	    return buf;
ali@0
    30
	}
ali@0
    31
    return "";
ali@0
    32
}
ali@0
    33
#else
ali@0
    34
#define long_option_str(opt)    ""
ali@0
    35
#endif
ali@0
    36
ali@0
    37
usage()
ali@0
    38
{
ali@0
    39
    fprintf(stderr,"Usage: xml_attached_file [OPTION] file\n");
ali@0
    40
    fprintf(stderr,"\n");
ali@0
    41
    fprintf(stderr,"  -t%s=MIME-type	    MIME type to use\n",
ali@0
    42
      long_option_str('t'));
ali@0
    43
    fprintf(stderr,"  -i%s=ID	            Attachment ID to use\n",
ali@0
    44
      long_option_str('i'));
ali@0
    45
    fprintf(stderr,"  -p%s	            Mark attachment as a patch\n",
ali@0
    46
      long_option_str('p'));
ali@0
    47
    exit(1);
ali@0
    48
}
ali@0
    49
ali@0
    50
/* Note that we limit line lengths to 76 characters following RFC 2045
ali@0
    51
 * (bugzilla uses MIME::Base64). This isn't strictly compliant with RFC 4648.
ali@0
    52
 */
ali@0
    53
static void base64_encode(FILE *in,FILE *out)
ali@0
    54
{
ali@0
    55
    int ng=0;		/* 76 characters == 19 groups */
ali@0
    56
    size_t nb;
ali@0
    57
    unsigned char bytes[3];
ali@0
    58
    const char alphabet[64]=
ali@0
    59
      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
ali@0
    60
    while ((nb=fread(bytes,1,3,in))==3)
ali@0
    61
    {
ali@0
    62
	if (ng++>=19)
ali@0
    63
	{
ali@0
    64
	    putc('\n',out);
ali@0
    65
	    ng=1;
ali@0
    66
	}
ali@0
    67
	putc(alphabet[bytes[0]>>2],out);
ali@0
    68
	putc(alphabet[(bytes[0]<<4|bytes[1]>>4)&0x3F],out);
ali@0
    69
	putc(alphabet[(bytes[1]<<2|bytes[2]>>6)&0x3F],out);
ali@0
    70
	putc(alphabet[bytes[2]&0x3F],out);
ali@0
    71
    }
ali@0
    72
    if (nb)
ali@0
    73
    {
ali@0
    74
	if (ng>=19)
ali@0
    75
	    putc('\n',out);
ali@0
    76
	putc(alphabet[bytes[0]>>2],out);
ali@0
    77
	if (nb==2)
ali@0
    78
	{
ali@0
    79
	    putc(alphabet[(bytes[0]<<4|bytes[1]>>4)&0x3F],out);
ali@0
    80
	    putc(alphabet[bytes[1]<<2&0x3F],out);
ali@0
    81
	}
ali@0
    82
	else
ali@0
    83
	{
ali@0
    84
	    putc(alphabet[bytes[0]<<4&0x3F],out);
ali@0
    85
	    putc('=',out);
ali@0
    86
	}
ali@0
    87
	putc('=',out);
ali@0
    88
    }
ali@0
    89
}
ali@0
    90
ali@0
    91
int main(int argc,char **argv)
ali@0
    92
{
ali@0
    93
    int c;
ali@0
    94
    FILE *fp;
ali@0
    95
    unsigned long id=0;
ali@0
    96
    int ispatch=0;
ali@0
    97
    char *type=NULL;
ali@0
    98
    for(;;)
ali@0
    99
    {
ali@0
   100
#ifdef __linux__
ali@0
   101
	int option_index=0;
ali@0
   102
	c=getopt_long(argc,argv,"t:i:p",long_options,&option_index);
ali@0
   103
#else
ali@0
   104
	c=getopt(argc,argv,"t:i:p");
ali@0
   105
#endif
ali@0
   106
	if (c<0)
ali@0
   107
	    break;
ali@0
   108
	switch(c)
ali@0
   109
	{
ali@0
   110
	    case 't':
ali@0
   111
		type=optarg;
ali@0
   112
		break;
ali@0
   113
	    case 'i':
ali@0
   114
		id=strtoul(optarg,NULL,10);
ali@0
   115
		break;
ali@0
   116
	    case 'p':
ali@0
   117
		ispatch=1;
ali@0
   118
		break;
ali@0
   119
	    default:
ali@0
   120
		usage();
ali@0
   121
	}
ali@0
   122
    }
ali@0
   123
    if (optind<argc)
ali@0
   124
    {
ali@0
   125
	fp=fopen(argv[optind],"rb");
ali@0
   126
	if (!fp)
ali@0
   127
	{
ali@0
   128
	    perror(argv[optind]);
ali@0
   129
	    exit(1);
ali@0
   130
	}
ali@0
   131
    }
ali@0
   132
    else
ali@0
   133
	fp=stdin;
ali@0
   134
    printf("<attachment ispatch=\"%d\">\n",ispatch);
ali@0
   135
    if (id)
ali@0
   136
	printf("  <attachid>%lu</attachid>\n",id);
ali@0
   137
    if (type)
ali@0
   138
	printf("  <type>%s</type>\n",type);
ali@0
   139
    printf("  <data encoding=\"base64\">\n");
ali@0
   140
    base64_encode(fp,stdout);
ali@0
   141
    printf("\n  </data>\n");
ali@0
   142
    printf("</attachment>\n");
ali@0
   143
    exit(0);
ali@0
   144
}