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