fixed heap-buffer-overflow in url_count_inline, fixes #122
[smdp.git] / src / url.c
1 /*
2  * Functions necessary to handle pandoc URLs.
3  * Copyright (C) 2016 Michael Goehler
4  *
5  * This file is part of mdp.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21
22 #include <stdlib.h>
23 #include <assert.h>
24 #include <wchar.h>
25 #include <stdio.h>
26
27 #include "url.h"
28
29 static void url_del_elem(url_t *elem);
30 static void url_print(url_t *u);
31
32 static url_t *list;
33 static int index_max;
34 static int init_ok;
35
36 void url_init(void) {
37     list = NULL;
38     index_max = 0;
39     init_ok = 1;
40 }
41
42 int url_add(const wchar_t *link_name, int link_name_length, const wchar_t *target, int target_length, int x, int y) {
43     if (!init_ok) return -1;
44
45     url_t *tmp = NULL;
46     int i = 0;
47
48     if (list) {
49         tmp = list;
50         while (tmp->next) {
51             tmp = tmp->next;
52             i++;
53         }
54         tmp->next = malloc(sizeof(url_t));
55         assert(tmp->next);
56         tmp = tmp->next;
57     } else {
58         list = malloc(sizeof(url_t));
59         tmp = list;
60         assert(tmp);
61     }
62
63     tmp -> link_name = calloc(link_name_length+1, sizeof(wchar_t));
64     assert(tmp->link_name);
65     wcsncpy(tmp->link_name, link_name, link_name_length);
66     tmp->link_name[link_name_length] = '\0';
67
68     tmp->target = calloc(target_length+1, sizeof(wchar_t));
69     assert(tmp->target);
70     wcsncpy(tmp->target, target, target_length);
71     tmp->target[target_length] = '\0';
72
73     tmp->x = x;
74     tmp->y = y;
75     tmp->next = NULL;
76
77     index_max++;
78
79     return index_max-1;
80 }
81
82 wchar_t * url_get_target(int index) {
83     if (!init_ok) return NULL;
84
85     url_t *tmp = list;
86
87     if (!tmp) return NULL;
88
89     while (index > 0 && tmp && tmp->next) {
90         tmp = tmp->next;
91         index--;
92     }
93
94     if (!index) {
95         return tmp->target;
96     } else return NULL;
97 }
98
99 wchar_t * url_get_name(int index) {
100     url_t *tmp = list;
101
102     while (index > 0 && tmp && tmp->next) {
103         tmp = tmp->next;
104         index --;
105     }
106
107     if (!index) {
108         return tmp->link_name;
109     } else return NULL;
110 }
111
112 void url_purge() {
113     url_del_elem(list);
114     list = NULL;
115     index_max = 0;
116     init_ok = 0;
117 }
118
119 static void url_del_elem(url_t *elem) {
120     if (!elem) return;
121
122     if (elem->next) {
123         url_del_elem(elem->next);
124         elem->next = NULL;
125     }
126
127     if (elem->target) {
128         free(elem->target);
129         elem->target = NULL;
130     }
131
132     if (elem->link_name) {
133         free(elem->link_name);
134         elem->link_name = NULL;
135     }
136
137     free(elem);
138 }
139
140 void url_dump(void) {
141     if (!list) return;
142
143     url_t *tmp = list;
144
145     while (tmp) {
146         url_print(tmp);
147         if (tmp->next)
148             tmp = tmp->next;
149         else break;
150     }
151 }
152
153 static void url_print(url_t *u) {
154     printf("url_t @ %p\n", u);
155 }
156
157 int url_get_amount(void) {
158     return index_max;
159 }
160
161 int url_count_inline(const wchar_t *line) {
162     int count = 0;
163     const wchar_t *i = line;
164
165     for (; *i; i++) {
166         if (*i == '\\') {
167             i++;
168         } else if ( *i == '[' && *(i+1) && *(i+1) != ']') {
169             while (*i && *i != ']') i++;
170             i++;
171             if (*i == '(' && wcschr(i, ')')) {
172                 count ++;
173                 i = wcschr(i, ')');
174             }
175         }
176     }
177
178     return count;
179 }
180
181 int url_len_inline(const wchar_t *value) {
182     int count = 0;
183     const wchar_t *i = value;
184
185     for (; *i; i++) {
186         if (*i == '\\') {
187             i++;
188         } else if ( *i == '[' && *(i+1) && *(i+1) != ']') {
189             while (*i && *i != ']') i++;
190             i++;
191             if (*i == '(' && wcschr(i, ')')) {
192                 while (*i && *i != ')') {
193                     count++;
194                     i++;
195                 }
196             }
197         }
198     }
199
200     return count;
201 }