1 /*
2  * file.c -- functions for dealing with file output
3  *
4  * Copyright (C)1999-2006 Mark Simpson <damned@theworld.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you can either send email to this
18  * program's maintainer or write to: The Free Software Foundation,
19  * Inc.; 59 Temple Place, Suite 330; Boston, MA 02111-1307, USA.
20  *
21  */
22 #ifdef HAVE_CONFIG_H
23 #  include "config.h"
24 #endif /* HAVE_CONFIG_H */
25 
26 #include "common.h"
27 
28 #include "alloc.h"
29 #include "date.h"
30 #include "debug.h"
31 #include "file.h"
32 #include "mapi_attr.h"
33 #include "options.h"
34 #include "path.h"
35 
36 #define TNEF_DEFAULT_FILENAME "tnef-tmp"
37 
38 /* ask user for confirmation of the action */
39 static int
confirm_action(const char * prompt,...)40 confirm_action (const char *prompt, ...)
41 {
42     if (INTERACTIVE)
43     {
44 	int confirmed = 0;
45 	char buf[BUFSIZ + 1];
46 	va_list args;
47 	va_start (args, prompt);
48 
49 	VPRINTF(stdout, prompt, args);
50 	fgets (buf, BUFSIZ, stdin);
51 	if (buf[0] == 'y' || buf[0] == 'Y') confirmed = 1;
52 
53 	va_end (args);
54 
55 	return confirmed;
56     }
57     return 1;
58 }
59 
60 void
file_write(File * file,const char * directory)61 file_write (File *file, const char* directory)
62 {
63     char *path = NULL;
64 
65     assert (file);
66     if (!file) return;
67 
68     if (file->name == NULL)
69     {
70 	file->name = strdup( TNEF_DEFAULT_FILENAME );
71 	debug_print ("No file name specified, using default %s.\n", TNEF_DEFAULT_FILENAME);
72     }
73 
74     if ( file->path == NULL )
75     {
76 	file->path = munge_fname( file->name );
77 
78 	if (file->path == NULL)
79 	{
80 	    file->path = strdup( TNEF_DEFAULT_FILENAME );
81 	    debug_print ("No path name available, using default %s.\n", TNEF_DEFAULT_FILENAME);
82 	}
83     }
84 
85     path = concat_fname( directory, file->path );
86 
87     if (path == NULL)
88     {
89 	path = strdup( TNEF_DEFAULT_FILENAME );
90 	debug_print ("No path generated, using default %s.\n", TNEF_DEFAULT_FILENAME);
91     }
92 
93     debug_print ("%sWRITING\t|\t%s\t|\t%s\n",
94 		 ((LIST_ONLY==0)?"":"NOT "), file->name, path);
95 
96     if (!LIST_ONLY)
97     {
98 	FILE *fp = NULL;
99 
100 	if (!confirm_action ("extract %s?", file->name)) return;
101 	if (!OVERWRITE_FILES)
102 	{
103 	    if (file_exists (path))
104 	    {
105 		if (!NUMBER_FILES)
106 		{
107 		    fprintf (stderr,
108 			     "tnef: %s: Could not create file: File exists\n",
109 			     path);
110 		    return;
111 		}
112 		else
113 		{
114 		    char *tmp = find_free_number (path);
115 		    debug_print ("Renaming %s to %s\n", path, tmp);
116 		    XFREE (path);
117 		    path = tmp;
118 		}
119 	    }
120 	}
121 
122 	fp = fopen (path, "wb");
123 	if (fp == NULL)
124 	{
125 	    perror (path);
126 	    exit (1);
127 	}
128 	if (fwrite (file->data, 1, file->len, fp) != file->len)
129 	{
130 	    perror (path);
131 	    exit (1);
132 	}
133 	fclose (fp);
134     }
135 
136     if (LIST_ONLY || VERBOSE_ON)
137     {
138 	if (LIST_ONLY && VERBOSE_ON)
139 	{
140 	    /* FIXME: print out date and stuff */
141 	    const char *date_str = date_to_str(&file->dt);
142 	    fprintf (stdout, "%11lu\t|\t%s\t|\t%s\t|\t%s",
143 		     (unsigned long)file->len,
144 		     date_str+4, /* skip the day of week */
145 		     file->name,
146 		     path);
147 	}
148 	else
149 	{
150             fprintf (stdout, "%s\t|\t%s", file->name, path);
151 	}
152 	if ( SHOW_MIME )
153 	{
154 	    fprintf (stdout, "\t|\t%s", file->mime_type ? file->mime_type : "unknown");
155             fprintf (stdout, "\t|\t%s", file->content_id ? file->content_id : "");
156 	}
157         fprintf (stdout, "\n");
158     }
159     XFREE(path);
160 }
161 
162 static void
file_add_mapi_attrs(File * file,MAPI_Attr ** attrs)163 file_add_mapi_attrs (File* file, MAPI_Attr** attrs)
164 {
165     int i;
166     for (i = 0; attrs[i]; i++)
167     {
168 	MAPI_Attr* a = attrs[i];
169 
170 	if (a->num_values)
171 	{
172 
173 	    switch (a->name)
174 	    {
175 	    case MAPI_ATTACH_LONG_FILENAME:
176 		if (file->name) XFREE(file->name);
177 		file->name = strdup( (char*)a->values[0].data.buf );
178 		break;
179 
180 	    case MAPI_ATTACH_DATA_OBJ:
181 		file->len = a->values[0].len;
182 		if (file->data) XFREE (file->data);
183 		file->data = CHECKED_XMALLOC (unsigned char, file->len);
184 		memmove (file->data, a->values[0].data.buf, file->len);
185 		break;
186 
187              case MAPI_ATTACH_MIME_TAG:
188 		if (file->mime_type) XFREE (file->mime_type);
189 		file->mime_type = CHECKED_XMALLOC (char, a->values[0].len);
190 		memmove (file->mime_type, a->values[0].data.buf, a->values[0].len);
191 		break;
192 
193                 case MAPI_ATTACH_CONTENT_ID:
194                     if (file->content_id) XFREE(file->content_id);
195                     file->content_id = CHECKED_XMALLOC (char, a->values[0].len);
196                     memmove (file->content_id, a->values[0].data.buf, a->values[0].len);
197                     break;
198 
199 	    default:
200 		break;
201 	    }
202 	}
203     }
204 }
205 
206 void
file_add_attr(File * file,Attr * attr)207 file_add_attr (File* file, Attr* attr)
208 {
209     assert (file && attr);
210     if (!(file && attr)) return;
211 
212     /* we only care about some things... we will skip most attributes */
213     switch (attr->name)
214     {
215     case attATTACHMODIFYDATE:
216 	copy_date_from_attr (attr, &file->dt);
217 	break;
218 
219     case attATTACHMENT:
220     {
221 	MAPI_Attr **mapi_attrs = mapi_attr_read (attr->len, attr->buf);
222 	if (mapi_attrs)
223 	{
224 	    file_add_mapi_attrs (file, mapi_attrs);
225 	    mapi_attr_free_list (mapi_attrs);
226 	    XFREE (mapi_attrs);
227 	}
228     }
229     break;
230 
231     case attATTACHTITLE:
232 	file->name = strdup( (char*)attr->buf );
233 	break;
234 
235     case attATTACHDATA:
236 	file->len = attr->len;
237 	file->data = CHECKED_XMALLOC(unsigned char, attr->len);
238 	memmove (file->data, attr->buf, attr->len);
239 	break;
240 
241     default:
242 	break;
243     }
244 }
245 
246 void
file_free(File * file)247 file_free (File *file)
248 {
249     if (file)
250     {
251 	XFREE (file->name);
252 	XFREE (file->data);
253 	XFREE (file->mime_type);
254         XFREE (file->content_id);
255         XFREE (file->path);
256 	memset (file, '\0', sizeof (File));
257     }
258 }
259 
260