]> err.no Git - sope/blob - sope-core/NGExtensions/FdExt.subproj/NSString+HTMLEscaping.m
fixed gcc 4.0 warnings
[sope] / sope-core / NGExtensions / FdExt.subproj / NSString+HTMLEscaping.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 "NSString+misc.h"
23 #include "common.h"
24
25 @implementation NSString(HTMLEscaping)
26
27 - (NSString *)stringByEscapingHTMLStringUsingCharacters {
28   register unsigned i, len, j;
29   register unichar  *chars, *buf;
30   unsigned escapeCount;
31   
32   if ((len = [self length]) == 0) return @"";
33   
34   chars = malloc((len + 3) * sizeof(unichar));
35   [self getCharacters:chars];
36   
37   /* check for characters to escape ... */
38   for (i = 0, escapeCount = 0; i < len; i++) {
39     switch (chars[i]) {
40       case '&': case '"': case '<': case '>':
41         escapeCount++;
42         break;
43       default:
44         if (chars[i] > 127)
45           escapeCount++;
46         break;
47     }
48   }
49   if (escapeCount == 0 ) {
50     /* nothing to escape ... */
51     if (chars) free(chars);
52     return [[self copy] autorelease];
53   }
54   
55   buf = calloc((len + 5) + (escapeCount * 8), sizeof(unichar));
56   for (i = 0, j = 0; i < len; i++) {
57     switch (chars[i]) {
58       /* escape special chars */
59       case '&':
60         buf[j] = '&'; j++; buf[j] = 'a'; j++; buf[j] = 'm'; j++;
61         buf[j] = 'p'; j++; buf[j] = ';'; j++;
62         break;
63       case '"':
64         buf[j] = '&'; j++; buf[j] = 'q'; j++; buf[j] = 'u'; j++;
65         buf[j] = 'o'; j++; buf[j] = 't'; j++; buf[j] = ';'; j++;
66         break;
67       case '<':
68         buf[j] = '&'; j++; buf[j] = 'l'; j++; buf[j] = 't'; j++;
69         buf[j] = ';'; j++;
70         break;
71       case '>':
72         buf[j] = '&'; j++; buf[j] = 'g'; j++; buf[j] = 't'; j++;
73         buf[j] = ';'; j++;
74         break;
75       case 223: /* &szlig; */
76         buf[j] = '&'; j++; buf[j] = 's'; j++; buf[j] = 'z'; j++;
77         buf[j] = 'l'; j++; buf[j] = 'i'; j++; buf[j] = 'g'; j++;
78         buf[j] = ';'; j++;
79         break;
80         // TODO: this is missing a LOT?
81       case 252: /* &uuml; */
82         buf[j] = '&'; j++; buf[j] = 'u'; j++; buf[j] = 'u'; j++;
83         buf[j] = 'm'; j++; buf[j] = 'l'; j++; buf[j] = ';'; j++;
84         break;
85       case 220: /* &Uuml; */
86         buf[j] = '&'; j++; buf[j] = 'U'; j++; buf[j] = 'u'; j++;
87         buf[j] = 'm'; j++; buf[j] = 'l'; j++; buf[j] = ';'; j++;
88         break;
89       case 228: /* &auml; */
90         buf[j] = '&'; j++; buf[j] = 'a'; j++; buf[j] = 'u'; j++;
91         buf[j] = 'm'; j++; buf[j] = 'l'; j++; buf[j] = ';'; j++;
92         break;
93       case 196: /* &Auml; */
94         buf[j] = '&'; j++; buf[j] = 'A'; j++; buf[j] = 'u'; j++;
95         buf[j] = 'm'; j++; buf[j] = 'l'; j++; buf[j] = ';'; j++;
96         break;
97       case 246: /* &ouml; */
98         buf[j] = '&'; j++; buf[j] = 'o'; j++; buf[j] = 'u'; j++;
99         buf[j] = 'm'; j++; buf[j] = 'l'; j++; buf[j] = ';'; j++;
100         break;
101       case 214: /* &Ouml; */
102         buf[j] = '&'; j++; buf[j] = 'O'; j++; buf[j] = 'u'; j++;
103         buf[j] = 'm'; j++; buf[j] = 'l'; j++; buf[j] = ';'; j++;
104         break;
105         
106       default:
107         /* escape big chars */
108         if (chars[i] > 127) {
109           unsigned char nbuf[16];
110           unsigned int k;
111           
112           sprintf((char *)nbuf, "&#%i;", (int)chars[i]);
113           for (k = 0; nbuf[k] != '\0'; k++) {
114             buf[j] = nbuf[k];
115             j++;
116           }
117         }
118         else {
119           /* nothing to escape */
120           buf[j] = chars[i];
121           j++;
122         }
123         break;
124     }
125   }
126   
127   self = [NSString stringWithCharacters:buf length:j];
128   
129   if (chars) free(chars);
130   if (buf)   free(buf);
131   return self;
132 }
133
134 - (NSString *)stringByEscapingHTMLAttributeValueUsingCharacters {
135   register unsigned i, len, j;
136   register unichar  *chars, *buf;
137   unsigned escapeCount;
138   
139   if ((len = [self length]) == 0) return @"";
140   
141   chars = malloc((len + 3) * sizeof(unichar));
142   [self getCharacters:chars];
143   
144   /* check for characters to escape ... */
145   for (i = 0, escapeCount = 0; i < len; i++) {
146     switch (chars[i]) {
147       case '&':
148       case '"':
149       case '<':
150       case '>':
151       case '\t':
152       case '\n':
153       case '\r':
154         escapeCount++;
155         break;
156       default:
157         if (chars[i] > 127)
158           escapeCount++;
159         break;
160     }
161   }
162   if (escapeCount == 0 ) {
163     /* nothing to escape ... */
164     if (chars) free(chars);
165     return [[self copy] autorelease];
166   }
167   
168   buf = calloc((len + 3) + (escapeCount * 8), sizeof(unichar));
169   for (i = 0, j = 0; i < len; i++) {
170     switch (chars[i]) {
171       /* escape special chars */
172       case '&':
173         buf[j] = '&'; j++; buf[j] = 'a'; j++; buf[j] = 'm'; j++;
174         buf[j] = 'p'; j++; buf[j] = ';'; j++;
175         break;
176       case '"':
177         buf[j] = '&'; j++; buf[j] = 'q'; j++; buf[j] = 'u'; j++;
178         buf[j] = 'o'; j++; buf[j] = 't'; j++; buf[j] = ';'; j++;
179         break;
180       case '<':
181         buf[j] = '&'; j++; buf[j] = 'l'; j++; buf[j] = 't'; j++;
182         buf[j] = ';'; j++;
183         break;
184       case '>':
185         buf[j] = '&'; j++; buf[j] = 'g'; j++; buf[j] = 't'; j++;
186         buf[j] = ';'; j++;
187         break;
188         
189       case '\t':
190         buf[j] = '&'; j++; buf[j] = '#'; j++; buf[j] = '9'; j++;
191         buf[j] = ';'; j++;
192         break;
193       case '\n':
194         buf[j] = '&'; j++; buf[j] = '#'; j++; buf[j] = '1'; j++;
195         buf[j] = '0'; j++; buf[j] = ';'; j++;
196         break;
197       case '\r':
198         buf[j] = '&'; j++; buf[j] = '#'; j++; buf[j] = '1'; j++;
199         buf[j] = '3'; j++; buf[j] = ';'; j++;
200         break;
201         
202       default:
203         /* escape big chars */
204         if (chars[i] > 127) {
205           unsigned char nbuf[16];
206           unsigned int k;
207           
208           sprintf((char *)nbuf, "&#%i;", (int)chars[i]);
209           for (k = 0; nbuf[k] != '\0'; k++) {
210             buf[j] = nbuf[k];
211             j++;
212           }
213         }
214         else {
215           /* nothing to escape */
216           buf[j] = chars[i]; j++;
217         }
218         break;
219     }
220   }
221   
222   self = [NSString stringWithCharacters:buf length:j];
223   
224   if (chars) free(chars);
225   if (buf)   free(buf);
226   return self;
227 }
228
229 - (NSString *)stringByEscapingHTMLString {
230   return [self stringByEscapingHTMLStringUsingCharacters];
231 }
232 - (NSString *)stringByEscapingHTMLAttributeValue {
233   return [self stringByEscapingHTMLAttributeValueUsingCharacters];
234 }
235
236 @end /* NSString(HTMLEscaping) */