/* $Id: uuefile.c,v 1.7.2.3 2003/01/31 11:55:40 stas_degteff Exp $ */ #include "uuecode.h" #include "dupe.h" #include #include #include #include static char *invalidExt[] = {"*.mo?", "*.tu?", "*.we?", "*.th?", "*.fr?", "*.sa?", "*.su?", "*.pkt", "*.tic"}; int isReady(UUEFile* uuc); void MakeFile(UUEFile* uuc); void MakeTicFile(UUEFile* uuc); void FreeUUEFile(UUEFile* uuc); typedef struct { char* areamask; char* fileEcho; } uueFileGroup; unsigned int fileGroupscount = 0; uueFileGroup *uueFileGroups = NULL; void initFileGroups() { unsigned int i = 0; char *tok; if(!config->numuuEGrp || uueFileGroups) return; for(i = 0; i < config->numuuEGrp; i++) { tok = strtok(config->uuEGrp[i], " \t,"); tok = strtok(NULL, " \t,"); while (tok) { uueFileGroups = srealloc(uueFileGroups, sizeof(uueFileGroup)*(fileGroupscount+1)); uueFileGroups[fileGroupscount].areamask = sstrdup(tok); uueFileGroups[fileGroupscount].fileEcho = config->uuEGrp[i]; fileGroupscount++; tok = strtok(NULL, " \t,"); } } } char* findFileGroup(char* areaMask) { unsigned int i = 0; char* areagroup = NULL; initFileGroups(); if(!uueFileGroups) return xstrscat(&areagroup,"uue.",areaMask,NULL); for(i = 0; i < fileGroupscount; i++) { if (patimat(areaMask,uueFileGroups[i].areamask)) return sstrdup(uueFileGroups[i].fileEcho); } return xstrscat(&areagroup,"uue.",areaMask,NULL); } #define DECODE_BYTE(b) ((b == 0x60) ? 0 : b - 0x20) typedef unsigned char BYTE; int DecodePart(char *text, FILE *outfile) { char *linep = NULL; size_t linelen = 0; int linecnt = 0; BYTE outbyte [3]; char* endl =NULL; char* linebuf = text; int lastlen = 0; int nRet = 0; do { endl = strchr(linebuf,'\r'); if(endl) endl[0] = '\0'; else break; /* The first byte of the line represents the length of the DECODED line */ linelen = DECODE_BYTE (linebuf [0]); linep = linebuf + 1; for (linecnt = linelen; linecnt > 0; linecnt -= 3, linep += 4) { lastlen = strlen(linep); if(lastlen > 3) { /* Decode the 4-byte block */ outbyte [0] = DECODE_BYTE (linep [0]); outbyte [1] = DECODE_BYTE (linep [1]); outbyte [0] <<= 2; outbyte [0] |= (outbyte [1] >> 4) & 0x03; outbyte [1] <<= 4; outbyte [2] = DECODE_BYTE (linep [2]); outbyte [1] |= (outbyte [2] >> 2) & 0x0F; outbyte [2] <<= 6; outbyte [2] |= DECODE_BYTE (linep [3]) & 0x3F; } else { outbyte [0] = DECODE_BYTE (linep [0]); if(lastlen > 1) { outbyte [1] = DECODE_BYTE (linep [1]); outbyte [0] <<= 2; outbyte [0] |= (outbyte [1] >> 4) & 0x03; outbyte [1] <<= 4; } if(lastlen > 2) { outbyte [2] = DECODE_BYTE (linep [2]); outbyte [1] |= (outbyte [2] >> 2) & 0x0F; outbyte [2] <<= 6; } //outbyte [2] |= DECODE_BYTE (linep [3]) & 0x3F; } /* Write the decoded bytes to the output file */ if (linecnt > 3) { if (fwrite (outbyte, 1, 3, outfile) != 3) { fprintf (stderr, "uudecode: Error writing to output file\n"); exit (1); } } else { if (fwrite (outbyte, 1, linecnt, outfile) != (size_t)linecnt) { fprintf (stderr, "uudecode: Error writing to output file\n"); exit (1); } linecnt = 3; } } nRet = 1; do { endl++; } while(endl[0] == '\r'); linebuf = endl; linelen = strlen(linebuf); } while (linelen > 1); return nRet; } int isReady(UUEFile* uuc) { int i; for(i = 0; i < uuc->m_nSections; i++) { if(uuc->UUEparts[i] == NULL) return 0; } return i == uuc->m_nSections; } UUEFile* MakeUUEFile(int nsec, char *name) { UUEFile* uuc = scalloc(1,sizeof(UUEFile)); uuc->m_nSections = nsec; if(nsec>0){ uuc->UUEparts = (char**)scalloc( nsec, sizeof(char*) ); if(nDelMsg || nCutMsg) uuc->toBeDeleted = (dword*)scalloc(nsec,sizeof(dword)); } if(name) uuc->m_fname = sstrdup(name); return uuc; } void FreeUUEFile(UUEFile* uuc) { int i; for(i = 0; i < uuc->m_nSections; i++) nfree(uuc->UUEparts[i]); nfree(uuc->toBeDeleted); nfree(uuc->description); nfree(uuc->m_fname); } void FreeUUEChain() { UUEFile* node = UFilesHead->next; w_log(LL_FUNC,"%s::FreeUUEChain()", __FILE__); while(UFilesHead->next) { node = UFilesHead->next->next; FreeUUEFile(UFilesHead->next); //nfree(UFilesHead->next); UFilesHead->next = node; } UFilesHead->prev = UFilesHead; } UUEFile* FindUUEFile(char *name) { UUEFile* node = UFilesHead->next; while(node) { if( node->m_fname && (stricmp(name, node->m_fname) == 0) ) break; node = node->next; } return node; } void AddPart(UUEFile* uuc, char* uuepart, int section, int slen) { if(section > uuc->m_nSections || uuc->m_nAdded == uuc->m_nSections || uuc->UUEparts[section-1]) return; if(section == 1) uuc->description = sstrdup((char*)xmsg.subj); uuc->UUEparts[section-1] = scalloc( slen+1, sizeof(char) ); strncpy(uuc->UUEparts[section-1],uuepart,slen); if(nDelMsg || nCutMsg) uuc->toBeDeleted[uuc->m_nAdded] = currMsgUid; uuc->m_nAdded++; if((uuc->m_nAdded == uuc->m_nSections) && isReady(uuc)) { MakeFile(uuc); } } #if defined(WINNT) # ifdef __MINGW32__ typedef int BOOL; typedef char *LPWSTR; typedef const char *LPCWSTR; BOOL __stdcall OemToCharA(LPCWSTR,LPWSTR); #define OemToChar OemToCharA # endif #elif !defined(UNIX) && !defined(OS2) && !defined(__DJGPP__) # include #endif void MakeFile(UUEFile* uuc) { FILE *out; char *fname = NULL; int i, nodel=0; s_textDupeEntry *msg = scalloc(sizeof(s_textDupeEntry),1); msg->filename = sstrdup(uuc->m_fname); msg->areaname = sstrdup(currArea->areaName); msg->from = sstrdup((char*)xmsg.from); if(dupeDetection(msg) == 1) { for(i = 0; i < 9; i++) { if(patimat(uuc->m_fname,invalidExt[i])) xstrcat(&uuc->m_fname,"_"); } xstrscat(&fname,config->protInbound,uuc->m_fname,NULL); if(!fexist(fname)) { out = fopen(fname, "wb"); if(out) { for(i = 0; i < uuc->m_nSections; i++) { if( DecodePart(uuc->UUEparts[i], out) == 0) break; } fclose(out); if(i == uuc->m_nSections) { w_log(LL_INFO, "file: %15s has %d complete sections is saved", uuc->m_fname,uuc->m_nSections); MakeTicFile(uuc); nodel = 0; } else { remove(fname); nodel = 1; } } else { w_log(LL_ERROR,"file: %15s can not be created", uuc->m_fname); } } else { w_log(LL_CREAT,"file: %15s detected in inbound", uuc->m_fname); } } else { w_log(LL_FUNC,"%s::MakeFile(), dupe file %15s detected", __FILE__,uuc->m_fname); } if( (!nodel) && (nDelMsg || nCutMsg) ) { for( i = 0; i < uuc->m_nSections; i++ ) toBeDeleted[nMaxDeleted+i] = uuc->toBeDeleted[i]; nMaxDeleted += uuc->m_nSections; } FreeUUEFile(uuc); //nfree(uuc); nfree(fname); w_log(LL_FUNC,"%s::MakeFile(), exit", __FILE__); } void MakeTicFile(UUEFile* uuc) { unsigned int i=0; struct stat stbuf; FILE *tichandle = NULL; char *newticfile = NULL; char *fname = NULL; char *areagroup = NULL; char origstr[36] = ""; s_link* link = getLinkFromAddr( config,*(currArea->useAka) ); while( !link && i < config->addrCount ) { link = getLinkFromAddr( config, config->addr[i] ); i++; } if(!link) { w_log(LL_INFO, "tic file not created for file %s", uuc->m_fname); return ; } xstrscat(&fname,config->protInbound,uuc->m_fname,NULL); stat(fname,&stbuf); if(stbuf.st_size == 0) { remove(fname); return; } newticfile=makeUniqueDosFileName(config->protInbound,"tic",config); tichandle=fopen(newticfile,"wb"); areagroup = findFileGroup(currArea->areaName); if(xmsg.orig.point == 0) sprintf(origstr, "%d:%d/%d", xmsg.orig.zone, xmsg.orig.net, xmsg.orig.node); else sprintf(origstr, "%d:%d/%d.%d", xmsg.orig.zone, xmsg.orig.net, xmsg.orig.node, xmsg.orig.point); if (config->outtab != NULL) recodeToTransportCharset(uuc->description); fprintf(tichandle, "Created by %s, written by Max Chernogor\r\n",versionStr); fprintf(tichandle, "File %s\r\n", uuc->m_fname); fprintf(tichandle, "Area %s\r\n", areagroup); if(uuc->description) fprintf(tichandle, "Desc %s\r\n", uuc->description); fprintf(tichandle, "From %s\r\n", aka2str(link->hisAka)); fprintf(tichandle, "To %s\r\n", aka2str(link->hisAka)); fprintf(tichandle, "Origin %s\r\n", origstr); fprintf(tichandle, "Size %lu\r\n", (unsigned long)stbuf.st_size); fprintf(tichandle, "Crc %08lX\r\n", (unsigned long) filecrc32(fname)); if(link->fileFixPwd) fprintf(tichandle, "Pw %s\r\n", link->fileFixPwd); fclose(tichandle); w_log(LL_CREAT, "tic file:%s created for file:%s",newticfile, uuc->m_fname); nfree(newticfile); nfree(areagroup); }