Mercurial > ~mikael > mcabber > hg
comparison mcabber/src/histolog.c @ 1436:6fb141142388
Improve reading of history files
Handle larger messages in history log files.
author | Mikael Berthe <mikael@lilotux.net> |
---|---|
date | Sun, 24 Feb 2008 17:46:13 +0100 |
parents | 366ef500c522 |
children | 071c8170b7de |
comparison
equal
deleted
inserted
replaced
1435:9bf7f3ddff10 | 1436:6fb141142388 |
---|---|
155 void hlog_read_history(const char *bjid, GList **p_buddyhbuf, guint width) | 155 void hlog_read_history(const char *bjid, GList **p_buddyhbuf, guint width) |
156 { | 156 { |
157 char *filename; | 157 char *filename; |
158 guchar type, info; | 158 guchar type, info; |
159 char *data, *tail; | 159 char *data, *tail; |
160 guint data_size; | |
160 char *xtext; | 161 char *xtext; |
161 time_t timestamp; | 162 time_t timestamp; |
162 guint prefix_flags; | 163 guint prefix_flags; |
163 guint len; | 164 guint len; |
164 FILE *fp; | 165 FILE *fp; |
173 | 174 |
174 if ((roster_gettype(bjid) & ROSTER_TYPE_ROOM) && | 175 if ((roster_gettype(bjid) & ROSTER_TYPE_ROOM) && |
175 (settings_opt_get_int("load_muc_logs") != 1)) | 176 (settings_opt_get_int("load_muc_logs") != 1)) |
176 return; | 177 return; |
177 | 178 |
178 data = g_new(char, HBB_BLOCKSIZE+32); | 179 data_size = HBB_BLOCKSIZE+32; |
180 data = g_new(char, data_size); | |
179 if (!data) { | 181 if (!data) { |
180 scr_LogPrint(LPRINT_LOGNORM, "Not enough memory to read history file"); | 182 scr_LogPrint(LPRINT_LOGNORM, "Not enough memory to read history file"); |
181 return; | 183 return; |
182 } | 184 } |
183 | 185 |
212 } | 214 } |
213 | 215 |
214 /* See write_histo_line() for line format... */ | 216 /* See write_histo_line() for line format... */ |
215 while (!feof(fp)) { | 217 while (!feof(fp)) { |
216 guint dataoffset = 25; | 218 guint dataoffset = 25; |
217 | 219 guint noeol; |
218 if (fgets(data, HBB_BLOCKSIZE+27, fp) == NULL) | 220 |
221 if (fgets(data, data_size-1, fp) == NULL) | |
219 break; | 222 break; |
220 ln++; | 223 ln++; |
221 | 224 |
222 for (tail = data; *tail; tail++) ; | 225 while (1) { |
226 for (tail = data; *tail; tail++) ; | |
227 noeol = (*(tail-1) != '\n'); | |
228 if (!noeol) | |
229 break; | |
230 /* TODO: duplicated code... could do better... */ | |
231 if (tail == data + data_size-2) { | |
232 // The buffer is too small to contain the whole line. | |
233 // Let's allocate some more space. | |
234 if (!max_num_of_blocks || | |
235 data_size/HBB_BLOCKSIZE < 5U*max_num_of_blocks) { | |
236 guint toffset = tail - data; | |
237 // Allocate one more block. | |
238 data_size = HBB_BLOCKSIZE * (1 + data_size/HBB_BLOCKSIZE); | |
239 data = g_renew(char, data, data_size); | |
240 // Update the tail pointer, as the data may have been moved. | |
241 tail = data + toffset; | |
242 if (fgets(tail, data_size-1 - (tail-data), fp) == NULL) | |
243 break; | |
244 } else { | |
245 scr_LogPrint(LPRINT_LOGNORM, "Line too long in history file!"); | |
246 ln--; | |
247 break; | |
248 } | |
249 } | |
250 } | |
223 | 251 |
224 type = data[0]; | 252 type = data[0]; |
225 info = data[1]; | 253 info = data[1]; |
226 | 254 |
227 if ((type != 'M' && type != 'S') || | 255 if ((type != 'M' && type != 'S') || |
250 err = 1; | 278 err = 1; |
251 } | 279 } |
252 continue; | 280 continue; |
253 } | 281 } |
254 | 282 |
255 // XXX This will fail when a message is too big | |
256 while (len--) { | 283 while (len--) { |
257 ln++; | 284 ln++; |
258 if (fgets(tail, HBB_BLOCKSIZE+27 - (tail-data), fp) == NULL) | 285 if (fgets(tail, data_size-1 - (tail-data), fp) == NULL) |
259 break; | 286 break; |
260 | 287 |
261 while (*tail) tail++; | 288 while (*tail) tail++; |
262 } | 289 noeol = (*(tail-1) != '\n'); |
263 // Small check for too long messages | 290 if (tail == data + data_size-2 && (len || noeol)) { |
264 if (tail >= HBB_BLOCKSIZE+dataoffset+1 + data) { | 291 // The buffer is too small to contain the whole message. |
265 // Maybe we will have a parse error on next, because this | 292 // Let's allocate some more space. |
266 // message is big (maybe too big). | 293 if (!max_num_of_blocks || |
267 scr_LogPrint(LPRINT_LOGNORM, "A message could be too big " | 294 data_size/HBB_BLOCKSIZE < 5U*max_num_of_blocks) { |
268 "in history file..."); | 295 guint toffset = tail - data; |
296 // If the line hasn't been read completely and we reallocate the | |
297 // buffer, we want to read one more time. | |
298 if (noeol) | |
299 len++; | |
300 // Allocate one more block. | |
301 data_size = HBB_BLOCKSIZE * (1 + data_size/HBB_BLOCKSIZE); | |
302 data = g_renew(char, data, data_size); | |
303 // Update the tail pointer, as the data may have been moved. | |
304 tail = data + toffset; | |
305 } else { | |
306 // There will probably be a parse error on next read, because | |
307 // this message hasn't been read entirely. | |
308 scr_LogPrint(LPRINT_LOGNORM, "Message too big in history file!"); | |
309 } | |
310 } | |
269 } | 311 } |
270 // Remove last CR (we keep it if the line is empty, too) | 312 // Remove last CR (we keep it if the line is empty, too) |
271 if ((tail > data+dataoffset+1) && (*(tail-1) == '\n')) | 313 if ((tail > data+dataoffset+1) && (*(tail-1) == '\n')) |
272 *(tail-1) = 0; | 314 *(tail-1) = 0; |
273 | 315 |