/* * Copyright (C) 2006 Nigel Horne * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. */ static char const rcsid[] = "$Id: uuencode.c,v 1.8 2006/12/11 11:55:11 njh Exp $"; #include "clamav.h" #if HAVE_CONFIG_H #include "clamav-config.h" #endif #ifdef HAVE_UNISTD_H #include #endif #include #include #include #ifdef HAVE_STRINGS_H #include #endif #include "others.h" #include "str.h" #ifdef C_WINDOWS #include #endif #include "mbox.h" #include "uuencode.h" /* Maximum line length according to RFC821 */ #define RFC2821LENGTH 1000 int cli_uuencode(const char *dir, int desc) { FILE *fin; int i; message *m; char buffer[RFC2821LENGTH + 1]; i = dup(desc); if((fin = fdopen(i, "rb")) == NULL) { cli_errmsg("Can't open descriptor %d\n", desc); close(i); return CL_EOPEN; } if(fgets(buffer, sizeof(buffer) - 1, fin) == NULL) { /* empty message */ fclose(fin); return CL_CLEAN; } if(!isuuencodebegin(buffer)) { fclose(fin); cli_errmsg("Message is not in uuencoded format\n"); return CL_EFORMAT; } m = messageCreate(); if(m == NULL) { fclose(fin); return CL_EMEM; } cli_dbgmsg("found uuencode file\n"); if(uudecodeFile(m, buffer, dir, fin) < 0) { messageDestroy(m); fclose(fin); cli_errmsg("Message is not in uuencoded format\n"); return CL_EFORMAT; } messageDestroy(m); fclose(fin); return CL_CLEAN; /* a lie - but it gets things going */ } /* * Save the uuencoded part of the file as it is read in since there's no need * to include it in the parse tree. Saves memory and parse time. * Return < 0 for failure */ int uudecodeFile(message *m, const char *firstline, const char *dir, FILE *fin) { fileblob *fb; char buffer[RFC2821LENGTH + 1]; char *filename = cli_strtok(firstline, 2, " "); if(filename == NULL) return -1; fb = fileblobCreate(); if(fb == NULL) { free(filename); return -1; } fileblobSetFilename(fb, dir, filename); cli_dbgmsg("uudecode %s\n", filename); free(filename); while(fgets(buffer, sizeof(buffer) - 1, fin) != NULL) { unsigned char data[1024]; const unsigned char *uptr; size_t len; cli_chomp(buffer); if(strcasecmp(buffer, "end") == 0) break; if(buffer[0] == '\0') break; uptr = decodeLine(m, UUENCODE, buffer, data, sizeof(data)); if(uptr == NULL) break; len = (size_t)(uptr - data); if((len > 62) || (len == 0)) break; if(fileblobAddData(fb, data, len) < 0) break; } fileblobDestroy(fb); return 1; }