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