]> err.no Git - sope/blob - sope-appserver/NGObjWeb/NSString+JavaScriptEscaping.m
bumped dyld versions, updated Xcode build to be in sync with latest commits
[sope] / sope-appserver / NGObjWeb / NSString+JavaScriptEscaping.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 <NGObjWeb/NSString+JavaScriptEscaping.h>
23 #include "common.h"
24
25 @implementation NSString(JavascriptEscaping)
26
27 static inline unichar HEX_NIBBLE(unichar v) {
28   return (v > 9) ? (v - 10 + 'a') : (v + '0');
29 }
30
31 - (NSString *)stringByApplyingJavaScriptEscaping {
32   /* Replaces \b, \f, \n, \r, \t, ', " by \-escaped sequences.
33      Replaces non-ASCII characters by either \xXX escape sequences, 
34      when character is in ISOLatin1, or \uXXXX escape sequences.
35      Result string can be used safely as a Javascript string value.
36   */
37   NSString  *javascriptEscapedString = self;
38   unsigned  additionalCharCount = 0;
39   unsigned  length = [self length];
40   int       i, firstEscapedCharIndex = -1, lastEscapedCharIndex = length;
41   
42   for(i = length - 1; i >= 0; i -=1) {
43     unichar aChar = [self characterAtIndex:i];
44     
45     if (aChar > 255) {
46       additionalCharCount += 5; // \uXXXX
47       firstEscapedCharIndex = i;
48     }
49     else if (aChar > 127) {
50       additionalCharCount += 3; // \xXX
51       firstEscapedCharIndex = i;
52     }
53     else if (aChar == '\b' || aChar == '\f' || aChar == '\n' || 
54              aChar == '\r' || 
55              aChar == '\t' || aChar == '\'' || aChar == '"' || aChar == '\\') {
56       additionalCharCount += 1;
57       firstEscapedCharIndex = i;
58     }
59     if (lastEscapedCharIndex == length && additionalCharCount != 0)
60       lastEscapedCharIndex = i;
61   }
62   
63   if (additionalCharCount > 0) {
64     unsigned  newLength = length + additionalCharCount;
65     unichar   *newChars = NSZoneMalloc(NSDefaultMallocZone(), 
66                             sizeof(unichar) * newLength);
67     unsigned  offset = 0;
68     
69     [self getCharacters:newChars range:NSMakeRange(0, firstEscapedCharIndex)];
70     for(i = firstEscapedCharIndex; i <= lastEscapedCharIndex; i += 1) {
71       unichar aChar = [self characterAtIndex:i];
72       
73       if (aChar > 255) {
74         newChars[i + offset] = '\\';
75         newChars[i + offset + 1] = 'u';
76         newChars[i + offset + 2] = HEX_NIBBLE((aChar >> 12) & 0x0F);
77         newChars[i + offset + 3] = HEX_NIBBLE((aChar >> 8)  & 0x0F);
78         newChars[i + offset + 4] = HEX_NIBBLE((aChar >> 4)  & 0x0F);
79         newChars[i + offset + 5] = HEX_NIBBLE( aChar        & 0x0F);
80         offset += 5;
81       }
82       else if (aChar > 127) {
83         newChars[i + offset] = '\\';
84         newChars[i + offset + 1] = 'x';
85         newChars[i + offset + 2] = HEX_NIBBLE((aChar >> 4)  & 0x0F);
86         newChars[i + offset + 3] = HEX_NIBBLE( aChar        & 0x0F);
87         offset += 3;
88       }
89       else if (aChar == '\b') {
90         newChars[i + offset] = '\\';
91         newChars[i + offset + 1] = 'b';
92         offset += 1;
93       }
94       else if (aChar == '\f') {
95         newChars[i + offset] = '\\';
96         newChars[i + offset + 1] = 'f';
97         offset += 1;
98       }
99       else if (aChar == '\n') {
100         newChars[i + offset] = '\\';
101         newChars[i + offset + 1] = 'n';
102         offset += 1;
103       }
104       else if (aChar == '\r') {
105         newChars[i + offset] = '\\';
106         newChars[i + offset + 1] = 'r';
107         offset += 1;
108       }
109       else if (aChar == '\t') {
110         newChars[i + offset] = '\\';
111         newChars[i + offset + 1] = 't';
112         offset += 1;
113       }
114       else if (aChar == '\'') {
115         newChars[i + offset] = '\\';
116         newChars[i + offset + 1] = '\'';
117         offset += 1;
118       }
119       else if (aChar == '"') {
120         newChars[i + offset] = '\\';
121         newChars[i + offset + 1] = '"';
122         offset += 1;
123       }
124       else if (aChar == '\\') {
125         newChars[i + offset] = '\\';
126         newChars[i + offset + 1] = '\\';
127         offset += 1;
128       }
129       else
130         newChars[i + offset] = aChar;
131     }
132     if (lastEscapedCharIndex < length)
133       [self getCharacters:(newChars + offset + lastEscapedCharIndex + 1) 
134               range:NSMakeRange(lastEscapedCharIndex + 1, 
135                       length - lastEscapedCharIndex - 1)];
136     javascriptEscapedString = [NSString stringWithCharacters:newChars 
137                                           length:newLength];
138   }
139   
140   return javascriptEscapedString;
141 }
142
143 @end /* NSString(JavascriptEscaping) */