]> err.no Git - sope/blob - sope-mime/NGMime/NGMimeUtilities.m
bumped framework versions
[sope] / sope-mime / NGMime / NGMimeUtilities.m
1 /*
2   Copyright (C) 2000-2005 SKYRIX Software AG
3
4   This file is part of SOPE.
5
6   SOPE is free software; you can redistribute it and/or modify it under
7   the terms of the GNU Lesser General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
12   WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14   License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with SOPE; see the file COPYING.  If not, write to the
18   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.
20 */
21
22 #include <NGMime/NGMimeType.h>
23 #include <NGMime/NGMimeUtilities.h>
24
25 typedef struct {
26   NSString *charset;
27   NSString *q;
28   NSString *boundary;
29   NSString *name;
30   NSString *fileName;
31   NSString *reportType;
32 } NGMimeParameterConstants;
33
34 static NGMimeParameterConstants *MimeParameterConstants = NULL;
35 static Class                    NSStringClass           = Nil;
36 static int                      MimeLogEnabled          = -1;
37
38 static NSString *_stringForParameterName(char *_type, int _len) {
39   if (NSStringClass == Nil)
40     NSStringClass = [NSString class];
41
42   if (MimeLogEnabled == -1) {
43     MimeLogEnabled = [[NSUserDefaults standardUserDefaults]
44                                       boolForKey:@"MimeLogEnabled"]?1:0;
45   }
46
47   if (MimeParameterConstants == NULL) {
48     MimeParameterConstants = malloc(sizeof(NGMimeParameterConstants));
49
50     MimeParameterConstants->charset    = NGMimeParameterTextCharset;
51     MimeParameterConstants->q          = @"q";
52     MimeParameterConstants->name       = @"name";
53     MimeParameterConstants->boundary   = @"boundary";
54     MimeParameterConstants->fileName   = @"filename";
55     MimeParameterConstants->reportType = @"report-type";
56   }
57   switch (_len) {
58     case 0:
59       return @"";
60     case 1:
61       if (_type[0] == 'q')
62         return MimeParameterConstants->q;
63       break;
64     case 4:
65       if (strncmp(_type, "name", 4) == 0) 
66         return MimeParameterConstants->name;
67       break;
68     case 7:
69       if (strncmp(_type, "charset", 7) == 0) 
70         return MimeParameterConstants->charset;
71       break;
72     case 8:
73       if (strncmp(_type, "boundary", 8) == 0) 
74           return MimeParameterConstants->boundary;
75       if (strncmp(_type, "filename", 8) == 0) 
76           return MimeParameterConstants->fileName;
77       break;
78     case 11:
79       if (strncmp(_type, "report-type", 11) == 0) 
80           return MimeParameterConstants->reportType;
81       break;
82   }
83   return [NSStringClass stringWithCString:_type length:_len];
84 }
85
86 NSDictionary *parseParameters(id self, NSString *_str, unichar *cstr) {
87   if (*cstr != '\0') {
88     NSMutableDictionary *paras;
89
90     paras = [[NSMutableDictionary alloc] initWithCapacity:8];
91     do {
92       unsigned len;
93       unichar  *tmp;
94       NSString *attrName, *attrValue;
95
96       attrValue = nil;
97       attrName  = nil;
98
99       // consume end of previous entry (spaces and ';')
100       while ((*cstr == ';') || isRfc822_LWSP(*cstr))
101         cstr++;
102
103       // parse attribute
104       tmp = cstr;
105       len = 0;
106       while ((*cstr != '\0') && (isMime_ValidTypeAttributeChar(*cstr))) {
107         cstr++;
108         len++;
109       }
110       if (len == 0)
111         break;
112       {
113         unsigned char     buf[len + 1];
114         register unsigned i;
115
116         buf[len] = '\0';
117         for (i = 0; i < len; i++) buf[i] = tolower(tmp[i]);
118
119         attrName = _stringForParameterName((char *)buf, len);
120       }
121       // skip spaces
122       while ((*cstr != '\0') && (isRfc822_LWSP(*cstr))) {
123         cstr++;
124       }
125       // no value was given for attribute
126       if (*cstr == '\0') {
127         if (MimeLogEnabled)
128           [self logWithFormat:@"WARNING(%s): attribute '%@' has no value in "
129                 @"MimeType '%@'", __PRETTY_FUNCTION__, attrName, _str];
130         break; // exit loop
131       }
132
133       // expect '='
134       if (*cstr != '=') {
135         if (MimeLogEnabled) 
136           [self logWithFormat:@"WARNING(%s): attribute '%@', missing '=' "
137                 @"in MimeType '%@'", __PRETTY_FUNCTION__, attrName, _str];
138         break; // exit loop
139       }
140       cstr++;
141
142       // skip spaces
143       while ((*cstr != '\0') && (isRfc822_LWSP(*cstr)))
144         cstr++;
145       
146       /* no value was given for parameter */
147       if (*cstr == '\0') {
148         if (MimeLogEnabled) 
149           [self logWithFormat:@"WARNING(%s): attribute '%@' has no value "
150                 @"in MimeType '%@'", __PRETTY_FUNCTION__, attrName, _str];
151         break; // exit loop
152       }
153       
154       /* now parameter read value */
155       if (isRfc822_QUOTE(*cstr)) { // quoted value
156         cstr++;
157         tmp = cstr;
158         len = 0;
159         while (!isRfc822_QUOTE(*cstr) && (*cstr != '\0')) {
160           cstr++;
161           len++;
162         }
163         attrValue = [[[NSString alloc] initWithCharacters:tmp length:len]
164                                 autorelease];
165           
166         if (*cstr == '\0') { // quote was not closed
167           if (MimeLogEnabled)  
168             [self logWithFormat:@"WARNING(%s): value-quotes in attribute "
169                   @"'%@' were not closed in MimeType '%@'",
170                   __PRETTY_FUNCTION__, attrName, _str];
171           break; // exit loop
172         }
173         cstr++; // skip closing quote
174       }
175       else { /* value without quotes */
176         tmp = cstr;
177         len = 0;
178
179         while (*cstr != '\0') {
180           if (isRfc822_SPACE(*cstr)) break;
181           if (isRfc822_CTL(*cstr))   break;
182             
183           if (*cstr == ';') break; /* parameter separator */
184             
185           cstr++;
186           len++;
187         }
188         attrValue = [[[NSString alloc] initWithCharacters:tmp length:len]
189                                 autorelease];
190       }
191       /* store attr/value pair in dictionary */
192       [paras setObject:attrValue forKey:attrName];
193       attrName  = nil;
194       attrValue = nil;
195
196       /* skip spaces */
197       while ((*cstr != '\0') && (isRfc822_LWSP(*cstr)))
198         cstr++;
199
200       if (*cstr == ';') // skip ';' (attribute separator)
201         cstr++;
202       else if (*cstr == '\0') /* parsing is finished, exit loop */
203         break; // exit loop
204       else {
205         if (MimeLogEnabled) 
206           [self logWithFormat:@"WARNING(%s): expected end of string or ';', "
207                 @"got '%c'%i (str='%@')", __PRETTY_FUNCTION__, *cstr,
208                 *cstr, _str];
209         break; // exit loop
210       }
211       /* skip spaces */
212       while ((*cstr != '\0') && (isRfc822_LWSP(*cstr)))
213         cstr++;
214     }
215     while (YES);
216     return [paras autorelease];
217   }
218   return nil;
219 }
220
221