mirror of
https://bitbucket.org/jsuto/piler.git
synced 2025-01-13 05:00:12 +01:00
Added support for consolidated zip files
Signed-off-by: Janos SUTO <sj@acts.hu>
This commit is contained in:
parent
f2e9dc8343
commit
ae97f52adf
172
src/archive.c
172
src/archive.c
@ -18,6 +18,7 @@
|
||||
#include <openssl/evp.h>
|
||||
#include <zlib.h>
|
||||
#include <assert.h>
|
||||
#include <zip.h>
|
||||
#include <piler.h>
|
||||
|
||||
|
||||
@ -130,34 +131,89 @@ int inf(unsigned char *in, int len, int mode, char **buffer, FILE *dest){
|
||||
}
|
||||
|
||||
|
||||
unsigned char *extract_file_from_zip(char *zipfile, char *filename, zip_uint64_t *size){
|
||||
int i=0, errorp;
|
||||
unsigned char *p=NULL;
|
||||
struct zip *z;
|
||||
struct zip_stat sb;
|
||||
struct zip_file *zf;
|
||||
|
||||
z = zip_open(zipfile, ZIP_RDONLY, &errorp);
|
||||
if(!z){
|
||||
syslog(LOG_INFO, "%s: error: corrupt zip file=%s, error code=%d", zipfile, filename, errorp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while(zip_stat_index(z, i, 0, &sb) == 0){
|
||||
if(sb.size > 0 && sb.comp_size > 0 && strncmp(sb.name, filename, strlen(filename)) == 0){
|
||||
*size = sb.comp_size;
|
||||
zf = zip_fopen_index(z, i, 0);
|
||||
if(zf){
|
||||
p = malloc(sb.comp_size);
|
||||
if(p){
|
||||
if(zip_fread(zf, p, sb.comp_size) == -1){
|
||||
syslog(LOG_PRIORITY, "zip_fread(): Error reading %s from %s", filename, zipfile);
|
||||
free(p);
|
||||
p = NULL;
|
||||
}
|
||||
}
|
||||
zip_fclose(zf);
|
||||
}
|
||||
else syslog(LOG_PRIORITY, "cannot extract '%s' from '%s'", filename, zipfile);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
zip_close(z);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
int retrieve_file_from_archive(char *filename, int mode, char **buffer, FILE *dest, struct config *cfg){
|
||||
int rc=0, n, olen, tlen, len, fd=-1;
|
||||
unsigned char *s=NULL, *addr=NULL, inbuf[REALLYBIGBUFSIZE];
|
||||
char *relfilename;
|
||||
unsigned char *s=NULL, *addr=NULL, *zipbuf=NULL, inbuf[REALLYBIGBUFSIZE];
|
||||
struct stat st;
|
||||
zip_uint64_t zipped_size=0;
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
EVP_CIPHER_CTX ctx;
|
||||
#else
|
||||
EVP_CIPHER_CTX *ctx=NULL;
|
||||
#endif
|
||||
|
||||
syslog(LOG_PRIORITY, "retrieveing %s", filename);
|
||||
|
||||
if(filename == NULL) return 1;
|
||||
|
||||
relfilename = strchr(filename, ' ');
|
||||
if(relfilename){
|
||||
// We'll read the given file from a zip file
|
||||
// filename is decomposed to <zipfile> and <relative filename>
|
||||
*relfilename = '\0';
|
||||
relfilename++;
|
||||
|
||||
fd = open(filename, O_RDONLY);
|
||||
if(fd == -1){
|
||||
syslog(LOG_PRIORITY, "%s: cannot open()", filename);
|
||||
return 1;
|
||||
zipbuf = extract_file_from_zip(filename, relfilename, &zipped_size);
|
||||
len = zipped_size+EVP_MAX_BLOCK_LENGTH;
|
||||
}
|
||||
else {
|
||||
// We have a distinct .m file or an attachment to read from
|
||||
fd = open(filename, O_RDONLY);
|
||||
if(fd == -1){
|
||||
syslog(LOG_PRIORITY, "%s: cannot open()", filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(fstat(fd, &st)){
|
||||
syslog(LOG_PRIORITY, "%s: cannot fstat()", filename);
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(fstat(fd, &st)){
|
||||
syslog(LOG_PRIORITY, "%s: cannot fstat()", filename);
|
||||
close(fd);
|
||||
return 1;
|
||||
len = st.st_size+EVP_MAX_BLOCK_LENGTH;
|
||||
}
|
||||
|
||||
|
||||
if(cfg->encrypt_messages == 1){
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
EVP_CIPHER_CTX_init(&ctx);
|
||||
@ -170,8 +226,6 @@ int retrieve_file_from_archive(char *filename, int mode, char **buffer, FILE *de
|
||||
EVP_DecryptInit_ex(ctx, EVP_bf_cbc(), NULL, cfg->key, cfg->iv);
|
||||
#endif
|
||||
|
||||
len = st.st_size+EVP_MAX_BLOCK_LENGTH;
|
||||
|
||||
s = malloc(len);
|
||||
|
||||
if(!s){
|
||||
@ -181,27 +235,35 @@ int retrieve_file_from_archive(char *filename, int mode, char **buffer, FILE *de
|
||||
|
||||
tlen = 0;
|
||||
|
||||
while((n = read(fd, inbuf, sizeof(inbuf)))){
|
||||
if(!relfilename){
|
||||
while((n = read(fd, inbuf, sizeof(inbuf)))){
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
if(!EVP_DecryptUpdate(&ctx, s+tlen, &olen, inbuf, n)){
|
||||
#else
|
||||
if(!EVP_DecryptUpdate(ctx, s+tlen, &olen, inbuf, n)){
|
||||
#endif
|
||||
syslog(LOG_PRIORITY, "%s: EVP_DecryptUpdate()", filename);
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
if(!EVP_DecryptUpdate(&ctx, s+tlen, &olen, inbuf, n)){
|
||||
#else
|
||||
if(!EVP_DecryptUpdate(ctx, s+tlen, &olen, inbuf, n)){
|
||||
#endif
|
||||
syslog(LOG_PRIORITY, "%s: EVP_DecryptUpdate()", filename);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
tlen += olen;
|
||||
}
|
||||
} else {
|
||||
if(!EVP_DecryptUpdate(ctx, s+tlen, &olen, zipbuf, zipped_size)){
|
||||
printf("error in EVP_DecryptUpdate\n");
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
tlen += olen;
|
||||
}
|
||||
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
if(EVP_DecryptFinal(&ctx, s + tlen, &olen) != 1){
|
||||
#else
|
||||
if(EVP_DecryptFinal(ctx, s + tlen, &olen) != 1){
|
||||
#endif
|
||||
syslog(LOG_PRIORITY, "%s: EVP_DecryptFinal()", filename);
|
||||
printf("error in EVP_DecryptFinal\n");
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
@ -222,6 +284,7 @@ int retrieve_file_from_archive(char *filename, int mode, char **buffer, FILE *de
|
||||
CLEANUP:
|
||||
if(fd != -1) close(fd);
|
||||
if(s) free(s);
|
||||
if(zipbuf) free(zipbuf);
|
||||
if(cfg->encrypt_messages == 1)
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
@ -233,13 +296,57 @@ CLEANUP:
|
||||
}
|
||||
|
||||
|
||||
void assemble_filename(char *filename, int len, char *s, struct config *cfg){
|
||||
char zipfilename[SMALLBUFSIZE];
|
||||
struct stat st;
|
||||
|
||||
/*
|
||||
* If the zip file exists, then fix the filename to be '<zipfile> <relative filename>'
|
||||
*/
|
||||
snprintf(zipfilename, sizeof(zipfilename)-1, "%s/%02x/%c%c%c.zip", cfg->queuedir, cfg->server_id, s[8], s[9], s[10]);
|
||||
|
||||
if(stat(zipfilename, &st)){
|
||||
snprintf(filename, len-1, "%s/%02x/%c%c%c/%c%c/%c%c/%s.m",
|
||||
cfg->queuedir, cfg->server_id, s[8], s[9], s[10], s[RND_STR_LEN-4], s[RND_STR_LEN-3], s[RND_STR_LEN-2], s[RND_STR_LEN-1], s);
|
||||
#ifdef HAVE_SUPPORT_FOR_COMPAT_STORAGE_LAYOUT
|
||||
if(stat(filename, &st)){
|
||||
snprintf(filename, len-1, "%s/%02x/%c%c/%c%c/%c%c/%s.m",
|
||||
cfg->queuedir, cfg->server_id, s[RND_STR_LEN-6], s[RND_STR_LEN-5], s[RND_STR_LEN-4], s[RND_STR_LEN-3], s[RND_STR_LEN-2], s[RND_STR_LEN-1], s);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
snprintf(filename, len-1, "%s %c%c%c/%c%c/%c%c/%s.m",
|
||||
zipfilename, s[8], s[9], s[10], s[RND_STR_LEN-4], s[RND_STR_LEN-3], s[RND_STR_LEN-2], s[RND_STR_LEN-1], s);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void assemble_attachment_filename(char *filename, int len, char *s, int attachment_id, struct config *cfg){
|
||||
char zipfilename[SMALLBUFSIZE];
|
||||
struct stat st;
|
||||
|
||||
snprintf(zipfilename, sizeof(zipfilename)-1, "%s/%02x/%c%c%c.zip", cfg->queuedir, cfg->server_id, s[8], s[9], s[10]);
|
||||
|
||||
if(stat(zipfilename, &st)){
|
||||
snprintf(filename, len-1, "%s/%02x/%c%c%c/%c%c/%c%c/%s.a%d", cfg->queuedir, cfg->server_id, s[8], s[9], s[10], s[RND_STR_LEN-4], s[RND_STR_LEN-3], s[RND_STR_LEN-2], s[RND_STR_LEN-1], s, attachment_id);
|
||||
|
||||
#ifdef HAVE_SUPPORT_FOR_COMPAT_STORAGE_LAYOUT
|
||||
if(stat(filename, &st)){
|
||||
snprintf(filename, len-1, "%s/%02x/%c%c/%c%c/%c%c/%s.a%d",
|
||||
cfg->queuedir, cfg->server_id, s[RND_STR_LEN-6], s[RND_STR_LEN-5], s[RND_STR_LEN-4], s[RND_STR_LEN-3], s[RND_STR_LEN-2], s[RND_STR_LEN-1], s, attachment_id);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
snprintf(filename, len-1, "%s %c%c%c/%c%c/%c%c/%s.a%d",
|
||||
zipfilename, s[8], s[9], s[10], s[RND_STR_LEN-4], s[RND_STR_LEN-3], s[RND_STR_LEN-2], s[RND_STR_LEN-1], s, attachment_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int retrieve_email_from_archive(struct session_data *sdata, FILE *dest, struct config *cfg){
|
||||
int attachments;
|
||||
char *buffer=NULL, *saved_buffer, *p, filename[SMALLBUFSIZE];
|
||||
struct ptr_array ptr_arr[MAX_ATTACHMENTS];
|
||||
#ifdef HAVE_SUPPORT_FOR_COMPAT_STORAGE_LAYOUT
|
||||
struct stat st;
|
||||
#endif
|
||||
|
||||
if(strlen(sdata->ttmpfile) != RND_STR_LEN){
|
||||
printf("invalid piler-id: %s\n", sdata->ttmpfile);
|
||||
@ -253,12 +360,8 @@ int retrieve_email_from_archive(struct session_data *sdata, FILE *dest, struct c
|
||||
return 1;
|
||||
}
|
||||
|
||||
snprintf(filename, sizeof(filename)-1, "%s/%02x/%c%c%c/%c%c/%c%c/%s.m", cfg->queuedir, cfg->server_id, *(sdata->ttmpfile+8), *(sdata->ttmpfile+9), *(sdata->ttmpfile+10), *(sdata->ttmpfile+RND_STR_LEN-4), *(sdata->ttmpfile+RND_STR_LEN-3), *(sdata->ttmpfile+RND_STR_LEN-2), *(sdata->ttmpfile+RND_STR_LEN-1), sdata->ttmpfile);
|
||||
#ifdef HAVE_SUPPORT_FOR_COMPAT_STORAGE_LAYOUT
|
||||
if(stat(filename, &st)){
|
||||
snprintf(filename, sizeof(filename)-1, "%s/%02x/%c%c/%c%c/%c%c/%s.m", cfg->queuedir, cfg->server_id, *(sdata->ttmpfile+RND_STR_LEN-6), *(sdata->ttmpfile+RND_STR_LEN-5), *(sdata->ttmpfile+RND_STR_LEN-4), *(sdata->ttmpfile+RND_STR_LEN-3), *(sdata->ttmpfile+RND_STR_LEN-2), *(sdata->ttmpfile+RND_STR_LEN-1), sdata->ttmpfile);
|
||||
}
|
||||
#endif
|
||||
|
||||
assemble_filename(filename, sizeof(filename), sdata->ttmpfile, cfg);
|
||||
|
||||
if(attachments == 0){
|
||||
retrieve_file_from_archive(filename, WRITE_TO_STDOUT, &buffer, dest, cfg);
|
||||
@ -280,14 +383,7 @@ int retrieve_email_from_archive(struct session_data *sdata, FILE *dest, struct c
|
||||
buffer = p + strlen(pointer);
|
||||
|
||||
if(strlen(ptr_arr[i].piler_id) == RND_STR_LEN){
|
||||
snprintf(filename, sizeof(filename)-1, "%s/%02x/%c%c%c/%c%c/%c%c/%s.a%d", cfg->queuedir, cfg->server_id, ptr_arr[i].piler_id[8], ptr_arr[i].piler_id[9], ptr_arr[i].piler_id[10], ptr_arr[i].piler_id[RND_STR_LEN-4], ptr_arr[i].piler_id[RND_STR_LEN-3], ptr_arr[i].piler_id[RND_STR_LEN-2], ptr_arr[i].piler_id[RND_STR_LEN-1], ptr_arr[i].piler_id, ptr_arr[i].attachment_id);
|
||||
|
||||
#ifdef HAVE_SUPPORT_FOR_COMPAT_STORAGE_LAYOUT
|
||||
if(stat(filename, &st)){
|
||||
snprintf(filename, sizeof(filename)-1, "%s/%02x/%c%c/%c%c/%c%c/%s.a%d", cfg->queuedir, cfg->server_id, ptr_arr[i].piler_id[RND_STR_LEN-6], ptr_arr[i].piler_id[RND_STR_LEN-5], ptr_arr[i].piler_id[RND_STR_LEN-4], ptr_arr[i].piler_id[RND_STR_LEN-3], ptr_arr[i].piler_id[RND_STR_LEN-2], ptr_arr[i].piler_id[RND_STR_LEN-1], ptr_arr[i].piler_id, ptr_arr[i].attachment_id);
|
||||
}
|
||||
#endif
|
||||
|
||||
assemble_attachment_filename(filename, sizeof(filename), ptr_arr[i].piler_id, ptr_arr[i].attachment_id, cfg);
|
||||
retrieve_file_from_archive(filename, WRITE_TO_STDOUT, NULL, dest, cfg);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user