1 /*****************************************************************************/
2 /* LibreDWG - free implementation of the DWG file format */
3 /* */
4 /* Copyright (C) 2019,2023 Free Software Foundation, Inc. */
5 /* */
6 /* This library is free software, licensed under the terms of the GNU */
7 /* General Public License as published by the Free Software Foundation, */
8 /* either version 3 of the License, or (at your option) any later version. */
9 /* You should have received a copy of the GNU General Public License */
10 /* along with this program. If not, see <http://www.gnu.org/licenses/>. */
11 /*****************************************************************************/
12
13 /*
14 * escape.c: SVG helpers
15 * written by Reini Urban
16 */
17
18 #include "config.h"
19 #include <string.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22
23 #include "common.h"
24 #include "escape.h"
25
26 char *ATTRIBUTE_MALLOC
27 htmlescape (const char *restrict src, const Dwg_Codepage cp)
28 {
29 size_t len;
30 char *dest, *d, *end;
31 unsigned char *s;
32 if (!src)
33 return NULL;
34 len = strlen (src) + 10;
35 d = (char *)calloc (len, 1);
36 s = (unsigned char *)src;
37 dest = d;
38 end = dest + len;
39 while (*s)
40 {
41 if (end - d <= 8)
42 {
43 const int off = d - dest;
44 char *newdest = (char *)realloc (dest, len + 10);
45 if (!newdest)
46 return NULL;
47 dest = newdest;
48 len += 10;
49 d = dest + off;
50 *d = 0;
51 end = dest + len;
52 }
53 switch (*s)
54 {
55 case '"':
56 strcat (d, """);
57 d += 6;
58 break;
59 case '\'':
60 strcat (d, "'");
61 d += 5;
62 break;
63 case '`':
64 strcat (d, "`");
65 d += 5;
66 break;
67 case '&':
68 strcat (d, "&");
69 d += 5;
70 break;
71 case '<':
72 strcat (d, "<");
73 d += 4;
74 break;
75 case '>':
76 strcat (d, ">");
77 d += 4;
78 break;
79 case '{':
80 strcat (d, "{");
81 d += 6;
82 break;
83 case '}':
84 strcat (d, "}");
85 d += 6;
86 break;
87 default:
88 {
89 uint16_t cc = *s;
90 wchar_t wc;
91 if (dwg_codepage_is_twobyte (cp, *s))
92 cc = cc << 8 | *++s;
93 wc = dwg_codepage_uwc (cp, cc);
94 if (wc > 127 || wc < 0x20)
95 {
96 sprintf (d, "&#x%X;", (unsigned)wc); // 4 + 4
97 d += strlen (d);
98 }
99 else
100 {
101 *d++ = *s;
102 }
103 *d = 0;
104 }
105 }
106 s++;
107 }
108 *d = 0;
109 return dest;
110 }
111
112 char *ATTRIBUTE_MALLOC
113 htmlwescape (BITCODE_TU wstr)
114 {
115 int len = 0;
116 char *dest, *d;
117 BITCODE_TU tmp = wstr;
118 BITCODE_RS c;
119
120 if (!wstr)
121 return NULL;
122 while ((c = *tmp++))
123 len++;
124 len += 16;
125 d = dest = (char *)calloc (len, 1);
126
127 while (*wstr)
128 {
129 const int off = d - dest;
130 if (off >= len - 8)
131 {
132 char *newdest = (char *)realloc (dest, len + 16);
133 if (!newdest)
134 return NULL;
135 dest = newdest;
136 len += 16;
137 d = dest + off;
138 *d = 0;
139 }
140 switch (*wstr)
141 {
142 case 34:
143 strcat (d, """);
144 d += 6;
145 break;
146 case 39:
147 strcat (d, "'");
148 d += 5;
149 break;
150 case 38:
151 strcat (d, "&");
152 d += 5;
153 break;
154 case 60:
155 strcat (d, "<");
156 d += 4;
157 break;
158 case 62:
159 strcat (d, ">");
160 d += 4;
161 break;
162 case 96:
163 strcat (d, "`");
164 d += 5;
165 break;
166 case 123:
167 strcat (d, "{");
168 d += 6;
169 break;
170 case 125:
171 strcat (d, "}");
172 d += 6;
173 break;
174 default:
175 if (*wstr >= 127 || *wstr < 20) // utf8 encodings
176 {
177 sprintf (d, "&#x%X;", *wstr);
178 d += strlen (d);
179 *d = 0;
180 }
181 else
182 {
183 *d++ = *wstr;
184 *d = 0;
185 }
186 }
187 wstr++;
188 }
189 *d = 0;
190 return dest;
191 }