
/* Generated by Interface Builder */

#import "IConvertMIME.h"
#import <sys/file.h>
#import <streams/streams.h>
#import "IMMEditor.h"
#import "IBinaryD.h"
#import "ITextD.h"
#import "IArticleD.h"
#import "IOrderedListD.h"
#import "IMediaTable.h"
#import "IExternalD.h"
#import "mem_file_desc.h"
#import "data_types.h"
#import "errdebug.h"


int RTFparse(); 

char *Cleanse();

void concatstream();
char fontheader[2000];
NXStream *plain2rtf(), *ez2rtf(), *richtext2rtf(), *CreatertfHead();

@implementation IConvertMIME

- convertToMIME:(IArticleD *)article stream:(NXStream *)MimeArticleStream1
{
    ITextD *bodyITextD;
    BOOL isMultimedia;
    InfoD *header;
    NXStream *MimeArticleStream;
    NXHashState state;
    const char *key, *value;
    struct mem_file_desc *file_desc_head = NULL;
    struct mem_file_desc **fdpp = &file_desc_head;
    struct mem_file_desc *fdp, *prevfdp;
    id object;
    int countObj;
    int len,max,size;
    char *buff;
//    char *extension=NULL;
    int n, ctr=0, plainonly=0;
    char *contenttype=NULL;
    char *bound=NULL;
    extern int Ismultip; 

    countObj = [article objectCount];
    countObj = countObj+2 ;

    if ((bodyITextD = [article objectWithKey:INDEX_RTF]) != nil) {
        isMultimedia = YES;
    } else if ((bodyITextD = [article objectWithKey:PLAINTEXT]) != nil) {
        isMultimedia = NO;
    }
//    if (strcmp(NXGetDefaultValue(OWNER,KANJICODE),"JIS")==0) {
//         [bodyITextD kanjiCodeConvert:"euc_to_jis"];
//    }

    if ((header = [article dataForKey:HEADER_INFO]) == nil) {
// There is no header.tbl

    } else {
// There is a header.tbl, namely normal.
	if ([header infoForKey:"Mime-Version"] == nil ){
	    [header insertKey:"Mime-Version" value:"1.0"];
	}
        if ( countObj > 2 && (isMultimedia == YES)){
            bound = (char *) calloc (200, sizeof(char));
	    sprintf(bound,"ISR.multimedia.%d.%d.%d",
              getuid(), getpid(), ctr);
            contenttype = (char *) calloc (200, sizeof(char));
	    sprintf(contenttype, "multipart/mixed ; boundary=""%s""", bound); 
	    Ismultip=1;
	    ctr++;
            [header insertKey:"Content-Type" value:contenttype];
	} else if ( countObj == 2 && (isMultimedia == YES)){
            bound = (char *) calloc (200, sizeof(char));
	    sprintf(bound,"ISR.multimedia.%d.%d.%d",
              getuid(), getpid(), ctr);
	    [header insertKey:"Content-Type" value:"text/richtext"];
	}else {
            [header insertKey:"Content-Type" value:"text/plain"];
	}
		
    }

      for (n = 0; countObj >= n+1 ; ++n) {
//      for (n = 0; (object = [article objectAt:n]) != nil; ++n) {
//        if (!strcmp(key = [object key], HEADER_INFO)) {
//            continue;
//        }
	object = [article objectAt:n];
	if ( object ){
        	 if ((*fdpp = (struct mem_file_desc *)
         	      malloc(sizeof(struct mem_file_desc))) == NULL) {
           	      [NXApp terminate:self];
       		 }
        	(void)strncpy((*fdpp)->fd_name, [object key], NAMSIZ);
//		extension = rindex((*fdpp)->fd_name,'.');
//       		 if (extension) {
//          	   ++extension;
//           	  extension = Cleanse(extension);
//         	} else extension = NULL;
       		 (*fdpp)->fd_type = FD_STREAM;
//		if ( extension ){
           	     (*fdpp)->fd_stream = NXOpenMemory(NULL, 0, NX_READWRITE);
           	     [object writeToStream:(*fdpp)->fd_stream];
        	     (*fdpp)->fd_size = NXTell((*fdpp)->fd_stream);
	             NXSeek((*fdpp)->fd_stream, 0, NX_FROMSTART);
DBG(1, NXSaveToFile((*fdpp)->fd_stream, (*fdpp)->fd_name);)
   		     NXSeek((*fdpp)->fd_stream, 0, NX_FROMSTART);
		     prevfdp = *fdpp;
       		     fdpp = &(*fdpp)->fd_nextp;
        	     if (!strcmp(key = [object key], PLAINTEXT)) {
	    		plainonly=1;
   		      	break;
     		     }
	}else{
		;
	}
      } 
    *fdpp = NULL;
	

    MimeArticleStream = NXOpenMemory(NULL, 0, NX_READWRITE);



    // terminate the posting
 
    if ( isMultimedia == YES && plainonly == 0){
        RTFparse(file_desc_head, MimeArticleStream, bound,countObj);
	if ( countObj >= 3 )
	NXPrintf(MimeArticleStream, "\r\n--%s-- ", bound);
    }
    else{
      for (fdp = file_desc_head, n=0;  fdp != NULL
			; n++, fdp = fdp->fd_nextp) {
        if(!strcmp(fdp->fd_name, PLAINTEXT)) {
        	NXSeek(fdp->fd_stream, (long)0,NX_FROMEND);
        	(long)size = NXTell(fdp->fd_stream);
        	NXSeek(fdp->fd_stream, (long)0,NX_FROMSTART);
        	NXGetMemoryBuffer(fdp->fd_stream,&buff,&len,&max);
        	NXWrite(MimeArticleStream, (const void *)buff, size);
		break;
        }
      }
    }
    NXSeek(MimeArticleStream,(long)0, NX_FROMEND);
    (long)size = NXTell(MimeArticleStream);
    NXSeek(MimeArticleStream,(long)size-1, NX_FROMSTART);
    NXPrintf(MimeArticleStream, "\r\n.\r\n");

    state = [header initState];
    while ([header nextState: &state key: (void **)&key value: (void **)&value]) {
           NXPrintf(MimeArticleStream1, "%s: %s\r\n", key, value);
    }
   if ( *fontheader !='\0' ){
        NXPrintf(MimeArticleStream1,"X-Fonttbl: {\\fonttbl%s}\r\n", fontheader);
	fontheader[0]='\0';
  }
    // terminate header
    NXPrintf(MimeArticleStream1, "\r\n");
    concatstream(MimeArticleStream1, MimeArticleStream);

   
    for (fdp = file_desc_head, n=0; fdp != NULL
			; n++, fdp = fdp->fd_nextp) {
        NXCloseMemory(fdp->fd_stream, NX_FREEBUFFER);
    }
    NXCloseMemory(MimeArticleStream,NX_FREEBUFFER);
    NXSeek(MimeArticleStream1, (long)0, NX_FROMSTART);
DBG(1,NXSaveToFile(MimeArticleStream1, "MimeArticleStream");)
    NXSeek(MimeArticleStream1, (long)0, NX_FROMSTART);
}

