Elementary util: Fix possible invalid read in _elm_util_mkup_to_text.
[framework/uifw/elementary.git] / src / lib / elm_util.c
1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4 #include <Elementary.h>
5 #include "elm_priv.h"
6
7 static char *
8 _str_ncpy(char *dest, const char *src, size_t count)
9 {
10    if ((!dest) || (!src)) return NULL;
11    return strncpy(dest, src, count);
12 }
13
14 static char *
15 _str_append(char *str, const char *txt, int *len, int *alloc)
16 {
17    int txt_len = strlen(txt);
18
19    if (txt_len <= 0) return str;
20    if ((*len + txt_len) >= *alloc)
21      {
22         char *str2;
23         int alloc2;
24
25         alloc2 = *alloc + txt_len + 128;
26         str2 = realloc(str, alloc2);
27         if (!str2) return str;
28         *alloc = alloc2;
29         str = str2;
30      }
31    strcpy(str + *len, txt);
32    *len += txt_len;
33    return str;
34 }
35
36 char *
37 _elm_util_mkup_to_text(const char *mkup)
38 {
39    char *str = NULL;
40    int str_len = 0, str_alloc = 0;
41    char *s, *p;
42    char *tag_start, *tag_end, *esc_start, *esc_end, *ts;
43
44    if (!mkup) return NULL;
45    tag_start = tag_end = esc_start = esc_end = NULL;
46    p = (char *)mkup;
47    s = p;
48    for (;;)
49      {
50         if ((!*p) ||
51             (tag_end) || (esc_end) ||
52             (tag_start) || (esc_start))
53           {
54              if (tag_end)
55                {
56                   char *ttag;
57
58                   ttag = malloc(tag_end - tag_start);
59                   if (ttag)
60                     {
61                        _str_ncpy(ttag, tag_start + 1, tag_end - tag_start - 1);
62                        ttag[tag_end - tag_start - 1] = 0;
63                        if (!strcmp(ttag, "br"))
64                          str = _str_append(str, "\n", &str_len, &str_alloc);
65                        else if (!strcmp(ttag, "\n"))
66                          str = _str_append(str, "\n", &str_len, &str_alloc);
67                        else if (!strcmp(ttag, "\\n"))
68                          str = _str_append(str, "\n", &str_len, &str_alloc);
69                        else if (!strcmp(ttag, "\t"))
70                          str = _str_append(str, "\t", &str_len, &str_alloc);
71                        else if (!strcmp(ttag, "\\t"))
72                          str = _str_append(str, "\t", &str_len, &str_alloc);
73                        else if (!strcmp(ttag, "ps")) /* Unicode paragraph separator */
74                          str = _str_append(str, "\xE2\x80\xA9", &str_len, &str_alloc);
75                        free(ttag);
76                     }
77                   tag_start = tag_end = NULL;
78                }
79              else if (esc_end)
80                {
81                   ts = malloc(esc_end - esc_start + 1);
82                   if (ts)
83                     {
84                        const char *esc;
85                        _str_ncpy(ts, esc_start, esc_end - esc_start);
86                        ts[esc_end - esc_start] = 0;
87                        esc = evas_textblock_escape_string_get(ts);
88                        if (esc)
89                          str = _str_append(str, esc, &str_len, &str_alloc);
90                        free(ts);
91                     }
92                   esc_start = esc_end = NULL;
93                }
94              else if ((!*p) && (s))
95                {
96                   ts = malloc(p - s + 1);
97                   if (ts)
98                     {
99                        _str_ncpy(ts, s, p - s);
100                        ts[p - s] = 0;
101                        str = _str_append(str, ts, &str_len, &str_alloc);
102                        free(ts);
103                     }
104                }
105
106              if (!*p) break;
107           }
108         if (*p == '<')
109           {
110              if ((s) && (!esc_start))
111                {
112                   tag_start = p;
113                   tag_end = NULL;
114                   ts = malloc(p - s + 1);
115                   if (ts)
116                     {
117                        _str_ncpy(ts, s, p - s);
118                        ts[p - s] = 0;
119                        str = _str_append(str, ts, &str_len, &str_alloc);
120                        free(ts);
121                     }
122                   s = NULL;
123                }
124           }
125         else if (*p == '>')
126           {
127              if (tag_start)
128                {
129                   tag_end = p;
130                   s = p + 1;
131                }
132           }
133         else if (*p == '&')
134           {
135              if ((s) && (!tag_start))
136                {
137                   esc_start = p;
138                   esc_end = NULL;
139                   ts = malloc(p - s + 1);
140                   if (ts)
141                     {
142                        _str_ncpy(ts, s, p - s);
143                        ts[p - s] = 0;
144                        str = _str_append(str, ts, &str_len, &str_alloc);
145                        free(ts);
146                     }
147                   s = NULL;
148                }
149           }
150         else if (*p == ';')
151           {
152              if (esc_start)
153                {
154                   esc_end = p;
155                   s = p + 1;
156                }
157           }
158         p++;
159      }
160    return str;
161 }
162
163 char *
164 _elm_util_text_to_mkup(const char *text)
165 {
166    char *str = NULL;
167    int str_len = 0, str_alloc = 0;
168    int ch, pos = 0, pos2 = 0;
169
170    if (!text) return NULL;
171    for (;;)
172      {
173         pos = pos2;
174         pos2 = evas_string_char_next_get((char *)(text), pos2, &ch);
175         if ((ch <= 0) || (pos2 <= 0)) break;
176         if (ch == '\n')
177           str = _str_append(str, "<br>", &str_len, &str_alloc);
178         else if (ch == '\t')
179           str = _str_append(str, "<\t>", &str_len, &str_alloc);
180         else if (ch == '<')
181           str = _str_append(str, "&lt;", &str_len, &str_alloc);
182         else if (ch == '>')
183           str = _str_append(str, "&gt;", &str_len, &str_alloc);
184         else if (ch == '&')
185           str = _str_append(str, "&amp;", &str_len, &str_alloc);
186         else if (ch == 0x2029) /* PS */
187           str = _str_append(str, "<ps>", &str_len, &str_alloc);
188         else
189           {
190              char tstr[16];
191
192              _str_ncpy(tstr, text + pos, pos2 - pos);
193              tstr[pos2 - pos] = 0;
194              str = _str_append(str, tstr, &str_len, &str_alloc);
195           }
196      }
197    return str;
198 }