1 /* Copyright (C) 2000-2015 Lavtech.com corp. All rights reserved.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License as published by
5    the Free Software Foundation; either version 2 of the License, or
6    (at your option) any later version.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program; if not, write to the Free Software
15    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16 */
17 
18 
19 #include "udm_config.h"
20 
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/types.h>
25 #include <errno.h>
26 
27 #include "udm_common.h"
28 #include "udm_utils.h"
29 #include "udm_vars.h"
30 #include "udm_result.h"
31 #include "udm_db.h"
32 #include "udm_env.h"
33 #include "udm_prog.h"
34 
35 
36 typedef struct
37 {
38   UDM_VALUE generic;
39   UDM_RESULT Result;
40 } UDM_VALUE_RESULT;
41 
42 
43 typedef struct
44 {
45   UDM_VAR_HEADER Header;
46   UDM_VALUE_RESULT Value;
47 } UDM_VAR_RESULT;
48 
49 
50 static udm_rc_t
UdmValueResultDump(const char * Data,const char * name,FILE * f)51 UdmValueResultDump(const char *Data, const char *name, FILE *f)
52 {
53   return UDM_NOTARGET;
54 }
55 
56 
57 static udm_var_flag_t
UdmValueResultFlags(const char * Data)58 UdmValueResultFlags(const char *Data)
59 {
60   return UDM_VARFLAG_READONLY;
61 }
62 
63 
64 static udm_secno_t
UdmValueResultSecno(const char * Data)65 UdmValueResultSecno(const char *Data)
66 {
67   return 0;
68 }
69 
70 
71 static size_t
UdmValueResultMemUsed(const char * Data)72 UdmValueResultMemUsed(const char *Data)
73 {
74   return sizeof(UDM_RESULT);
75 }
76 
77 
78 static void
UdmValueResultDestructor(char * Data)79 UdmValueResultDestructor(char *Data)
80 {
81   UDM_RESULT *Res= (UDM_RESULT *) Data;
82   UdmResultFree(Res);
83 }
84 
85 
86 static udm_rc_t
UdmValueResultCopy(char * D,const char * S)87 UdmValueResultCopy(char *D, const char *S)
88 {
89   UDM_ASSERT(0); /* TODO34: Add CloneVar(), with reference */
90   memmove(D, S, sizeof(UDM_RESULT));
91   return UDM_OK;
92 }
93 
94 
95 static udm_rc_t
UdmValueResultConstructor(char * Data,const UDM_VALUE ** args,size_t nargs)96 UdmValueResultConstructor(char *Data,
97                           const UDM_VALUE **args, size_t nargs)
98 {
99   if (args && args[0] && args[0]->handler->datatype == UDM_VALUE_DATA_TYPE_ENV)
100   {
101     UDM_RESULT *Result;
102     if (!(Result= (UDM_RESULT *) UdmMalloc(sizeof(UDM_RESULT))))
103       return UDM_ERROR;
104     UdmResultInit(Result);
105     ((UDM_RESULT *) Data)[0]= Result[0];
106   }
107   else
108   {
109     UDM_BZERO(Data, sizeof(UDM_RESULT));
110   }
111   return UDM_OK;
112 }
113 
114 
115 static size_t
UdmValueResultVarSize(void)116 UdmValueResultVarSize(void)
117 {
118   return sizeof(UDM_VAR_RESULT);
119 }
120 
121 
122 static size_t
UdmValueResultValueSize(void)123 UdmValueResultValueSize(void)
124 {
125   return sizeof(UDM_VALUE_RESULT);
126 }
127 
128 
129 static size_t
UdmValueResultDataOffset(void)130 UdmValueResultDataOffset(void)
131 {
132   return offsetof(UDM_VALUE_RESULT, Result);
133 }
134 
135 
136 static size_t
UdmValueResultDataSize(void)137 UdmValueResultDataSize(void)
138 {
139   return sizeof(UDM_RESULT);
140 }
141 
142 
143 static size_t
UdmValueResultDataAlignment(void)144 UdmValueResultDataAlignment(void)
145 {
146   return sizeof(size_t);
147 }
148 
149 
150 static void
UdmValueResultGetConstStr(const char * Data,UDM_CONST_STR * Val)151 UdmValueResultGetConstStr(const char *Data, UDM_CONST_STR *Val)
152 {
153   static const UDM_CONST_STR name= {UDM_CSTR_WITH_LEN("#Result#")};
154   *Val= name;
155 }
156 
157 
158 static void
UdmValueResultGetBool(const char * Data,udm_bool_t * val)159 UdmValueResultGetBool(const char *Data, udm_bool_t *val)
160 {
161   *val= UDM_TRUE;
162 }
163 
164 
165 static void
UdmValueResultGetInt(const char * Data,int * val)166 UdmValueResultGetInt(const char *Data, int *val)
167 {
168   *val= 0;
169 }
170 
171 
172 static void
UdmValueResultGetUInt(const char * Data,unsigned int * val)173 UdmValueResultGetUInt(const char *Data, unsigned int *val)
174 {
175   *val= 0;
176 }
177 
178 
179 static void
UdmValueResultGetDouble(const char * Data,double * val)180 UdmValueResultGetDouble(const char *Data, double *val)
181 {
182   *val= 0.0;
183 }
184 
185 
186 static udm_rc_t
UdmValueResultSetInt(char * Data,int value)187 UdmValueResultSetInt(char *Data, int value)
188 {
189   return UDM_NOTARGET;
190 }
191 
192 
193 static udm_rc_t
UdmValueResultSetDouble(char * Data,double value)194 UdmValueResultSetDouble(char *Data, double value)
195 {
196   return UDM_NOTARGET;
197 }
198 
199 
200 static udm_rc_t
UdmValueResultConvertCharset(char * Data,UDM_CONV * conv,int flags)201 UdmValueResultConvertCharset(char *Data, UDM_CONV *conv, int flags)
202 {
203   return UDM_NOTARGET;
204 }
205 
206 
207 static udm_rc_t
UdmValueResultAppendStrn(char * Data,const char * str,size_t length)208 UdmValueResultAppendStrn(char *Data, const char *str, size_t length)
209 {
210   return UDM_NOTARGET;
211 }
212 
213 
214 static udm_rc_t
UdmValueResultSetStrn(char * Data,const char * str,size_t length)215 UdmValueResultSetStrn(char *Data, const char *str, size_t length)
216 {
217   return UDM_NOTARGET;
218 }
219 
220 
221 static udm_rc_t
UdmValueResultSetConv(char * Data,UDM_CONV * conv,int cnvflags,const char * src,size_t srclen)222 UdmValueResultSetConv(char *Data, UDM_CONV *conv, int cnvflags,
223                       const char *src, size_t srclen)
224 {
225   return UDM_NOTARGET;
226 }
227 
228 
229 static udm_rc_t
UdmValueResultAppendConv(char * Data,size_t maxlen,UDM_CONV * cnv,int cnvflags,const char * src,size_t srclen)230 UdmValueResultAppendConv(char *Data, size_t maxlen,
231                          UDM_CONV *cnv, int cnvflags,
232                          const char *src, size_t srclen)
233 {
234   return UDM_NOTARGET;
235 }
236 
237 
238 static udm_rc_t
UdmValueResultPrintToFile(const char * Data,FILE * f)239 UdmValueResultPrintToFile(const char *Data, FILE *f)
240 {
241   return UDM_OK;
242 }
243 
244 
245 static udm_rc_t
UdmValueResultPrintToDSTR(const char * Data,UDM_DSTR * dstr)246 UdmValueResultPrintToDSTR(const char *Data, UDM_DSTR *dstr)
247 {
248   return UDM_OK;
249 }
250 
251 
252 static void
UdmResultMethodFind(UDM_PROG_EXECUTOR_STATE * state)253 UdmResultMethodFind(UDM_PROG_EXECUTOR_STATE *state)
254 {
255   UDM_RESULT *Result= (UDM_RESULT*) state->vreg[0].Data;
256   UDM_ENV *Env= ((UDM_ENV **) state->vreg[1].Data)[0];
257   const UDM_SECTION *Section= (const UDM_SECTION*) state->vreg[2].Data;
258   char str[256];
259   Env->errstr[0]= '\0';
260   Env->THDHandler= state->globals.THDHandler;
261   udm_snprintf(str, sizeof(str), "%.*s",
262                (int) UdmDSTRLength(&Section->Value), UdmDSTRPtr(&Section->Value));
263   /*
264     TODO34: if Env is reused for multiple queries, this UdmEnvPrepate()
265     will load ispell multiple times. Fix this to avoid multiple loading.
266   */
267   if (UDM_FUNC_RETURN_INT(state, UdmEnvPrepare(Env)))
268     return; /* Error, e.g. could not load ispell files */
269   UDM_FUNC_RETURN_INT(state, UdmEnvFind(Env, Result, str));
270 }
271 
272 static UDM_VALUE_PROTOTYPE UdmResultMethodPrototypeFind[]=
273 {{&UdmValueHandlerResult},{&UdmValueHandlerEnv},{&UdmValueHandlerSimple}};
274 
275 
276 static void
UdmResultMethodTotalFound(UDM_PROG_EXECUTOR_STATE * state)277 UdmResultMethodTotalFound(UDM_PROG_EXECUTOR_STATE *state)
278 {
279   UDM_RESULT *Result= (UDM_RESULT*) state->vreg[0].Data;
280   UDM_FUNC_RETURN_INT(state, (int) UdmResultTotalFound(Result));
281 }
282 
283 static void
UdmResultMethodFirst(UDM_PROG_EXECUTOR_STATE * state)284 UdmResultMethodFirst(UDM_PROG_EXECUTOR_STATE *state)
285 {
286   UDM_RESULT *Result= (UDM_RESULT*) state->vreg[0].Data;
287   UDM_FUNC_RETURN_INT(state, (int) UdmResultFirst(Result));
288 }
289 
290 static void
UdmResultMethodLast(UDM_PROG_EXECUTOR_STATE * state)291 UdmResultMethodLast(UDM_PROG_EXECUTOR_STATE *state)
292 {
293   UDM_RESULT *Result= (UDM_RESULT*) state->vreg[0].Data;
294   UDM_FUNC_RETURN_INT(state, (int) UdmResultLast(Result));
295 }
296 
297 static void
UdmResultMethodNumRows(UDM_PROG_EXECUTOR_STATE * state)298 UdmResultMethodNumRows(UDM_PROG_EXECUTOR_STATE *state)
299 {
300   UDM_RESULT *Result= (UDM_RESULT*) state->vreg[0].Data;
301   UDM_FUNC_RETURN_INT(state, (int) UdmResultNumRows(Result));
302 }
303 
304 
305 static void
UdmResultMethodNumWords(UDM_PROG_EXECUTOR_STATE * state)306 UdmResultMethodNumWords(UDM_PROG_EXECUTOR_STATE *state)
307 {
308   UDM_RESULT *Result= (UDM_RESULT*) state->vreg[0].Data;
309   UDM_FUNC_RETURN_INT(state, (int) Result->WWList.nwords);
310 }
311 
312 
313 static void
UdmResultMethodNumUniqWords(UDM_PROG_EXECUTOR_STATE * state)314 UdmResultMethodNumUniqWords(UDM_PROG_EXECUTOR_STATE *state)
315 {
316   UDM_RESULT *Result= (UDM_RESULT*) state->vreg[0].Data;
317   UDM_FUNC_RETURN_INT(state, (int) Result->WWList.nuniq);
318 }
319 
320 
321 static udm_rc_t
UdmResultPropertyAppendHilight(UDM_DSTR * dst,UDM_CHARSET * cs,const UDM_CONST_STR * str,const char * hlbeg,size_t hlbeglen,const char * hlend,size_t hlendlen)322 UdmResultPropertyAppendHilight(UDM_DSTR *dst,
323                                UDM_CHARSET *cs,
324                                const UDM_CONST_STR *str,
325                                const char *hlbeg, size_t hlbeglen,
326                                const char *hlend, size_t hlendlen)
327 {
328   UDM_DSTR tmp;
329   UDM_CONV cnv;
330   UdmConvInit(&cnv, cs, cs);
331   UdmDSTRInit(&tmp, 128);
332   UdmDSTRAppendConv(&tmp, &cnv, str->str, str->length, UDM_RECODE_HTML);
333   UdmDSTRAppendHighlight(dst, UdmDSTRPtr(&tmp), UdmDSTRLength(&tmp),
334                          hlbeg, hlbeglen, hlend, hlendlen);
335   UdmDSTRFree(&tmp);
336   return UDM_OK;
337 }
338 
339 
340 static UDM_VALUE *
UdmVarListFindValueByDSTR(UDM_VARLIST * Vars,const UDM_DSTR * str)341 UdmVarListFindValueByDSTR(UDM_VARLIST *Vars, const UDM_DSTR *str)
342 {
343   char name[128];
344   udm_snprintf(name, sizeof(name), "%.*s",
345                (int) UdmDSTRLength(str), UdmDSTRPtr(str));
346   return UdmVarListFindValue(Vars, name);
347 }
348 
349 
350 static void
UdmResultMethodWord(UDM_PROG_EXECUTOR_STATE * state)351 UdmResultMethodWord(UDM_PROG_EXECUTOR_STATE *state)
352 {
353   UDM_RESULT *Result= (UDM_RESULT *) state->vreg[0].Data;
354   int pos= ((int *) state->vreg[1].Data)[0];
355   void *ret= UdmProgExecutorStateSetupReturnValue(state, &UdmValueHandlerQueryWord);
356   if (pos < 0 || (size_t) pos >= Result->WWList.nwords)
357     return;
358   state->fatal_error= UdmValueHandlerQueryWord.Copy(ret,
359                                                    (char *) &Result->WWList.Word[pos]);
360 }
361 
362 
363 static void
UdmResultMethodPropertyCommon(UDM_PROG_EXECUTOR_STATE * state,UDM_SECTION * ReturnValue,UDM_VARLIST * Vars,UDM_SECTION * Property,UDM_CHARSET * cs,udm_bool_t html,const char * hlbeg,size_t hlbeglen,const char * hlend,size_t hlendlen)364 UdmResultMethodPropertyCommon(UDM_PROG_EXECUTOR_STATE *state,
365                               UDM_SECTION *ReturnValue,
366                               UDM_VARLIST *Vars, UDM_SECTION *Property,
367                               UDM_CHARSET *cs, udm_bool_t html,
368                               const char *hlbeg, size_t hlbeglen,
369                               const char *hlend, size_t hlendlen)
370 {
371   UDM_CONST_STR str;
372   UDM_VALUE *Value;
373   if (!(Value= UdmVarListFindValueByDSTR(Vars, &Property->Value)))
374     return;
375   Value->handler->GetConstStr(UdmValueDataPtr(Value), &str);
376   state->fatal_error= html ?
377     UdmResultPropertyAppendHilight(&ReturnValue->Value, cs, &str,
378                                    hlbeg, hlbeglen,
379                                    hlend, hlendlen) :
380     UdmDSTRAppendRemoveHiLight(&ReturnValue->Value, str.str, str.length);
381 }
382 
383 
384 static void
UdmResultMethodDocumentPropertyInternal(UDM_PROG_EXECUTOR_STATE * state,udm_bool_t html,const char * hlbeg,size_t hlbeglen,const char * hlend,size_t hlendlen)385 UdmResultMethodDocumentPropertyInternal(UDM_PROG_EXECUTOR_STATE *state,
386                                         udm_bool_t html,
387                                         const char *hlbeg, size_t hlbeglen,
388                                         const char *hlend, size_t hlendlen)
389 {
390   UDM_RESULT *Result= (UDM_RESULT *) state->vreg[0].Data;
391   int pos= ((int *) state->vreg[1].Data)[0];
392   UDM_SECTION *Property= (UDM_SECTION *) state->vreg[2].Data;
393   UDM_SECTION *ret= UdmProgExecutorStateSetupReturnValue(state, &UdmValueHandlerSimple);
394   if (pos < 0 || (size_t) pos >= Result->num_rows)
395     return;
396   UdmResultMethodPropertyCommon(state, ret, &Result->Doc[pos].Sections,
397                                        Property,
398                                        Result->Doc[pos].lcs, html,
399                                        hlbeg, hlbeglen, hlend, hlendlen);
400 }
401 
402 
403 static void
UdmResultMethodPropertyInternal(UDM_PROG_EXECUTOR_STATE * state,UDM_CHARSET * cs,udm_bool_t html,const char * hlbeg,size_t hlbeglen,const char * hlend,size_t hlendlen)404 UdmResultMethodPropertyInternal(UDM_PROG_EXECUTOR_STATE *state,
405                                 UDM_CHARSET *cs,
406                                 udm_bool_t html,
407                                 const char *hlbeg, size_t hlbeglen,
408                                 const char *hlend, size_t hlendlen)
409 {
410   UDM_RESULT *Result= (UDM_RESULT *) state->vreg[0].Data;
411   UDM_SECTION *Property= (UDM_SECTION *) state->vreg[1].Data;
412   UDM_SECTION *ret= UdmProgExecutorStateSetupReturnValue(state, &UdmValueHandlerSimple);
413   UdmResultMethodPropertyCommon(state, ret, &Result->Vars,
414                                 Property, cs, html,
415                                 hlbeg, hlbeglen, hlend, hlendlen);
416 }
417 
418 
419 static void
UdmResultMethodDocumentProperty(UDM_PROG_EXECUTOR_STATE * state)420 UdmResultMethodDocumentProperty(UDM_PROG_EXECUTOR_STATE *state)
421 {
422   UdmResultMethodDocumentPropertyInternal(state, UDM_FALSE, "", 0, "", 0);
423 }
424 
425 
426 static void
UdmResultMethodDocumentPropertyHtml(UDM_PROG_EXECUTOR_STATE * state)427 UdmResultMethodDocumentPropertyHtml(UDM_PROG_EXECUTOR_STATE *state)
428 {
429   UdmResultMethodDocumentPropertyInternal(state, UDM_TRUE, "", 0, "", 0);
430 }
431 
432 
433 static void
UdmResultMethodDocumentPropertyHtml5(UDM_PROG_EXECUTOR_STATE * state)434 UdmResultMethodDocumentPropertyHtml5(UDM_PROG_EXECUTOR_STATE *state)
435 {
436   UDM_SECTION *HlBeg= (UDM_SECTION *) state->vreg[3].Data;
437   UDM_SECTION *HlEnd= (UDM_SECTION *) state->vreg[4].Data;
438   UdmResultMethodDocumentPropertyInternal(state, UDM_TRUE,
439                                           UdmDSTRPtr(&HlBeg->Value),
440                                           UdmDSTRLength(&HlBeg->Value),
441                                           UdmDSTRPtr(&HlEnd->Value),
442                                           UdmDSTRLength(&HlEnd->Value));
443 }
444 
445 
446 static void
UdmResultMethodProperty(UDM_PROG_EXECUTOR_STATE * state)447 UdmResultMethodProperty(UDM_PROG_EXECUTOR_STATE *state)
448 {
449   UdmResultMethodPropertyInternal(state, &udm_charset_latin1, UDM_FALSE,
450                                   "", 0, "", 0);
451 }
452 
453 
454 static UDM_VALUE_PROTOTYPE UdmValuePrototypeThis[]= {{&UdmValueHandlerResult}};
455 
456 
457 static UDM_VALUE_PROTOTYPE UdmValuePrototypeResultString[]=
458 {{&UdmValueHandlerResult},
459  {&UdmValueHandlerSimple},
460 };
461 
462 
463 static UDM_VALUE_PROTOTYPE UdmValuePrototypeResultIntString[]=
464 {{&UdmValueHandlerResult},
465  {&UdmValueHandlerInt},
466  {&UdmValueHandlerSimple},
467  {&UdmValueHandlerSimple},
468  {&UdmValueHandlerSimple},
469 };
470 
471 
472 static const UDM_FUNCTION ResultMethods[]=
473 {
474   {{UDM_CSTR_WITH_LEN("find")},
475     {{&UdmValueHandlerInt}, 3, UdmResultMethodPrototypeFind},
476     UdmResultMethodFind},
477   {{UDM_CSTR_WITH_LEN("total_found")},
478     {{&UdmValueHandlerInt}, 1, UdmValuePrototypeThis},
479     UdmResultMethodTotalFound},
480   {{UDM_CSTR_WITH_LEN("first")},
481     {{&UdmValueHandlerInt}, 1, UdmValuePrototypeThis},
482     UdmResultMethodFirst},
483   {{UDM_CSTR_WITH_LEN("last")},
484     {{&UdmValueHandlerInt}, 1, UdmValuePrototypeThis},
485     UdmResultMethodLast},
486   {{UDM_CSTR_WITH_LEN("num_rows")},
487     {{&UdmValueHandlerInt}, 1, UdmValuePrototypeThis},
488     UdmResultMethodNumRows},
489   {{UDM_CSTR_WITH_LEN("num_words")},
490     {{&UdmValueHandlerInt}, 1, UdmValuePrototypeThis},
491     UdmResultMethodNumWords},
492   {{UDM_CSTR_WITH_LEN("num_uniq_words")},
493     {{&UdmValueHandlerInt}, 1, UdmValuePrototypeThis},
494     UdmResultMethodNumUniqWords},
495   {{UDM_CSTR_WITH_LEN("document_property")},
496     {{&UdmValueHandlerSimple}, 3, UdmValuePrototypeResultIntString},
497     UdmResultMethodDocumentProperty},
498   {{UDM_CSTR_WITH_LEN("document_property_html")},
499     {{&UdmValueHandlerSimple}, 3, UdmValuePrototypeResultIntString},
500     UdmResultMethodDocumentPropertyHtml},
501   {{UDM_CSTR_WITH_LEN("document_property_html")},
502     {{&UdmValueHandlerSimple}, 5, UdmValuePrototypeResultIntString},
503     UdmResultMethodDocumentPropertyHtml5},
504   {{UDM_CSTR_WITH_LEN("property")},
505     {{&UdmValueHandlerSimple}, 2, UdmValuePrototypeResultString},
506     UdmResultMethodProperty},
507   {{UDM_CSTR_WITH_LEN("word")},
508     {{&UdmValueHandlerQueryWord}, 2, UdmValuePrototypeResultIntString},
509     UdmResultMethodWord},
510   {{0,0}, {{NULL}, 0, NULL}, NULL}
511 };
512 
513 
514 UDM_VALUE_HANDLER UdmValueHandlerResult=
515 {
516   UDM_VALUE_HANDLER_TYPE_RESULT,
517   UDM_VALUE_DATA_TYPE_RESULT,
518   UDM_VALUE_DATA_TYPE_STR,
519   "RESULT",
520   UdmValueResultConstructor,
521   UdmValueResultDestructor,
522   UdmValueResultCopy,
523   UdmValueResultVarSize,
524   UdmValueResultValueSize,
525   UdmValueResultDataOffset,
526   UdmValueResultDataSize,
527   UdmValueResultDataAlignment,
528   UdmValueResultDump,
529   UdmValueResultFlags,
530   UdmValueResultSecno,
531   UdmValueResultMemUsed,
532   UdmValueResultGetConstStr,
533   UdmValueResultGetBool,
534   UdmValueResultGetInt,
535   UdmValueResultGetUInt,
536   UdmValueResultGetDouble,
537   UdmValueResultSetInt,
538   UdmValueResultSetDouble,
539   UdmValueResultSetStrn,
540   UdmValueResultPrintToFile,
541   UdmValueResultPrintToDSTR,
542   UdmValueResultConvertCharset,
543   UdmValueResultSetConv,
544   UdmValueResultAppendStrn,
545   UdmValueResultAppendConv,
546   ResultMethods,
547 };
548