]> git.ipfire.org Git - thirdparty/sarg.git/blob - grepday.c
Use one function to parse the lines from sarg-general instead of multiple codes scatt...
[thirdparty/sarg.git] / grepday.c
1 /*
2 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
3 * 1998, 2010
4 *
5 * SARG donations:
6 * please look at http://sarg.sourceforge.net/donations.php
7 * Support:
8 * http://sourceforge.net/projects/sarg/forums/forum/363374
9 * ---------------------------------------------------------------------
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
24 *
25 */
26
27 #include "include/conf.h"
28 #include "include/defs.h"
29
30 #if defined(HAVE_GD)
31
32 static int blue;
33 static int white;
34 static int lavender;
35 static int darkblue;
36 static int dimgray;
37 static int goldenrod;
38 static int goldenrod2;
39 static int gray;
40 static int silver;
41 static int black;
42
43 #if defined(HAVE_ICONV_H) && defined(gdFTEX_Unicode)
44 #include <iconv.h>
45 #define SARGgdImageStringFT I18NgdImageStringFT
46
47 static char * I18NgdImageStringFT (gdImage * im, int *brect, int fg, char *fontlist,
48 double ptsize, double angle, int x, int y, char *string)
49 {
50 iconv_t localtoutf;
51 char *sstring, *str, *sstr, *retval;
52 size_t slen, sslen;
53
54 slen = strlen(string) + 1; // We must include string termination character
55 sslen = slen * 2; // We assume that UTF8 maximum 2 times large than local
56 sstring = (char *)malloc(sslen);
57 if (!sstring) {
58 fprintf(stderr, "SARG: %s (%zu):\n",text[59],sslen);
59 exit(1);
60 }
61
62 str = (char *) string;
63 sstr = (char *) sstring;
64
65 localtoutf = iconv_open ("UTF-8", CharSet);
66 if (localtoutf==(iconv_t)-1) {
67 fprintf(stderr,"SARG(grepday) iconv cannot convert from %s to UTF-8 - %s\n",CharSet,strerror(errno));
68 strcpy(sstring,string); //show something sensible on the graph
69 }
70 else {
71 if (iconv (localtoutf, (ICONV_CONST char **)&str, &slen, &sstr, &sslen)==-1) {
72 fprintf(stderr,"SARG(grepday) iconv failed to convert string \"%s\" from %s to UTF-8 - %s\n",string,CharSet,strerror(errno));
73 strcpy(sstring,string); //show something sensible on the graph
74 }
75 iconv_close (localtoutf);
76 }
77
78 retval = gdImageStringFTEx (im, brect, fg, fontlist, ptsize, angle, x, y, sstring, gdFTEX_Unicode);
79 free(sstring);
80
81 return retval;
82 }
83 #else
84 #define SARGgdImageStringFT gdImageStringFT
85 #endif
86
87 static void bar(int x1,long long int n)
88 {
89 gdPoint points[4];
90 int brect[8];
91 int val=0, x;
92 long long int num;
93 char v[15];
94
95 static const long long int limits[400]={0,500,1000,2000,3000,4000,
96 5000,6000,7000,8000,9000,10000,
97 20000,30000,40000,50000,70000,90000,
98 110000,130000,150000,170000,190000,210000,
99 230000,250000,280000,310000,340000,370000,
100 400000,430000,450000,460000,490000,500000,
101 550000,600000,650000,700000,750000,800000,
102 850000,900000,950000,1000000,1100000,1200000,
103 1300000,1400000,1500000,1600000,1700000,1800000,
104 1900000,2000000,2100000,2200000,2300000,2400000,
105 2500000,2600000,2700000,2800000,2900000,3000000,
106 3100000,3200000,3300000,3400000,3500000,3600000,
107 3700000,3800000,3900000,4000000,4100000,4200000,
108 4300000,4400000,4500000,4600000,4700000,4800000,
109 4900000,5000000,5100000,5200000,5300000,5400000,
110 5500000,5600000,5700000,5800000,5900000,6000000,
111 6100000,6200000,6300000,6400000,6500000,6600000,
112 6700000,6800000,6900000,7000000,7100000,7200000,
113 7300000,7400000,7500000,7600000,7700000,7800000,
114 7900000,8000000,8100000,8200000,8300000,8400000,
115 8500000,8600000,8700000,8800000,8900000,9000000,
116 9100000,9200000,9300000,9400000,9500000,9600000,
117 9700000,9800000,9900000,10000000,10500000,11000000,
118 11500000,12000000,12500000,13000000,13500000,14000000,
119 14500000,15000000,15500000,16000000,16500000,17000000,
120 17500000,18000000,18500000,19000000,19500000,20000000,
121 21000000,22000000,23000000,24000000,25000000,26000000,
122 27000000,28000000,29000000,30000000,31000000,32000000,
123 33000000,34000000,35000000,36000000,37000000,38000000,
124 39000000,40000000,41000000,42000000,43000000,44000000,
125 45000000,46000000,47000000,48000000,49000000,50000000,
126 51000000,52000000,53000000,54000000,55000000,56000000,
127 57000000,58000000,59000000,60000000,61000000,62000000,
128 63000000,64000000,65000000,66000000,67000000,68000000,
129 69000000,70000000,71000000,72000000,73000000,74000000,
130 75000000,76000000,77000000,78000000,79000000,80000000,
131 81000000,82000000,83000000,84000000,85000000,86000000,
132 87000000,88000000,89000000,90000000,91000000,92000000,
133 93000000,94000000,95000000,96000000,97000000,98000000,
134 99000000,100000000,110000000,120000000,130000000,140000000,
135 150000000,160000000,170000000,180000000,190000000,200000000,
136 210000000,220000000,230000000,240000000,250000000,260000000,
137 270000000,280000000,290000000,300000000,310000000,320000000,
138 330000000,340000000,350000000,360000000,370000000,380000000,
139 390000000,400000000,410000000,420000000,430000000,440000000,
140 450000000,460000000,470000000,480000000,490000000,500000000,
141 510000000,520000000,530000000,540000000,550000000,560000000,
142 570000000,580000000,590000000,600000000,610000000,620000000,
143 630000000,640000000,650000000,660000000,670000000,680000000,
144 690000000,700000000,710000000,720000000,730000000,740000000,
145 750000000,760000000,770000000,780000000,790000000,800000000,
146 810000000,820000000,830000000,840000000,850000000,860000000,
147 870000000,880000000,890000000,900000000,910000000,920000000,
148 930000000,940000000,950000000,960000000,970000000,980000000,
149 990000000LL,1000000000LL,1100000000LL,1200000000LL,1300000000LL,1400000000LL,
150 1500000000LL,1600000000LL,1700000000LL,1800000000LL,1900000000LL,2000000000LL,
151 2100000000LL,2200000000LL,2300000000LL,2400000000LL,2500000000LL,2600000000LL,
152 2700000000LL,2800000000LL,2900000000LL,3000000000LL,3100000000LL,3200000000LL,
153 3300000000LL,3400000000LL,3500000000LL,3600000000LL,3700000000LL,3800000000LL,
154 3900000000LL,4000000000LL,4100000000LL,4200000000LL,4300000000LL,4400000000LL,
155 4500000000LL,4600000000LL,4700000000LL,4800000000LL,4900000000LL,5000000000LL};
156
157 if(strcmp(GraphDaysBytesBarColor,"orange") == 0) {
158 color1 = gdImageColorAllocate(im, 255, 233, 142);
159 color2 = gdImageColorAllocate(im, 220, 163, 72);
160 color3 = gdImageColorAllocate(im, 255, 198, 107);
161 }
162 if(strcmp(GraphDaysBytesBarColor,"blue") == 0) {
163 color1 = gdImageColorAllocate(im, 62, 80, 167);
164 color2 = gdImageColorAllocate(im, 40, 51, 101);
165 color3 = gdImageColorAllocate(im, 57, 73, 150);
166 }
167 if(strcmp(GraphDaysBytesBarColor,"green") == 0) {
168 color1 = gdImageColorAllocate(im,120,166,129);
169 color2 = gdImageColorAllocate(im,84,113,82);
170 color3 = gdImageColorAllocate(im,158,223,167);
171 }
172 if(strcmp(GraphDaysBytesBarColor,"yellow") == 0) {
173 color1 = gdImageColorAllocate(im,185,185,10);
174 color2 = gdImageColorAllocate(im,111,111,10);
175 color3 = gdImageColorAllocate(im,166,166,10);
176 }
177 if(strcmp(GraphDaysBytesBarColor,"brown") == 0) {
178 color1 = gdImageColorAllocate(im,97,45,27);
179 color2 = gdImageColorAllocate(im,60,30,20);
180 color3 = gdImageColorAllocate(im,88,41,26);
181 }
182 if(strcmp(GraphDaysBytesBarColor,"red") == 0){
183 color1 = gdImageColorAllocate(im,185,10,10);
184 color2 = gdImageColorAllocate(im,111,10,10);
185 color3 = gdImageColorAllocate(im,166,10,10);
186 }
187
188 blue = gdImageColorAllocate(im, 0, 0, 255);
189 white = gdImageColorAllocate(im, 255, 255, 255);
190 dimgray = gdImageColorAllocate(im, 105, 105, 105);
191 goldenrod = gdImageColorAllocate(im, 234, 234, 174);
192 goldenrod2 = gdImageColorAllocate(im, 207, 181, 59);
193
194 num = n;
195 val = 55;
196 for(x=0; x<=366; x++) {
197 if(limits[x] >= num) {
198 val = 425 - x;
199 break;
200 }
201 }
202
203 gdImageFilledRectangle(im, x1, val, x1+11, 425, color3);
204
205 points[0].x = x1+7;
206 points[0].y = val-5;
207 points[1].x = x1;
208 points[1].y = val;
209 points[2].x = x1+11;
210 points[2].y = val;
211 points[3].x = x1+17;
212 points[3].y = val-5;
213 gdImageFilledPolygon(im, points, 4, color1);
214
215 gdImageLine(im, x1+8, val-2, x1+8, val-10, dimgray);
216 gdImageFilledRectangle(im, x1-2, val-20, x1+18, val-10, goldenrod);
217 gdImageRectangle(im, x1-2, val-20, x1+18, val-10, goldenrod2);
218
219 snprintf(v,6,"%s",fixnum(num,0));
220
221 SARGgdImageStringFT(im,&brect[0],black,GraphFont,6,0.0,x1-1,val-12,v);
222
223 points[0].x = x1+17;
224 points[0].y = val-5;
225 points[1].x = x1+11;
226 points[1].y = val;
227 points[2].x = x1+11;
228 points[2].y = 426;
229 points[3].x = x1+17;
230 points[3].y = 420;
231 gdImageFilledPolygon(im, points, 4, color2);
232
233 return;
234 }
235 #endif //HAVE_GD
236
237 void greport_day(const char *user)
238 {
239 #ifdef HAVE_GD
240 FILE *fp_in, *pngout;
241 int x, y;
242 int x1;
243 int brect[8];
244 char wdirname[MAXLEN];
245 char graph[MAXLEN];
246 char buf[MAXLEN];
247 char wuser[255];
248 char csort[255];
249 char data[20];
250 char s[15];
251 char tmp5[MAXLEN];
252 int count=0;
253 int oday=0;
254 int day=0;
255 long long int llday;
256 long long int bytes;
257 char ftime[128];
258 long long int tot=0;
259 time_t t;
260 struct tm *local;
261 int cstatus;
262 struct getwordstruct gwarea;
263 struct getwordstruct gwarea1;
264
265 if(!Graphs || GraphFont[0]=='\0') {
266 unlink(wdirname);
267 return;
268 }
269 if(access(GraphFont, R_OK) != 0) {
270 fprintf(stderr, "SARG: (grepday) Fontname: %s not found.\n",GraphFont);
271 exit(1);
272 }
273
274 im = gdImageCreate(720, 480);
275
276 lavender = gdImageColorAllocate(im, 230, 230, 250);
277 white = gdImageColorAllocate(im, 255, 255, 255);
278 gray = gdImageColorAllocate(im, 192, 192, 192);
279 silver = gdImageColorAllocate(im, 211, 211, 211);
280 black = gdImageColorAllocate(im, 0, 0, 0);
281 blue = gdImageColorAllocate(im, 35, 35, 227);
282 dimgray = gdImageColorAllocate(im, 105, 105, 105);
283 darkblue = gdImageColorAllocate(im, 0, 0, 139);
284
285 gdImageRectangle(im, 0, 0, 719, 479, dimgray);
286 gdImageFilledRectangle(im, 60, 60, 700, 420, silver);
287
288 points[0].x = 50;
289 points[0].y = 65;
290 points[1].x = 50;
291 points[1].y = 425;
292 points[2].x = 60;
293 points[2].y = 420;
294 points[3].x = 60;
295 points[3].y = 60;
296 gdImageFilledPolygon(im, points, 4, gray);
297
298 points[0].x = 60;
299 points[0].y = 420;
300 points[1].x = 50;
301 points[1].y = 425;
302 points[2].x = 690;
303 points[2].y = 425;
304 points[3].x = 700;
305 points[3].y = 420;
306 gdImageFilledPolygon(im, points, 4, gray);
307
308 gdImageLine(im, 50, 65, 50, 430, black);
309 gdImageLine(im, 45, 425, 690, 425, black);
310 gdImageLine(im, 50, 425, 60, 420, black);
311 gdImageLine(im, 60, 420, 60, 60, black);
312 gdImageLine(im, 700, 60, 700, 420, black);
313 gdImageLine(im, 690, 425, 700, 420, black);
314
315 for(x=415; x>=65; x=x-10) {
316 gdImageLine(im, 50, x, 60, x-5, dimgray);
317 gdImageLine(im, 47, x, 50, x, dimgray);
318 }
319
320 for(x=60; x<=420; x=x+10)
321 gdImageLine(im, 60, x, 700, x, dimgray);
322
323 gdImageLine(im, 60, 420, 700, 420, black);
324
325 for(x=70; x<=680; x=x+20)
326 gdImageLine(im, x, 425, x, 428, dimgray);
327
328 y=65;
329 for(x=1; x<=31; x++) {
330 sprintf(s,"%02d",x);
331 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,y,437,s);
332 y=y+20;
333 }
334
335 t = time(NULL);
336 local = localtime(&t);
337 if(strcmp(DateFormat,"u") == 0)
338 strftime(ftime, sizeof(ftime), "%b/%d/%Y %H:%M", local);
339 if(strcmp(DateFormat,"e") == 0)
340 strftime(ftime, sizeof(ftime), "%d/%b/%Y-%H:%M", local);
341
342 if(dotinuser && strchr(name,'_')) {
343 subs(name,sizeof(name),"_",".");
344 }
345
346 SARGgdImageStringFT(im,&brect[0],darkblue,GraphFont,7,0.0,620,470,ftime);
347 if(ShowSargInfo) SARGgdImageStringFT(im,&brect[0],darkblue,GraphFont,10,0.0,257,15,"SARG, ");
348 SARGgdImageStringFT(im,&brect[0],darkblue,GraphFont,10,0.0,300,15,Title);
349 sprintf(warea,"%s: %s",text[89],period);
350 SARGgdImageStringFT(im,&brect[0],darkblue,GraphFont,9,0.0,300,27,warea);
351 sprintf(warea,"%s: %s",text[90],name);
352 SARGgdImageStringFT(im,&brect[0],darkblue,GraphFont,9,0.0,300,38,warea);
353 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,418," 50K");
354 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,408,"250K");
355 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,398,"500K");
356 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,388," 1M");
357 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,378," 2M");
358 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,368," 3M");
359 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,358," 4M");
360 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,348," 5M");
361 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,338," 6M");
362 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,328," 7M");
363 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,318," 8M");
364 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,308," 9M");
365 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,298," 10M");
366 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,288," 15M");
367 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,278," 20M");
368 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,268," 30M");
369 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,258," 40M");
370 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,248," 50M");
371 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,238," 60M");
372 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,228," 70M");
373 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,218," 80M");
374 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,208," 90M");
375 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,198,"100M");
376 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,188,"200M");
377 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,178,"300M");
378 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,168,"400M");
379 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,158,"500M");
380 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,148,"600M");
381 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,138,"700M");
382 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,128,"800M");
383 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,118,"900M");
384 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23,108," 1G");
385 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23, 98," 2G");
386 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23, 88," 3G");
387 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23, 78," 4G");
388 SARGgdImageStringFT(im,&brect[0],dimgray,GraphFont,7,0.0,23, 68," 5G");
389 if(strcmp(datetimeby,"bytes") == 0)
390 SARGgdImageStringFT(im,&brect[0],black,GraphFont,10,3.14/2,20,248,text[93]);
391 else
392 SARGgdImageStringFT(im,&brect[0],black,GraphFont,10,3.14/2,20,248,text[94]);
393 SARGgdImageStringFT(im,&brect[0],black,GraphFont,10,0.0,330,460,text[127]);
394
395 if (snprintf(graph,sizeof(graph),"%s/%s/graph_day.png",dirname,user)>=sizeof(graph)) {
396 fprintf(stderr, "SARG: user name too long for: %s/%s/graph_day.png\n",dirname,user);
397 exit(1);
398 }
399 if (snprintf(wdirname,sizeof(wdirname),"%s/%s.day",tmp,user)>=sizeof(wdirname)) {
400 fprintf(stderr, "SARG: user name too long for: %s/%s.day\n",tmp,user);
401 exit(1);
402 }
403 if (snprintf(tmp5,sizeof(tmp5),"%s/%s.graph",tmp,user)>=sizeof(tmp5)) {
404 fprintf(stderr, "SARG: user name too long for: %s/%s.graph\n",tmp,user);
405 exit(1);
406 }
407
408 if(access(wdirname, R_OK) != 0) {
409 gdImageDestroy(im);
410 return;
411 }
412
413 if(strcmp(DateFormat,"e") == 0)
414 sprintf(csort,"sort -t\"/\" -k 1,1 -o \"%s\" \"%s\"",tmp5,wdirname);
415 else
416 sprintf(csort,"sort -t\"/\" -k 2,2 -o \"%s\" \"%s\"",tmp5,wdirname);
417
418 cstatus=system(csort);
419 if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) {
420 fprintf(stderr, "SARG: sort command return status %d\n",WEXITSTATUS(cstatus));
421 fprintf(stderr, "SARG: sort command: %s\n",csort);
422 exit(1);
423 }
424
425 if((fp_in=fopen(tmp5,"r"))==NULL) {
426 fprintf(stderr, "SARG: (grepday) %s: %s\n",text[8],tmp5);
427 exit(1);
428 }
429
430 if((pngout=fopen(graph,"wb"))==NULL) {
431 fprintf(stderr, "SARG: (grepday) %s: %s\n",text[8],graph);
432 exit(1);
433 }
434
435 strcpy(wuser,user);
436 if(strstr(wuser,"_") != 0)
437 fixip(wuser);
438
439 if(Ip2Name)
440 if((str=(char *) strstr(name, ".")) != (char *) NULL) {
441 if((str=(char *) strstr(str+1, ".")) != (char *) NULL)
442 ip2name(wuser,sizeof(wuser));
443 }
444
445 user_find(name, sizeof(name), wuser);
446
447 while(fgets(buf,sizeof(buf),fp_in)!=NULL) {
448 fixendofline(buf);
449 getword_start(&gwarea,buf);
450 if (getword(data,sizeof(data),&gwarea,'\t')<0) {
451 printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",tmp5);
452 exit(1);
453 }
454 getword_start(&gwarea1,data);
455 if (getword_atoll(&llday,&gwarea1,'/')<0) {
456 printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",tmp5);
457 exit(1);
458 }
459 if(strcmp(DateFormat,"u") == 0) {
460 if (getword_atoll(&llday,&gwarea1,'/')<0) {
461 printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",tmp5);
462 exit(1);
463 }
464 }
465 day=(int)llday;
466 if(!count) {
467 oday=day;
468 count++;
469 }
470 if (getword_skip(20,&gwarea,'\t')<0 || getword_atoll(&bytes,&gwarea,'\t')<0) {
471 printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",tmp5);
472 exit(1);
473 }
474
475 if(oday!=day) {
476 x1 = 44 +(oday * 20);
477 bar(x1,tot);
478 oday=day;
479 tot=0;
480 }
481 tot+=bytes;
482 }
483
484 if(tot) {
485 x1 = 44 +(day * 20);
486 bar(x1,tot);
487 }
488
489 gdImagePng(im, pngout);
490 fclose(pngout);
491 gdImageDestroy(im);
492
493 fclose(fp_in);
494 unlink(wdirname);
495 unlink(tmp5);
496
497 #endif //HAVE_GD
498
499 return;
500 }
501
502 void greport_cleanup(void)
503 {
504 #ifdef HAVE_GD
505 gdFontCacheShutdown();
506 #endif
507 }