- convertToItem:(NXStream *)stream
{
    id     articleItem,mediaClass,mediaObject;
    struct mem_file_desc  *adpp,*temppp, *get_Item();
    int i=0, plainonly=1;
    NXStream *Body;
    NXStream *plainBody;
    NXStream *HBody;
    NXStream *tmpStream;
    char *extension=NULL;
    char *temp_ext;
    char *MsgId=NULL;
    char *Mimeversion=NULL;
    char *fonttbl=NULL;
    char pathName[2048];
    NXStream *crlfStream;
    void tocrlf(NXStream *in, NXStream *out);

    // convert '\n' --> '\r''\n'
    //   local disk convention is that the end of line is '\n', but MIME
    //   converter request '\r''\n' at the end
    NXSeek (stream, (long)0, NX_FROMSTART);
    crlfStream = NXOpenMemory (NULL, 0, NX_READWRITE);
    tocrlf (stream, crlfStream);
    NXSeek (crlfStream, (long)0, NX_FROMSTART);

    temppp = get_Item(crlfStream);
    NXCloseMemory (crlfStream, NX_FREEBUFFER);

    for( adpp = temppp; adpp !=(struct mem_file_desc *)NULL ; 
					    adpp = adpp->fd_nextp){
         extension = rindex(adpp->fd_name, '.');
         if (extension) {
             ++extension;
         } else {
        	extension = (char *) calloc (15, sizeof(char));
        	strcpy(extension,"NULL_Extension");
	 }
         temp_ext = (char *) calloc (100, sizeof(char));
	 strcpy(temp_ext,extension);
	 temp_ext=Cleanse(temp_ext);
        if ( i == 0 ){
            mediaClass =(id)[IMediaTable mediaClassForFileExtension:extension];
            // There are really two kinds of .rtf objects: index.rtf and
            // regular .rtf objects.  The media table gives the object for
            // index.rtf.  Regular .rtf objects can be handled as binary
            // objects.
            if (mediaClass == (id)[IMediaTable mediaClassForFileExtension:
                RTF_FILE_EXTENSION] && strcmp(adpp->fd_name, INDEX_RTF) != 0) {
                mediaClass = [IBinaryD class];
            }
            mediaObject = [[(id)mediaClass allocFromZone:[self zone]]
                   initWithKey:adpp->fd_name];
            NXSeek(adpp->fd_stream, (long)0,NX_FROMSTART);
            [mediaObject  readFromStream:adpp->fd_stream];
            MsgId = [mediaObject infoForKey:MESSAGE_ID];
	    if (!MsgId){
            	MsgId = [mediaObject infoForKey:"Message-Id"];
	    	if (!MsgId){
            		MsgId = [mediaObject infoForKey:"Message-id"];
			if (!MsgId){
	        	        MsgId = (char *) calloc (200, sizeof(char));
				strcpy(MsgId,"There_is_No_MessageID");	
			fprintf(stderr,"IConvertMIME:No Msg ID in the header\n");
			}
		}
	    }
            fonttbl = [mediaObject infoForKey:"X-Fonttbl"];
	    if (!fonttbl){
            	fonttbl = [mediaObject infoForKey:"X-fonttbl"];
	    }

            articleItem = [[IArticleD allocFromZone:[self zone]] initWithKey:MsgId];
            Mimeversion = [mediaObject infoForKey:"Mime-Version"];
	    if (!Mimeversion){
	    	if (!Mimeversion){
		  Mimeversion = [mediaObject infoForKey:"MIME-Version"];
	    		if (!Mimeversion){
			//fprintf(stderr,"IConvertMIME:No Mime-Version header\n");
			Mimeversion = NULL;
			}
		}
	    }
		
DBG(1,NXSaveToFile(adpp->fd_stream, adpp->fd_name);)
    	    NXCloseMemory(adpp->fd_stream,NX_FREEBUFFER);
            [articleItem insertKeyedObject:mediaObject];
	
 	    i++;
 	    Body = NXOpenMemory(NULL,0,NX_READWRITE);
 	    plainBody = NXOpenMemory(NULL,0,NX_READWRITE);
        }else {
            if ( Mimeversion == NULL ){	
//  There is no Mime-Version header in headers.
                NXSeek(adpp->fd_stream, (long)0,NX_FROMSTART);
		concatstream(plainBody,adpp->fd_stream);
    	    NXCloseMemory(adpp->fd_stream,NX_FREEBUFFER);
 	    }else{	
//  There is a Mime-Version header in headers.
		if (!strcmp(temp_ext,"plain") ){
	            NXPrintf(Body,"\n");
		    concatstream(Body,tmpStream=plain2rtf(adpp->fd_stream));
		    concatstream(plainBody,adpp->fd_stream);
    	    NXCloseMemory(tmpStream,NX_FREEBUFFER);
    	    NXCloseMemory(adpp->fd_stream,NX_FREEBUFFER);
		    if ( plainonly )
			plainonly=1;
		    else
			plainonly=0;
		}else if (!strcmp(temp_ext,"ez") ){
		    concatstream(Body,tmpStream=ez2rtf(adpp->fd_stream));
    	    NXCloseMemory(tmpStream,NX_FREEBUFFER);
    	    NXCloseMemory(adpp->fd_stream,NX_FREEBUFFER);
		    plainonly=0;
		}else if (!strcmp(temp_ext,"next") ){
		    concatstream(Body,adpp->fd_stream);
    	    NXCloseMemory(adpp->fd_stream,NX_FREEBUFFER);
		    plainonly=0;
		    strcpy(Mimeversion , "next");
		}else if (!strcmp(temp_ext,"richtext") ){
	            NXPrintf(Body,"\n");
		    concatstream(Body,tmpStream=richtext2rtf(adpp->fd_stream));
    	    NXCloseMemory(tmpStream,NX_FREEBUFFER);
    	    NXCloseMemory(adpp->fd_stream,NX_FREEBUFFER);
		    plainonly=0;
		}else{

		plainonly=0;
		NXPrintf(Body,
                  "\n{\\pard\\tx1280\\tx2560\\tx3840\\tx5120\\tx6400\\tx7680\\tx8960\\tx10240\\tx11520\\tx12800\\f0\\b0\\i0\\ul0\\fs32\\fc0{\\MMtiff%d %s\n}\n%c}", i++, adpp->fd_name, '\254');
		if ( !strcmp(temp_ext,"local-file") ||
		     !strcmp(temp_ext,"x-news")     ||
		     !strcmp(temp_ext,"anon-ftp")){
		    strncpy(pathName, adpp->fd_name, 2048);
		    *rindex(pathName,'.')= '\0';	
                      mediaObject = [[IExternalD
                    allocFromZone:NXCreateZone(vm_page_size, vm_page_size, YES)]
                    initWithDomain:NXUniqueString(extension) andPath:pathName];
		}else{

	             mediaClass =(id)[IMediaTable mediaClassForFileExtension:extension]; 
                     // There are really two kinds of .rtf objects: index.rtf
                     // and regular .rtf objects.  The media table gives the
                     // object for index.rtf.  Regular .rtf objects can be
                     // handled as binary objects.
                     if (mediaClass == (id)[IMediaTable
                         mediaClassForFileExtension:RTF_FILE_EXTENSION] &&
                         strcmp(adpp->fd_name, INDEX_RTF) != 0) {
                         mediaClass = [IBinaryD class];
                     }
		     if ( mediaClass != NULL ){
                     	mediaObject = [[(id)mediaClass allocFromZone:[self zone]] initWithKey:adpp->fd_name];
                     	NXSeek(adpp->fd_stream, (long)0,NX_FROMSTART);
                     	[mediaObject readFromStream:adpp->fd_stream];
                     	NXCloseMemory(adpp->fd_stream,NX_FREEBUFFER);
		     } else {
			mediaObject = [IBinaryD allocFromZone: [self zone]];
			[mediaObject initWithKey:adpp->fd_name];
			[mediaObject readFromStream:adpp->fd_stream];
                     	NXCloseMemory(adpp->fd_stream,NX_FREEBUFFER);
//			[IMediaD getFileIconFor:mediaObject];
//			[mediaObject setImage:icon]; 
		    }
			
                    [articleItem insertKeyedObject:mediaObject];
		}
//                [articleItem insertKeyedObject:mediaObject];
		}
	    }
        }
	free(temp_ext);
    }
    if ( Mimeversion == NULL || plainonly == 1 ){
        mediaObject = [[ITextD allocFromZone:[self zone]]
            initWithKey:PLAINTEXT];
        NXSeek(plainBody, (long)0,NX_FROMSTART);
        [mediaObject readFromStream:plainBody];
//        if (strcmp(NXGetDefaultValue(OWNER,KANJICODE),"JIS")==0) {
//            [mediaObject kanjiCodeConvert:"jis_to_euc"];
//        }
        [articleItem insertKeyedObject:mediaObject];
DBG(1,NXSaveToFile(plainBody, PLAINTEXT);)
    }else if (!strcmp(Mimeversion,"next")){
        mediaObject = [[ITextD allocFromZone:[self zone]]
            initWithKey:INDEX_RTF];
        NXSeek(Body, (long)0,NX_FROMSTART);
        [mediaObject readFromStream:Body];
//        if (strcmp(NXGetDefaultValue(OWNER,KANJICODE),"JIS")==0) {
//            [mediaObject kanjiCodeConvert:"jis_to_euc"];
//        }
        [articleItem insertKeyedObject:mediaObject];
DBG(1,NXSaveToFile(Body, INDEX_RTF);)
    }else{
        mediaObject = [[ITextD allocFromZone:[self zone]]
            initWithKey:INDEX_RTF];
        NXSeek(Body, (long)0,NX_FROMSTART);
 	HBody = NXOpenMemory(NULL,0,NX_READWRITE);
	CreatertfHead(HBody, fonttbl);
	fonttbl=NULL;
	NXPrintf(HBody,"\n");
        concatstream(HBody,Body);
	NXPrintf(HBody,"}");
        NXSeek(HBody, (long)0,NX_FROMSTART);
        [mediaObject readFromStream:HBody];
//        if (strcmp(NXGetDefaultValue(OWNER,KANJICODE),"JIS")==0) {
//            [mediaObject kanjiCodeConvert:"jis_to_euc"];
//        }
        [articleItem insertKeyedObject:mediaObject];
DBG(1,NXSaveToFile(HBody, INDEX_RTF);)
        NXCloseMemory(HBody,NX_FREEBUFFER);
   }

    NXCloseMemory(Body,NX_FREEBUFFER);
    NXCloseMemory(plainBody,NX_FREEBUFFER);
    free(temppp);

    return(articleItem); 
}

@end
