1 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2   backend.c defines the functions to access the database search output
3   markus@mhoenicka.de 6-19-00
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9 
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 
19   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
20 
21 #include <stdlib.h>
22 #include <string.h>
23 #include <stdio.h>
24 #include <syslog.h>
25 #include <math.h> /* for log() */
26 #include <dbi/dbi.h>
27 
28 #include "refdb.h"
29 #include "linklist.h"
30 #include "refdbd.h"
31 #include "backend.h"
32 #include "strfncs.h"
33 #include "dbfncs.h"
34 #include "risdb.h"
35 #include "authorinfo.h"
36 #include "connect.h"
37 #include "readris.h"
38 
39 
40 /* globals */
41 
42 extern int n_log_level;
43 extern dbi_result dbi_style_res;
44 extern char main_db[];
45 
46 /* this string array is used for author queries. MySQL uses an enum field,
47    pgsql and others use an int field to store the author type */
48 const char author_type_string[2][3][14] = {
49   {"\'part\'", "\'publication\'", "\'set\'"},
50   {"1", "2", "3"}
51 };
52 
53 /* this is the javascript code used to pop up the tooltips in the
54    xhtml output of the checkref command */
55 char checkref_javascript[] = "<script type=\"text/javascript\">\n"
56 "<!--\n"
57 "tooltip = null;\n"
58 "document.onmousemove = updateTOOLTIP;\n"
59 "function updateTOOLTIP(e) {\n"
60 "	x = (document.all) ? window.event.x + document.body.scrollLeft : e.pageX;\n"
61 "	y = (document.all) ? window.event.y + document.body.scrollTop  : e.pageY;\n"
62 "	if (tooltip != null) {\n"
63 "		tooltip.style.left = (x + 10) + \"px\";\n"
64 "		tooltip.style.top 	= (y + 10) + \"px\";\n"
65 "	}\n"
66 "}\n"
67 "\n"
68 "function showTOOLTIP(id) {\n"
69 "   tooltip = document.getElementById(id);\n"
70 "   tooltip.style.display = \"block\"\n"
71 "}\n"
72 "\n"
73 "function hideTOOLTIP() {\n"
74 "	tooltip.style.display = \"none\";\n"
75 "}\n"
76 "//-->\n"
77 "</script>\n";
78 
79 /* forward declaration of local functions */
80 static const char* real_get_periodical(dbi_result dbires, int is_temp, unsigned long long* ptr_frequency);
81 
82 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
83   assemble_header(): assembles various html, xhtml, and XML headers
84 
85   struct renderinfo* ptr_rendinfo ptr to a structure containing
86                      information how the stuff is to be rendered
87 
88   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
assemble_header(struct renderinfo * ptr_rendinfo)89 char* assemble_header(struct renderinfo* ptr_rendinfo) {
90   /* see whether the client specified a character encoding */
91   char enc_string[PREFS_BUF_LEN+80];
92   char* my_script;
93   char* header;
94   size_t header_len = 1024;
95 
96   if (ptr_rendinfo->javascript == 1) {
97     header_len += strlen(checkref_javascript);
98     my_script = checkref_javascript;
99   }
100   else {
101     /* ptr to an empty string */
102     my_script = &checkref_javascript[strlen(checkref_javascript)];
103   }
104 
105   if ((header = malloc(header_len)) == NULL) {
106     LOG_PRINT(LOG_WARNING, get_status_msg(801));
107     return NULL;
108   }
109 
110   *header = '\0';
111 
112   switch (ptr_rendinfo->ref_format) {
113   case REFHTML:
114     /* fall through */
115   case REFXHTML:
116     /* html/xhtml output */
117     if (*(ptr_rendinfo->ptr_biblio_info->encoding)) {
118       if (ptr_rendinfo->ref_format == REFHTML) {
119 	snprintf(enc_string, PREFS_BUF_LEN+80, "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\">\n", ptr_rendinfo->ptr_biblio_info->encoding);
120       }
121       else { /* XHTML, need to close meta tag for XML */
122 	snprintf(enc_string, PREFS_BUF_LEN+80, "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\"/>\n", ptr_rendinfo->ptr_biblio_info->encoding);
123       }
124     }
125     else {
126       /* should never happen */
127       *enc_string = '\0';
128     }
129 
130     if (*(ptr_rendinfo->cgi_url)) {
131       if (ptr_rendinfo->ref_format == REFHTML) {
132 	snprintf(header, header_len, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n<html>\n<head>\n%s<title>%s reference list</title>\n<meta name=\"generator\" content=\"%s %s\">\n<link rel=\"stylesheet\" type=\"text/css\" href=\"%s\">\n</head>\n<body>\n<h1 class='h1'>refdb reference list</h1>\n", enc_string, PACKAGE, PACKAGE, VERSION, ptr_rendinfo->cgi_url);
133       }
134       else { /* REFXHTML */
135 	snprintf(header, header_len, "<?xml version=\"1.0\" encoding=\"%s\"?>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\"><head>%s<title>%s reference list</title><meta name=\"generator\" content=\"%s %s\" /><link rel=\"stylesheet\" type=\"text/css\" href=\"%s\" />\n%s</head>\n<body>\n<h1 class='h1'>refdb reference list</h1>\n", ptr_rendinfo->ptr_biblio_info->encoding, enc_string, PACKAGE, PACKAGE, VERSION, ptr_rendinfo->cgi_url, my_script);
136       }
137     }
138     else { /* don't use css */
139       if (ptr_rendinfo->ref_format == REFHTML) {
140 	snprintf(header, header_len, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n<html>\n<head>\n%s<title>%s reference list</title>\n<meta name=\"generator\" content=\"%s %s\">\n</head>\n<body>\n<h1 class='h1'>refdb reference list</h1>\n", enc_string, PACKAGE, PACKAGE, VERSION);
141       }
142       else { /* REFXHTML */
143 	snprintf(header, header_len, "<?xml version=\"1.0\" encoding=\"%s\"?>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\"><head>%s<title>%s reference list</title><meta name=\"generator\" content=\"%s %s\" />%s</head>\n<body>\n<h1 class='h1'>refdb reference list</h1>\n", ptr_rendinfo->ptr_biblio_info->encoding, enc_string, PACKAGE, PACKAGE, VERSION, my_script);
144       }
145     }
146     break;
147   case RISX:
148     /* risx output */
149     if (*(ptr_rendinfo->ptr_clrequest->namespace)) {
150       snprintf(header, header_len, "<?xml version=\"1.0\" encoding=\"%s\"?>\n", ptr_rendinfo->ptr_biblio_info->encoding);
151     }
152     else {
153       snprintf(header, header_len, "<?xml version=\"1.0\" encoding=\"%s\"?>\n%s", ptr_rendinfo->ptr_biblio_info->encoding, RISX_PUBID);
154     }
155     break;
156   case REFMODS:
157     /* MODS output */
158     snprintf(header, header_len, "<?xml version=\"1.0\" encoding=\"%s\"?>\n", ptr_rendinfo->ptr_biblio_info->encoding);
159     break;
160   case XNOTE:
161     /* xnote output */
162     snprintf(header, header_len, "<?xml version=\"1.0\" encoding=\"%s\"?>\n%s", ptr_rendinfo->ptr_biblio_info->encoding, XNOTE_PUBID);
163     break;
164   case REFCITATIONLISTX:
165     /* citationlistx output */
166     snprintf(header, header_len, "<?xml version=\"1.0\" encoding=\"%s\"?>\n%s", ptr_rendinfo->ptr_biblio_info->encoding, CITATIONLISTX_PUBID);
167     break;
168 /*   default: */
169     /* empty string */
170   }
171 
172 
173   return header;
174 }
175 
176 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
177   add_root_to_link(): inserts pdfroot into a link. The returned string
178                       is malloc()'ed and must be freed by the calling
179 		      function
180 
181   char* add_root_to_link(): returns a malloc()'ed string, or NULL if
182                       something goes wrong. One likely reason for the latter
183 		      is if the link is not relative, or does not use
184 		      the file:// protocol
185 
186   const char* link ptr to string containing the link
187 
188   const char* pdfroot ptr to string containing the pdfroot
189 
190   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
add_root_to_link(const char * link,const char * pdfroot)191 char* add_root_to_link(const char* link, const char* pdfroot) {
192   char* full_link = NULL;
193 
194   if (!link || !*link) {
195     return NULL;
196   }
197 
198   if (!pdfroot                           /* no pdfroot available */
199       || strlen(link) < 7                /* too short */
200       || !strncmp(link, "file:///", 8)   /* not a relative path */
201       || strncmp(link, "file://", 7)) {  /* not the appropriate protocol */
202     /* return a copy of link */
203     if ((full_link = strdup(link)) == NULL) {
204       return NULL;
205     }
206   }
207   else {
208     /* insert pdfroot after protocol specifier */
209     if ((full_link = malloc(strlen(link)+strlen(pdfroot)+1)) == NULL) {
210       return NULL;
211     }
212 
213     strcpy(full_link, link);
214 
215     /* move part after protocol specifier out of the way */
216     memmove(full_link+strlen(pdfroot)+7, full_link+7, strlen(full_link+7));
217 
218     /* insert pdfroot into the gap */
219     memcpy(full_link+7, pdfroot, strlen(pdfroot));
220   }
221 
222   return full_link;
223 }
224 
225 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
226   has_part_data(): returns true if a reference type may have part data
227 
228   int has_part_data returns 1 if the type has part data, 0 if not
229 
230   const char* type ptr to a string containing the reference type to check
231 
232   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
has_part_data(const char * type)233 int has_part_data(const char* type) {
234   if (!type) {
235     return 0;
236   }
237 
238   if (!strcmp(type, "ABST")
239       || !strcmp(type, "CHAP")
240       || !strcmp(type, "CASE")
241       || !strcmp(type, "CONF")
242       || !strcmp(type, "GEN")
243       || !strcmp(type, "INPR")
244       || !strcmp(type, "JOUR")
245       || !strcmp(type, "JFULL")
246       || !strcmp(type, "MGZN")
247       || !strcmp(type, "NEWS")
248       || !strcmp(type, "SER")) {
249     return 1;
250   }
251   else {
252     return 0;
253   }
254 }
255 
256 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
257   has_set_data(): returns true if a reference type may have set data
258 
259   int has_set_data returns 1 if the type has set data, 0 if not
260 
261   const char* type ptr to a string containing the reference type to check
262 
263   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
has_set_data(const char * type)264 int has_set_data(const char* type) {
265   if (!type) {
266     return 0;
267   }
268 
269   if (!strcmp(type, "BOOK")
270       || !strcmp(type, "CHAP")
271       || !strcmp(type, "CONF")
272       || !strcmp(type, "DATA")
273       || !strcmp(type, "GEN")
274       || !strcmp(type, "MPCT")
275       || !strcmp(type, "MUSIC")
276       || !strcmp(type, "REPORT")
277       || !strcmp(type, "SER")
278       || !strcmp(type, "SOUND")
279       || !strcmp(type, "VIDEO")) {
280     return 1;
281   }
282   else {
283     return 0;
284   }
285 }
286 
287 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
288   has_periodical_data(): returns true if a reference type has periodical
289                          data
290 
291   int has_periodical_data returns 1 if the type has periodical data, 0 if not
292 
293   const char* type ptr to a string containing the reference type to check
294 
295   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
has_periodical_data(const char * type)296 int has_periodical_data(const char* type) {
297   if (!type) {
298     return 0;
299   }
300 
301   if (!strcmp(type, "ABST")
302       || !strcmp(type, "GEN")
303       || !strcmp(type, "INPR")
304       || !strcmp(type, "JOUR")
305       || !strcmp(type, "JFULL")
306       || !strcmp(type, "MGZN")
307       || !strcmp(type, "NEWS")) {
308     return 1;
309   }
310   else {
311     return 0;
312   }
313 }
314 
315 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
316   has_chapter_data(): returns true if a reference type has something
317                       similar to chapter data
318 
319   int has_chapter_data returns 1 if the type has periodical data, 0 if not
320 
321   const char* type ptr to a string containing the reference type to check
322 
323   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
has_chapter_data(const char * type)324 int has_chapter_data(const char* type) {
325   if (!type) {
326     return 0;
327   }
328 
329   if (!strcmp(type, "CASE")
330       || !strcmp(type, "CHAP")
331       || !strcmp(type, "CONF")
332       || !strcmp(type, "GEN")) {
333     return 1;
334   }
335   else {
336     return 0;
337   }
338 }
339 
340 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
341   get_reference_count(): retrieves the number of references in a database
342 
343   unsigned long long get_reference_count returns the number of references
344                      in the current database, and places the highest ID
345                      in the provided counter
346 
347   dbi_conn conn database connection
348 
349   unsigned long long* ptr_max_id will be set to the highest reference ID
350                      if non-NULL
351 
352   int n_istemp if 1, use temporary tables as data source
353 
354   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_reference_count(dbi_conn conn,unsigned long long * ptr_max_id,int n_istemp)355 unsigned long long get_reference_count(dbi_conn conn, unsigned long long* ptr_max_id, int n_istemp) {
356   unsigned long long numrefs;
357   char sql_command[128];
358   char prefix[] = TEMP_TABLE_NAME_PREFIX;
359   dbi_result dbires;
360 
361   /* fix the insert */
362   if (!n_istemp) {
363     *prefix = '\0';
364   }
365 
366   sprintf(sql_command, "SELECT COUNT(*), MAX(refdb_id) FROM t_%srefdb WHERE refdb_type!='DUMMY'", prefix);
367 
368   LOG_PRINT(LOG_DEBUG, sql_command);
369 
370   dbires = dbi_conn_query(conn, sql_command);
371   if (!dbires
372       || !dbi_result_next_row(dbires)) {
373     return 0;
374   }
375 
376   numrefs = my_dbi_result_get_idval_idx(dbires, 1); /* 1-base index */
377   if (ptr_max_id) {
378     *ptr_max_id = my_dbi_result_get_idval_idx(dbires, 2);
379   }
380 
381   dbi_result_free(dbires);
382 
383   return numrefs;
384 }
385 
386 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
387   get_notes_count(): retrieves the number of notes in a database
388 
389   unsigned long long get_notes_count returns the number of notes
390                      in the current database, and places the highest ID
391                      in the provided counter
392 
393   dbi_conn conn database connection
394 
395   unsigned long long* ptr_max_id will be set to the highest note ID
396                      if non-NULL
397 
398   int n_istemp if 1, use temporary tables as data source
399 
400   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_notes_count(dbi_conn conn,unsigned long long * ptr_max_id,int n_istemp)401 unsigned long long get_notes_count(dbi_conn conn, unsigned long long* ptr_max_id, int n_istemp) {
402   unsigned long long numnotes;
403   char sql_command[128];
404   char prefix[] = TEMP_TABLE_NAME_PREFIX;
405   dbi_result dbires;
406 
407   /* fix the insert */
408   if (!n_istemp) {
409     *prefix = '\0';
410   }
411 
412   sprintf(sql_command, "SELECT COUNT(*), MAX(note_id) FROM t_%snote", prefix);
413 
414   LOG_PRINT(LOG_DEBUG, sql_command);
415 
416   dbires = dbi_conn_query(conn, sql_command);
417   if (!dbires
418       || !dbi_result_next_row(dbires)) {
419     return 0;
420   }
421 
422   numnotes = my_dbi_result_get_idval_idx(dbires, 1); /* 1-base index */
423   if (ptr_max_id) {
424     *ptr_max_id = my_dbi_result_get_idval_idx(dbires, 2);
425   }
426 
427   dbi_result_free(dbires);
428 
429   return numnotes;
430 }
431 
432 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
433   calculate_relative_frequency(): calculates a measure of the frequency
434                      of a keyword, authorname or whatever
435 
436   int calculate_relative_frequency returns the relative frequency
437 
438   unsigned long long frequency the number of occurrences of the item
439                      in the database
440 
441   unsigned long long refcount the total number of references in the
442                      database
443 
444   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
calculate_relative_frequency(unsigned long long frequency,unsigned long long refcount)445 int calculate_relative_frequency(unsigned long long frequency, unsigned long long refcount) {
446   if (!frequency || !refcount || refcount == 1) {
447     return 0;
448   }
449   else {
450     /* using log stretches the available span more evenly over several
451      orders of magnitude. The resulting values are supposed to be
452      between 0 (item appears only on one or a few references) to 9
453      (item appears in just about every reference) */
454     return (int)(10*(log((double)frequency)/log((double)refcount)));
455   }
456 }
457 
458 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
459   get_refdb_note_id(): retrieves the note_id element from a note query
460 
461   char* get_refdb_note_id returns a pointer to a string containing the
462                      note_id element
463 
464   dbi_result dbires database query result, pointing to the current
465                     dataset
466 
467   char* id ptr to string that will receive the id. Must be long
468                     enough for the representation of an unsigned
469 		    long long number
470 
471   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_note_id(dbi_result dbires,char * id)472 char* get_refdb_note_id(dbi_result dbires, char* id) {
473   unsigned long long n_id;
474   dbi_error_flag errflag;
475 
476   n_id = my_dbi_result_get_idval(dbires, "note_id");
477   errflag = dbi_conn_error_flag(dbi_result_get_conn(dbires));
478 
479   if (n_id == 0 || errflag) { /* all IDs > 0 so this must be an error */
480     return NULL;
481   }
482   else {
483     sprintf(id, ULLSPEC, (unsigned long long)n_id);
484     return id;
485   }
486 }
487 
488 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
489   get_refdb_note_key(): retrieves the note_key element from a note query
490 
491   char* get_refdb_note_key returns a pointer to a string containing the
492                      note_key element
493 
494   dbi_result dbires database query result, pointing to the current
495                     dataset
496 
497   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_note_key(dbi_result dbires)498 const char* get_refdb_note_key(dbi_result dbires) {
499   const char* result;
500 
501   result = dbi_result_get_string(dbires, "note_key");
502   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
503     return NULL;
504   }
505   else {
506     return result;
507   }
508 }
509 
510 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
511   get_refdb_note_user_name(): retrieves the user_name element from a note query
512 
513   char* get_refdb_note_user_name returns a pointer to a string containing the
514                      user_name element
515 
516   dbi_result dbires database query result, pointing to the current
517                     dataset
518 
519   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_note_user_name(dbi_result dbires)520 const char* get_refdb_note_user_name(dbi_result dbires) {
521   const char* result;
522 
523   result = dbi_result_get_string(dbires, "user_name");
524   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
525     return NULL;
526   }
527   else {
528     return result;
529   }
530 }
531 
532 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
533   get_refdb_note_title_copy(): retrieves the title element from a note query
534 
535   char* get_refdb_note_title_copy returns a pointer to a string containing the
536                      note_title element. The string is allocated and
537 		     must be freed by the caller
538 
539   dbi_result dbires database query result, pointing to the current
540                     dataset
541 
542   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_note_title_copy(dbi_result dbires)543 char* get_refdb_note_title_copy(dbi_result dbires) {
544   return my_dbi_result_get_string_copy(dbires, "note_title");
545 }
546 
547 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
548   get_refdb_note_content_copy(): retrieves the content element from a note query
549 
550   char* get_refdb_note_content_copy returns a pointer to a string containing the
551                      note_content element. The string is allocated and
552 		     must be freed by the caller
553 
554   dbi_result dbires database query result, pointing to the current
555                     dataset
556 
557   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_note_content_copy(dbi_result dbires)558 char* get_refdb_note_content_copy(dbi_result dbires) {
559   return my_dbi_result_get_string_copy(dbires, "note_content");
560 }
561 
562 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
563   get_refdb_note_content_type(): retrieves the content_type element
564                                  from a note query
565 
566   char* get_refdb_content_type returns a pointer to a string containing the
567                      content_type element
568 
569   dbi_result dbires database query result, pointing to the current
570                     dataset
571 
572   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_note_content_type(dbi_result dbires)573 const char* get_refdb_note_content_type(dbi_result dbires) {
574   const char* result;
575 
576   result = dbi_result_get_string(dbires, "note_content_type");
577   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
578     return NULL;
579   }
580   else {
581     return result;
582   }
583 }
584 
585 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
586   get_refdb_note_content_xmllang(): retrieves the content_xmllang element
587                                  from a note query
588 
589   char* get_refdb_content_xmllang returns a pointer to a string containing the
590                      content_xmllang element
591 
592   dbi_result dbires database query result, pointing to the current
593                     dataset
594 
595   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_note_content_xmllang(dbi_result dbires)596 const char* get_refdb_note_content_xmllang(dbi_result dbires) {
597   const char* result;
598 
599   result = dbi_result_get_string(dbires, "note_content_xmllang");
600   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
601     return NULL;
602   }
603   else {
604     return result;
605   }
606 }
607 
608 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
609   get_refdb_note_date(): retrieves the note_date element from a note query
610 
611   char* get_refdb_note_date returns a pointer to a string containing the
612                      note_date element
613 
614   dbi_result dbires database query result, pointing to the current
615                     dataset
616 
617   char* date string that receives the date. Must be >= 256 byte
618 
619   int mode 0 = string 1 = notex representation
620   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_note_date(dbi_result dbires,char * date,int mode)621 char* get_refdb_note_date(dbi_result dbires, char* date, int mode) {
622   time_t the_time;
623 
624   the_time = dbi_result_get_datetime(dbires, "note_date");
625 
626   if (dbi_conn_error_flag(dbi_result_get_conn(dbires)) == 0) {
627     if (the_time) {
628       if (!mode) {
629 	strftime(date, 256, "%a %b %d %Y", gmtime(&the_time));
630       }
631       else {
632 	strftime(date, 256, "%Y-%m-%d", gmtime(&the_time));
633       }
634     }
635     else {
636       strcpy(date, "nd");
637     }
638     return date;
639   }
640   else {
641     return NULL; /* have no date */
642   }
643 }
644 
645 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
646   get_refdb_note_share(): retrieves the share attribute
647                                  from a note query
648 
649   char* get_refdb_note_share returns 1 if public, 0 if private, -1
650                           if not set by user
651 
652   dbi_result dbires database query result, pointing to the current
653                     dataset
654 
655   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_note_share(dbi_result dbires)656 short int get_refdb_note_share(dbi_result dbires) {
657   short int result;
658 
659   result = dbi_result_get_short(dbires, "note_share");
660   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
661     return 0; /* be paranoid in case of an error */
662   }
663   else {
664     return result;
665   }
666 }
667 
668 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
669   request_notes_by_ref(): requests all notes that are associated to
670                           a given reference
671 
672   dbi_result request_notes_by_ref returns a pointer to a dbi result structure
673                      which contains the notes
674 
675   dbi_conn conn the connection
676 
677   int mode 1 = reference entry 2 = keyword entry 4 = author entry
678            8 = periodical entry
679 
680   const char* user name of current user
681 
682   int share 1=share by default, 0=hide by default
683 
684   int include_lists 0=ignore reference lists 1=include reference lists
685 
686   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
request_notes_by_ref(dbi_conn conn,unsigned long long n_id,int mode,const char * user,int share,int include_lists)687 dbi_result request_notes_by_ref(dbi_conn conn, unsigned long long n_id, int mode, const char* user, int share, int include_lists) {
688   int nis_first = 1;
689   char* sql_command;
690   char* sql_chunk;
691   const char* drivername;
692   char userspec[512];
693   char namespec[512];
694   dbi_result dbires;
695   dbi_driver driver;
696 
697   driver = dbi_conn_get_driver(conn);
698   drivername = dbi_driver_get_name(driver);
699 
700   sql_command = malloc(4096);
701 
702   if (sql_command == NULL) {
703     return NULL;
704   }
705 
706   sql_chunk = malloc(2048);
707 
708   if (sql_chunk == NULL) {
709     free(sql_command);
710     return NULL;
711   }
712 
713   *sql_command = '\0';
714 
715   /* assemble substring which selects the notes based on the share settings */
716   if (share) {
717     snprintf(userspec, 512, "(t_user.user_name=\'%s\' OR (t_user.user_name!=\'%s\' AND t_note.note_share!=0))", user, user);
718   }
719   else {
720     snprintf(userspec, 512, "(t_user.user_name=\'%s\' OR (t_user.user_name!=\'%s\' AND t_note.note_share=1))", user, user);
721   }
722 
723   /* assemble substring which selects the notes based on the note key
724      to exclude reference lists */
725   if (!include_lists) {
726     size_t namelen;
727 
728     namelen = strlen(user);
729     snprintf(namespec, 512, " AND NOT (%s(t_note.note_key%s1%s %d)=\'%s\') ", my_dbi_driver_get_cap(driver, "substring"), my_dbi_driver_get_cap(driver, "substring_from"), my_dbi_driver_get_cap(driver, "substring_for"), namelen, user);
730   }
731   else {
732     *namespec = 0;
733   }
734 
735   if (!strcmp(my_dbi_driver_get_cap(driver, "union"), "t")) {
736     if (mode & REFERENCE) {
737       sprintf(sql_chunk,
738 	      "SELECT DISTINCT t_note.note_id, t_note.note_key, t_note.note_title, t_note.note_user_id, t_note.note_date, t_note.note_content, t_note.note_content_type, t_note.note_content_xmllang FROM t_note INNER JOIN t_xnote ON t_note.note_id=t_xnote.note_id INNER JOIN t_refdb ON t_xnote.xref_id=t_refdb.refdb_id INNER JOIN t_user ON t_note.note_user_id=t_user.user_id WHERE %s AND t_refdb.refdb_id="ULLSPEC" AND t_xnote.xnote_type=\'REFERENCE\'%s",
739 	      userspec,
740 	      (unsigned long long)n_id,
741 	      namespec);
742 
743       strcat(sql_command, sql_chunk);
744       nis_first = 0;
745     }
746 
747     if (mode & KEYWORD) {
748       sprintf(sql_chunk,
749 	      "SELECT DISTINCT t_note.note_id, t_note.note_key, t_note.note_title, t_note.note_user_id, t_note.note_date, t_note.note_content, t_note.note_content_type, t_note.note_content_xmllang FROM t_note INNER JOIN t_xnote ON t_note.note_id=t_xnote.note_id INNER JOIN t_user ON t_note.note_user_id=t_user.user_id INNER JOIN t_keyword ON t_xnote.xref_id=t_keyword.keyword_id INNER JOIN t_xkeyword ON t_xkeyword.keyword_id=t_keyword.keyword_id INNER JOIN t_refdb ON t_xkeyword.xref_id=t_refdb.refdb_id WHERE %s AND t_refdb.refdb_id="ULLSPEC" AND t_xnote.xnote_type=\'KEYWORD\'%s",
750 	      userspec,
751 	      (unsigned long long)n_id,
752 	      namespec);
753 
754       if (!nis_first) {
755 	strcat(sql_command, " UNION ");
756       }
757       strcat(sql_command, sql_chunk);
758       nis_first = 0;
759     }
760 
761     if (mode & AUTHOR) {
762       sprintf(sql_chunk,
763 	      "SELECT DISTINCT t_note.note_id, t_note.note_key, t_note.note_title, t_note.note_user_id, t_note.note_date, t_note.note_content, t_note.note_content_type, t_note.note_content_xmllang FROM t_note INNER JOIN t_xnote ON t_note.note_id=t_xnote.note_id INNER JOIN t_user ON t_note.note_user_id=t_user.user_id INNER JOIN t_author ON t_xnote.xref_id=t_author.author_id INNER JOIN t_xauthor ON t_xauthor.author_id=t_author.author_id INNER JOIN t_refdb ON t_xauthor.refdb_id=t_refdb.refdb_id WHERE %s AND t_refdb.refdb_id="ULLSPEC" AND t_xnote.xnote_type=\'AUTHOR\'%s",
764 	      userspec,
765 	      (unsigned long long)n_id,
766 	      namespec);
767 
768       if (!nis_first) {
769 	strcat(sql_command, " UNION ");
770       }
771       strcat(sql_command, sql_chunk);
772       nis_first = 0;
773     }
774 
775     if (mode & PERIODICAL) {
776       sprintf(sql_chunk,
777 	      "SELECT DISTINCT t_note.note_id, t_note.note_key, t_note.note_title, t_note.note_user_id, t_note.note_date, t_note.note_content, t_note.note_content_type, t_note.note_content_xmllang FROM t_note INNER JOIN t_xnote ON t_note.note_id=t_xnote.note_id INNER JOIN t_periodical ON t_xnote.xref_id=t_periodical.periodical_id INNER JOIN t_refdb ON t_refdb.refdb_periodical_id=t_periodical.periodical_id INNER JOIN t_user ON t_note.note_user_id=t_user.user_id WHERE %s AND t_refdb.refdb_id="ULLSPEC" AND t_xnote.xnote_type=\'PERIODICAL\'%s",
778 	      userspec,
779 	      (unsigned long long)n_id,
780 	      namespec);
781 
782       if (!nis_first) {
783 	strcat(sql_command, " UNION ");
784       }
785       strcat(sql_command, sql_chunk);
786     }
787   }
788   else {
789     /* if the db engine does not support UNION, emulate UNION with
790        SELECT INTO temptable */
791     if (!strcmp(drivername, "mysql")) {
792       /* mysql */
793       strcpy(sql_command, "CREATE TEMPORARY TABLE t_noteunion \
794                                     (note_id BIGINT, \
795                                     note_key VARCHAR(255), \
796                                     note_title VARCHAR(255), \
797                                     note_content BLOB, \
798                                     note_content_type VARCHAR(255), \
799                                     note_content_xmllang VARCHAR(255), \
800                                     note_user_id BIGINT, \
801                                     note_date DATETIME)");
802     }
803     else if (!strcmp(drivername, "pgsql")) {
804       /* pgsql */
805       strcpy(sql_command, "CREATE TEMPORARY TABLE t_noteunion \
806                                    (note_id BIGSERIAL, \
807                                     note_key VARCHAR(255) UNIQUE, \
808                                     note_title VARCHAR(255), \
809                                     note_content TEXT, \
810                                     note_content_type VARCHAR(255), \
811                                     note_content_xmllang VARCHAR(255), \
812                                     note_user_id BIGINT, \
813                                     note_date DATE)");
814     }
815     else if (!strcmp(drivername, "sqlite")) {
816       /* sqlite */
817       strcpy(sql_command, "CREATE TEMPORARY TABLE t_noteunion \
818                                    (note_id INTEGER, \
819                                     note_key TEXT, \
820                                     note_title TEXT, \
821                                     note_content_type TEXT, \
822                                     note_content_xmllang TEXT, \
823                                     note_user_id INTEGER, \
824                                     note_date DATE, \
825                                     note_content TEXT)");
826     }
827     else if (!strcmp(drivername, "sqlite3")) {
828       /* sqlite3 */
829       strcpy(sql_command, "CREATE TEMPORARY TABLE t_noteunion \
830                                    (note_id BIGINT, \
831                                     note_key TEXT, \
832                                     note_title TEXT, \
833                                     note_content_type TEXT, \
834                                     note_content_xmllang TEXT, \
835                                     note_user_id BIGINT, \
836                                     note_date DATE, \
837                                     note_content TEXT)");
838     }
839     /* else: will be caught earlier */
840 
841     LOG_PRINT(LOG_DEBUG, sql_command);
842     dbires = dbi_conn_query(conn, sql_command);
843 
844     if (!dbires) {
845       LOG_PRINT(LOG_WARNING, "create temporary table failed");
846       free(sql_command);
847       free(sql_chunk);
848       return NULL;
849     }
850 
851 
852     /* now collect the data in the temporary table */
853     if (mode & REFERENCE) {
854       sprintf(sql_chunk,
855 	      "INSERT INTO t_noteunion (note_id, note_key, note_title, note_user_id, note_date, note_content, note_content_type, note_content_xmllang) SELECT DISTINCT t_note.note_id, t_note.note_key, t_note.note_title, t_note.note_user_id, t_note.note_date, t_note.note_content, t_note.note_content_type, t_note.note_content_xmllang FROM t_note INNER JOIN t_xnote ON t_note.note_id=t_xnote.note_id INNER JOIN t_user ON t_note.note_user_id=t_user.user_id INNER JOIN t_refdb ON t_xnote.xref_id=t_refdb.refdb_id WHERE %s AND t_refdb.refdb_id="ULLSPEC" AND t_xnote.xnote_type=\'REFERENCE\'%s",
856 	      userspec,
857 	      (unsigned long long)n_id,
858 	      namespec);
859 
860       LOG_PRINT(LOG_DEBUG, sql_chunk);
861       dbires = dbi_conn_query(conn, sql_chunk);
862 
863       if (!dbires) {
864 	LOG_PRINT(LOG_WARNING, "insert into temporary table failed");
865 /* 	free(sql_command); */
866 /* 	free(sql_chunk); */
867 /* 	return NULL; */
868       }
869     }
870 
871     if (mode & KEYWORD) {
872       sprintf(sql_chunk,
873 	      "INSERT INTO t_noteunion (note_id, note_key, note_title, note_user_id, note_date, note_content, note_content_type, note_content_xmllang) SELECT DISTINCT t_note.note_id, t_note.note_key, t_note.note_title, t_note.note_user_id, t_note.note_date, t_note.note_content FROM t_note INNER JOIN t_xnote ON t_note.note_id=t_xnote.note_id INNER JOIN t_user ON t_note.note_user_id=t_user.user_id INNER JOIN t_keyword ON t_xnote.xref_id=t_keyword.keyword_id INNER JOIN t_xkeyword ON t_xkeyword.keyword_id=t_keyword.keyword_id INNER JOIN t_refdb ON t_xkeyword.xref_id=t_refdb.refdb_id WHERE %s AND t_refdb.refdb_id="ULLSPEC" AND t_xnote.xnote_type=\'KEYWORD\'%s",
874 	      userspec,
875 	      (unsigned long long)n_id,
876 	      namespec);
877 
878       LOG_PRINT(LOG_DEBUG, sql_chunk);
879       dbires = dbi_conn_query(conn, sql_chunk);
880 
881       if (!dbires) {
882 	LOG_PRINT(LOG_WARNING, "insert into temporary table failed");
883 /* 	free(sql_command); */
884 /* 	free(sql_chunk); */
885 /* 	return NULL; */
886       }
887     }
888 
889     if (mode & AUTHOR) {
890       sprintf(sql_chunk,
891 	      "INSERT INTO t_noteunion (note_id, note_key, note_title, note_user_id, note_date, note_content, note_content_type, note_content_xmllang) SELECT DISTINCT t_note.note_id, t_note.note_key, t_note.note_title, t_note.note_user_id, t_note.note_date, t_note.note_content, t_note.note_content_type, t_note.note_content_xmllang FROM t_note INNER JOIN t_xnote ON t_note.note_id=t_xnote.note_id INNER JOIN t_author ON t_xnote.xref_id=t_author.author_id INNER JOIN t_xauthor ON t_xauthor.author_id=t_author.author_id INNER JOIN t_refdb ON t_xauthor.refdb_id=t_refdb.refdb_id INNER JOIN t_user ON t_note.note_user_id=t_user.user_id WHERE %s AND t_refdb.refdb_id="ULLSPEC" AND t_xnote.xnote_type=\'AUTHOR\'%s",
892 	      userspec,
893 	      (unsigned long long)n_id,
894 	      namespec);
895 
896       LOG_PRINT(LOG_DEBUG, sql_chunk);
897       dbires = dbi_conn_query(conn, sql_chunk);
898 
899       if (!dbires) {
900 	LOG_PRINT(LOG_WARNING, "insert into temporary table failed");
901 /* 	free(sql_command); */
902 /* 	free(sql_chunk); */
903 /* 	return NULL; */
904       }
905     }
906 
907     if (mode & PERIODICAL) {
908       sprintf(sql_chunk,
909 	      "INSERT INTO t_noteunion (note_id, note_key, note_title, note_user_id, note_date, note_content, note_content_type, note_content_xmllang) SELECT DISTINCT t_note.note_id, t_note.note_key, t_note.note_title, t_note.note_user_id, t_note.note_date, t_note.note_content, t_note.note_content_type, t_note.note_content_xmllang FROM t_note INNER JOIN t_xnote ON t_note.note_id=t_xnote.note_id INNER JOIN t_periodical ON t_xnote.xref_id=t_periodical.periodical_id INNER JOIN t_refdb ON t_refdb.refdb_periodical_id=t_periodical.periodical_id INNER JOIN t_user ON t_note.note_user_id=t_user.user_id WHERE %s AND t_refdb.refdb_id="ULLSPEC" AND t_xnote.xnote_type=\'PERIODICAL\'%s",
910 	      userspec,
911 	      (unsigned long long)n_id,
912 	      namespec);
913 
914       LOG_PRINT(LOG_DEBUG, sql_chunk);
915       dbires = dbi_conn_query(conn, sql_chunk);
916 
917       if (!dbires) {
918 	LOG_PRINT(LOG_WARNING, "insert into temporary table failed");
919 /* 	free(sql_command); */
920 /* 	free(sql_chunk); */
921 /* 	return NULL; */
922       }
923     }
924 
925     /* now retrieve the datasets again */
926     sprintf(sql_command, "SELECT DISTINCT note_id, note_key, note_title, note_user_id, note_date, note_content, note_content_type, note_content_xmllang FROM t_noteunion");
927 
928   }
929 
930   free(sql_chunk);
931 
932   LOG_PRINT(LOG_DEBUG, sql_command);
933   dbires = dbi_conn_query(conn, sql_command);
934 
935  /*  if (!dbires) { */
936     /* begin weird hack */
937 /*     sprintf(sql_command, "SELECT refdb_id FROM t_refdb where refdb_id=-1"); */
938 /*     LOG_PRINT(LOG_DEBUG, sql_command); */
939 /*     dbires = dbi_conn_query(conn, sql_command); */
940     /* end weird hack */
941 /*     return NULL; */
942 /*   } */
943 
944   free(sql_command);
945 
946   return dbires;
947 }
948 
949 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
950   free_request_notes_by_ref(): cleans up the resources used by a previous
951                                call to request_notes_by_ref
952 
953   int free_request_notes_by_ref returns 0 on success and 1 if an error
954                                occurs
955 
956   dbi_conn conn the connection
957 
958   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
free_request_notes_by_ref(dbi_conn conn)959 int free_request_notes_by_ref(dbi_conn conn) {
960   dbi_result dbires;
961   char sql_command[23];
962 
963   /* check whether we used a temporary table. If yes, drop it */
964   if (strcmp(my_dbi_driver_get_cap(dbi_conn_get_driver(conn), "union"), "t")) {
965     /* get rid of the temporary table */
966     strcpy(sql_command, "DROP TABLE t_noteunion");
967     LOG_PRINT(LOG_DEBUG, sql_command);
968     dbires = dbi_conn_query(conn, sql_command);
969 
970     if (!dbires) {
971       LOG_PRINT(LOG_WARNING, "drop temporary table failed");
972       return 1;
973     }
974   }
975 
976   return 0;
977 }
978 
979 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
980   request_links(): prepares the retrieval of links
981 
982   dbi_result request_links returns a pointer to a dbi result structure
983                      which contains the links
984 
985   dbi_conn conn the connection
986 
987   int mode 0 = reference entry 1 = keyword entry 2 = author entry
988            3 = periodical entry
989 
990   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
request_links(dbi_conn conn,unsigned long long n_id,int mode)991 dbi_result request_links(dbi_conn conn, unsigned long long n_id, int mode) {
992   char* sql_command;
993   char linktype[4][11] = {"REFERENCE", "KEYWORD", "AUTHOR", "PERIODICAL"};
994   dbi_result dbires;
995 
996   sql_command = malloc(512);
997 
998   if (sql_command == NULL) {
999     return NULL;
1000   }
1001 
1002   if (!mode) {
1003     /* link to refererence. Need citation key */
1004     sprintf(sql_command, "SELECT t_refdb.refdb_citekey FROM t_refdb INNER JOIN t_xnote ON t_refdb.refdb_id=t_xnote.xref_id INNER JOIN t_note ON t_xnote.note_id= t_note.note_id WHERE t_xnote.xnote_type='\%s\' AND t_note.note_id="ULLSPEC, linktype[mode], (unsigned long long)n_id);
1005   }
1006   else if (mode == 1) {
1007     /* link to keyword. Need keyword name */
1008     sprintf(sql_command, "SELECT t_keyword.keyword_name FROM t_keyword INNER JOIN t_xnote ON t_keyword.keyword_id=t_xnote.xref_id INNER JOIN t_note ON t_xnote.note_id= t_note.note_id WHERE t_xnote.xnote_type='\%s\' AND t_note.note_id="ULLSPEC, linktype[mode], (unsigned long long)n_id);
1009   }
1010   else if (mode == 2) {
1011     /* link to author. Need author name */
1012     sprintf(sql_command, "SELECT t_author.author_name FROM t_author INNER JOIN t_xnote ON t_author.author_id=t_xnote.xref_id INNER JOIN t_note ON t_xnote.note_id= t_note.note_id WHERE t_xnote.xnote_type='\%s\' AND t_note.note_id="ULLSPEC, linktype[mode], (unsigned long long)n_id);
1013   }
1014   else /* if (mode == 3) */ {
1015     /* link to periodical. Need one of the periodical names */
1016     sprintf(sql_command, "SELECT t_periodical.periodical_name,t_periodical.periodical_abbrev,t_periodical.periodical_custabbrev1,t_periodical.periodical_custabbrev2 FROM t_periodical INNER JOIN t_xnote ON t_periodical.periodical_id=t_xnote.xref_id INNER JOIN t_note ON t_xnote.note_id=t_note.note_id WHERE t_xnote.xnote_type='\%s\' AND t_note.note_id="ULLSPEC, linktype[mode], (unsigned long long)n_id);
1017   }
1018 
1019   LOG_PRINT(LOG_DEBUG, sql_command);
1020   dbires = dbi_conn_query(conn, sql_command);
1021   free(sql_command);
1022   if (!dbires) {
1023     return NULL;
1024   }
1025 
1026   return dbires;
1027 }
1028 
1029 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1030   get_link(): retrieves a link
1031 
1032   char* get_link returns a pointer to a string containing the
1033                      link
1034 
1035   dbi_result dbires database query result, pointing to the current
1036                     dataset
1037 
1038   int *ptr_mode pointer to an integer to request the link type. This
1039                     argument is currently ignored for all but periodical
1040 		    links. Initialize *ptr_mode to one of: 0 = reference entry
1041 		    1 = keyword entry 2 = author entry 3 = periodical entry
1042 		    For successfully retrieved periodical entries,
1043 		    *ptr_mode will be updated to reflect the type of the
1044 		    periodical name used: 0 = full name, 1 = abbreviated
1045 		    name, 2 = custom abbreviation 1, 3 = custom abbreviation 2
1046 
1047   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_link(dbi_result dbires,int * ptr_mode)1048 const char* get_link(dbi_result dbires, int *ptr_mode) {
1049   const char* result = NULL;
1050   int i = 1; /* index into a dbi result, starts at 1 */
1051 
1052   if (dbi_result_next_row(dbires)) {
1053     if (*ptr_mode == 3) {
1054       /* periodical links require special treatment as we don't know
1055 	 in advance which periodical names are available */
1056       while (i < 5 && (!result || !*result)) {
1057 	result = dbi_result_get_string_idx(dbires, i);
1058 	if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1059 	  return NULL;
1060 	}
1061 	else if (result && *result) {
1062 	  *ptr_mode = i-1;
1063 	  return result;
1064 	}
1065 	i++;
1066       }
1067       return NULL;
1068     }
1069     else {
1070       result = dbi_result_get_string_idx(dbires, 1);
1071       if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1072 	return NULL;
1073       }
1074       else {
1075 	return result;
1076       }
1077     }
1078   }
1079   else {
1080     return NULL;
1081   }
1082 }
1083 
1084   /* 0  refdb_id             ID  - (if numeric)
1085      1  refdb_type           TY  -
1086      2  refdb_pubyear        PY  - (partial)
1087      3  refdb_startpage      SP  -
1088      4  refdb_endpage        EP  -
1089      5  refdb_abstract       N2  -
1090      6  refdb_title          TI  -
1091      7  refdb_volume         VL  -
1092      8  refdb_issue          CP  -
1093      9  refdb_booktitle      BT  -
1094     10  refdb_city           CY  -
1095     11  refdb_publisher      PB  -
1096     12  refdb_title_series   T3  -
1097     13  refdb_address        AD  -
1098     14  refdb_url            UR  -
1099     15  refdb_issn           SN  -
1100     16  refdb_periodical_id  JO  - (indirect)
1101     17  refdb_pyother_info   PY  - (partial)
1102     18  refdb_secyear        Y2  - (partial)
1103     19  refdb_secother_info  Y2  - (partial)
1104     20  refdb_user1          U1  -
1105     21  refdb_user2          U2  -
1106     22  refdb_user3          U3  -
1107     23  refdb_user4          U4  -
1108     24  refdb_user5          U5  -
1109     28  refdb_citekey        ID  - (if non-numeric)
1110 */
1111 
1112 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1113   get_refdb_id(): retrieves the refdb_id element from a query result
1114 
1115   char* get_refdb_id returns a pointer to a string containing the
1116                      refdb_id element
1117 
1118   dbi_result dbires database query result, pointing to the current
1119                     dataset
1120 
1121   char* id ptr to string that will receive the id. Must be long
1122                     enough for the representation of an unsigned
1123 		    long long number
1124 
1125   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_id(dbi_result dbires,char * id)1126 char* get_refdb_id(dbi_result dbires, char* id) {
1127   unsigned long long n_id;
1128   dbi_error_flag errflag;
1129 
1130   n_id = my_dbi_result_get_idval(dbires, "refdb_id");
1131   errflag = dbi_conn_error_flag(dbi_result_get_conn(dbires));
1132 
1133   if (n_id == 0 || errflag) { /* all IDs > 0 so this must be an error */
1134     return NULL;
1135   }
1136   else {
1137     sprintf(id, ULLSPEC, (unsigned long long)n_id);
1138     return id;
1139   }
1140 }
1141 
1142 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1143   get_refdb_citekey(): retrieves the refdb_citekey element from a query result
1144 
1145   char* get_refdb_citekey returns a pointer to a string containing the
1146                      refdb_citekey element
1147 
1148   dbi_result dbires database query result, pointing to the current
1149                     dataset
1150 
1151   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_citekey(dbi_result dbires)1152 const char* get_refdb_citekey(dbi_result dbires) {
1153   const char* result;
1154 
1155   result = dbi_result_get_string(dbires, "refdb_citekey");
1156   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1157     return NULL;
1158   }
1159   else {
1160     return result;
1161   }
1162 }
1163 
1164 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1165   get_refdb_type(): retrieves the refdb_type element from a query result
1166 
1167   char* get_refdb_type returns a pointer to a string containing the
1168                      refdb_type element
1169 
1170   dbi_result dbires database query result, pointing to the current
1171                     dataset
1172 
1173   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_type(dbi_result dbires)1174 const char* get_refdb_type(dbi_result dbires) {
1175   const char* result;
1176 
1177   result = dbi_result_get_string(dbires, "refdb_type");
1178   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1179     return NULL;
1180   }
1181   else {
1182     return result;
1183   }
1184 }
1185 
1186 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1187   get_refdb_pubyear(): retrieves the refdb_pubyear element from a query result
1188 
1189   char* get_refdb_pubyear returns a pointer to a string containing the
1190                      refdb_pubyear element
1191 
1192   dbi_result dbires database query result, pointing to the current
1193                     dataset
1194 
1195   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_pubyear(dbi_result dbires,char * year)1196 char* get_refdb_pubyear(dbi_result dbires, char* year) {
1197   int n_year;
1198 
1199   n_year = dbi_result_get_short(dbires, "refdb_pubyear");
1200 
1201   if (dbi_conn_error_flag(dbi_result_get_conn(dbires)) == 0) {
1202     if (n_year != 0) {
1203       sprintf(year, "%hd", n_year);
1204     }
1205     else {
1206       strcpy(year, "nd");
1207     }
1208     return year;
1209   }
1210   else {
1211     return NULL; /* have no year */
1212   }
1213 }
1214 
1215 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1216   get_refdb_startpage(): retrieves the refdb_startpage element from a query result
1217 
1218   char* get_refdb_startpage returns a pointer to a string containing the
1219                      refdb_startpage element
1220 
1221   dbi_result dbires database query result, pointing to the current
1222                     dataset
1223 
1224   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_startpage(dbi_result dbires)1225 const char* get_refdb_startpage(dbi_result dbires) {
1226   const char* result;
1227 
1228   result = dbi_result_get_string(dbires, "refdb_startpage");
1229   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1230     return NULL;
1231   }
1232   else {
1233     return result;
1234   }
1235 }
1236 
1237 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1238   get_refdb_endpage(): retrieves the refdb_endpage element from a query result
1239 
1240   char* get_refdb_endpage returns a pointer to a string containing the
1241                      refdb_endpage element
1242 
1243   dbi_result dbires database query result, pointing to the current
1244                     dataset
1245 
1246   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_endpage(dbi_result dbires)1247 const char* get_refdb_endpage(dbi_result dbires) {
1248   const char* result;
1249 
1250   result = dbi_result_get_string(dbires, "refdb_endpage");
1251   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1252     return NULL;
1253   }
1254   else {
1255     return result;
1256   }
1257 }
1258 
1259 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1260   get_refdb_abstract_copy(): retrieves the refdb_abstract element from
1261                              a query result
1262 
1263   char* get_refdb_abstract_copy returns a pointer to a string containing the
1264                      refdb_abstract element. The string is allocated and
1265 		     must be freed by the caller
1266 
1267   dbi_result dbires database query result, pointing to the current
1268                     dataset
1269 
1270   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_abstract_copy(dbi_result dbires)1271 char* get_refdb_abstract_copy(dbi_result dbires) {
1272   return my_dbi_result_get_string_copy(dbires, "refdb_abstract");
1273 }
1274 
1275 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1276   get_refdb_title_copy(): retrieves the refdb_title element from a query result
1277 
1278   char* get_refdb_title_copy returns a pointer to a string containing the
1279                      refdb_title element. The string is allocated and
1280 		     must be freed by the caller
1281 
1282   dbi_result dbires database query result, pointing to the current
1283                     dataset
1284 
1285   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_title_copy(dbi_result dbires)1286 char* get_refdb_title_copy(dbi_result dbires) {
1287   return my_dbi_result_get_string_copy(dbires, "refdb_title");
1288 }
1289 
1290 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1291   get_refdb_volume(): retrieves the refdb_volume element from a query result
1292 
1293   char* get_refdb_volume returns a pointer to a string containing the
1294                      refdb_volume element
1295 
1296   dbi_result dbires database query result, pointing to the current
1297                     dataset
1298 
1299   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_volume(dbi_result dbires)1300 const char* get_refdb_volume(dbi_result dbires) {
1301   const char* result;
1302 
1303   result = dbi_result_get_string(dbires, "refdb_volume");
1304   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1305     return NULL;
1306   }
1307   else {
1308     return result;
1309   }
1310 }
1311 
1312 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1313   get_refdb_issue(): retrieves the refdb_issue element from a query result
1314 
1315   char* get_refdb_issue  returns a pointer to a string containing the
1316                      refdb_issue element
1317 
1318   dbi_result dbires database query result, pointing to the current
1319                     dataset
1320 
1321   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_issue(dbi_result dbires)1322 const char* get_refdb_issue(dbi_result dbires) {
1323   const char* result;
1324 
1325   result = dbi_result_get_string(dbires, "refdb_issue");
1326   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1327     return NULL;
1328   }
1329   else {
1330     return result;
1331   }
1332 }
1333 
1334 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1335   get_refdb_booktitle_copy(): retrieves the refdb_booktitle element from a query result
1336 
1337   char* get_refdb_booktitle_copy returns a pointer to a string containing the
1338                      refdb_booktitle element. The string is allocated and
1339 		     must be freed by the caller
1340 
1341   dbi_result dbires database query result, pointing to the current
1342                     dataset
1343 
1344   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_booktitle_copy(dbi_result dbires)1345 char* get_refdb_booktitle_copy(dbi_result dbires) {
1346   return my_dbi_result_get_string_copy(dbires, "refdb_booktitle");
1347 }
1348 
1349 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1350   get_refdb_city(): retrieves the refdb_city element from a query result
1351 
1352   char* get_refdb_city returns a pointer to a string containing the
1353                      refdb_city element
1354 
1355   dbi_result dbires database query result, pointing to the current
1356                     dataset
1357 
1358   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_city(dbi_result dbires)1359 const char* get_refdb_city(dbi_result dbires) {
1360   const char* result;
1361 
1362   result = dbi_result_get_string(dbires, "refdb_city");
1363   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1364     return NULL;
1365   }
1366   else {
1367     return result;
1368   }
1369 }
1370 
1371 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1372   get_refdb_publisher(): retrieves the refdb_publisher element from a query result
1373 
1374   char* get_refdb_publisher returns a pointer to a string containing the
1375                      refdb_publisher element
1376 
1377   dbi_result dbires database query result, pointing to the current
1378                     dataset
1379 
1380   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_publisher(dbi_result dbires)1381 const char* get_refdb_publisher(dbi_result dbires) {
1382   const char* result;
1383 
1384   result = dbi_result_get_string(dbires, "refdb_publisher");
1385   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1386     return NULL;
1387   }
1388   else {
1389     return result;
1390   }
1391 }
1392 
1393 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1394   get_refdb_title_series_copy(): retrieves the refdb_title_series
1395                                  element from a query result
1396 
1397   char* get_refdb_title_series_copy returns a pointer to a string
1398                      containing the refdb_title_series element.
1399                      The string is allocated and
1400 		     must be freed by the caller
1401 
1402   dbi_result dbires database query result, pointing to the current
1403                     dataset
1404 
1405   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_title_series_copy(dbi_result dbires)1406 char* get_refdb_title_series_copy(dbi_result dbires) {
1407   return my_dbi_result_get_string_copy(dbires, "refdb_title_series");
1408 }
1409 
1410 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1411   get_refdb_address_copy(): retrieves the refdb_address element from a
1412                             query result
1413 
1414   char* get_refdb_address_copy returns a pointer to a string containing the
1415                      refdb_address element. The string is allocated and
1416 		     must be freed by the caller
1417 
1418   dbi_result dbires database query result, pointing to the current
1419                     dataset
1420 
1421   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_address_copy(dbi_result dbires)1422 char* get_refdb_address_copy(dbi_result dbires) {
1423   return my_dbi_result_get_string_copy(dbires, "refdb_address");
1424 }
1425 
1426 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1427   get_refdb_url_copy(): retrieves the refdb_url element from a query result
1428 
1429   char* get_refdb_url_copy returns a pointer to a string containing the
1430                      refdb_url element. The string is allocated and
1431 		     must be freed by the caller
1432 
1433   dbi_result dbires database query result, pointing to the current
1434                     dataset
1435 
1436   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
1437 /* char* get_refdb_url_copy(dbi_result dbires) { */
1438 /*   return my_dbi_result_get_string_copy(dbires, "refdb_url"); */
1439 /* } */
1440 
1441 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1442   get_refdb_issn(): retrieves the refdb_issn element from a query result
1443 
1444   char* get_refdb_issn returns a pointer to a string containing the
1445                      refdb_issn element
1446 
1447   dbi_result dbires database query result, pointing to the current
1448                     dataset
1449 
1450   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_issn(dbi_result dbires)1451 const char* get_refdb_issn(dbi_result dbires) {
1452   const char* result;
1453 
1454   result = dbi_result_get_string(dbires, "refdb_issn");
1455   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1456     return NULL;
1457   }
1458   else {
1459     return result;
1460   }
1461 }
1462 
1463 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1464   get_refdb_pyother_info(): retrieves the refdb_pyother_info element from a query result
1465 
1466   char* get_refdb_pyother_info returns a pointer to a string containing the
1467                      refdb_pyother_info element
1468 
1469   dbi_result dbires database query result, pointing to the current
1470                     dataset
1471 
1472   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_pyother_info(dbi_result dbires)1473 const char* get_refdb_pyother_info(dbi_result dbires) {
1474   const char* result;
1475 
1476   result = dbi_result_get_string(dbires, "refdb_pyother_info");
1477   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1478     return NULL;
1479   }
1480   else {
1481     return result;
1482   }
1483 }
1484 
1485 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1486   get_refdb_secyear(): retrieves the refdb_secyear element from a query result
1487 
1488   char* get_refdb_secyear returns a pointer to a string containing the
1489                      refdb_secyear element
1490 
1491   dbi_result dbires database query result, pointing to the current
1492                     dataset
1493 
1494   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_secyear(dbi_result dbires,char * year)1495 char* get_refdb_secyear(dbi_result dbires, char* year) {
1496   int n_year;
1497 
1498   n_year = dbi_result_get_short(dbires, "refdb_secyear");
1499 
1500   if (n_year != 0 && dbi_conn_error_flag(dbi_result_get_conn(dbires)) == 0) {
1501     sprintf(year, "%hd", n_year);
1502     return year;
1503   }
1504   else {
1505     return NULL; /* have no year */
1506   }
1507 }
1508 
1509 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1510   get_refdb_secother_info(): retrieves the refdb_secother_info element from a query result
1511 
1512   char* get_refdb_secother_info returns a pointer to a string containing the
1513                      refdb_secother_info element
1514 
1515   dbi_result dbires database query result, pointing to the current
1516                     dataset
1517 
1518   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_secother_info(dbi_result dbires)1519 const char* get_refdb_secother_info(dbi_result dbires) {
1520   const char* result;
1521 
1522   result = dbi_result_get_string(dbires, "refdb_secother_info");
1523   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1524     return NULL;
1525   }
1526   else {
1527     return result;
1528   }
1529 }
1530 
1531 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1532   get_refdb_user(): retrieves refdb_user elements from a query result
1533 
1534   char* get_refdb_user returns a pointer to a string containing the
1535                      refdb_user element
1536 
1537   dbi_result dbires database query result, pointing to the current
1538                     dataset
1539 
1540   int n_fieldno  number of user field to retrieve (1-5)
1541 
1542   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_user(dbi_result dbires,int n_fieldno)1543 const char* get_refdb_user(dbi_result dbires, int n_fieldno) {
1544   switch(n_fieldno) {
1545   case 1:
1546     return get_refdb_user1(dbires);
1547     break;
1548   case 2:
1549     return get_refdb_user2(dbires);
1550     break;
1551   case 3:
1552     return get_refdb_user3(dbires);
1553     break;
1554   case 4:
1555     return get_refdb_user4(dbires);
1556     break;
1557   case 5:
1558     return get_refdb_user5(dbires);
1559     break;
1560   default:
1561     return NULL;
1562   }
1563 }
1564 
1565 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1566   get_refdb_user1(): retrieves the refdb_user1 element from a query result
1567 
1568   char* get_refdb_user1 returns a pointer to a string containing the
1569                      refdb_user1 element
1570 
1571   dbi_result dbires database query result, pointing to the current
1572                     dataset
1573 
1574   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_user1(dbi_result dbires)1575 const char* get_refdb_user1(dbi_result dbires) {
1576   const char* result;
1577 
1578   result = dbi_result_get_string(dbires, "refdb_user1");
1579   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1580     return NULL;
1581   }
1582   else {
1583     return result;
1584   }
1585 }
1586 
1587 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1588   get_refdb_user2(): retrieves the refdb_user2 element from a query result
1589 
1590   char* get_refdb_user1 returns a pointer to a string containing the
1591                      refdb_user2 element
1592 
1593   dbi_result dbires database query result, pointing to the current
1594                     dataset
1595 
1596   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_user2(dbi_result dbires)1597 const char* get_refdb_user2(dbi_result dbires) {
1598   const char* result;
1599 
1600   result = dbi_result_get_string(dbires, "refdb_user2");
1601   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1602     return NULL;
1603   }
1604   else {
1605     return result;
1606   }
1607 }
1608 
1609 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1610   get_refdb_user3(): retrieves the refdb_user3 element from a query result
1611 
1612   char* get_refdb_user3 returns a pointer to a string containing the
1613                      refdb_user3 element
1614 
1615   dbi_result dbires database query result, pointing to the current
1616                     dataset
1617 
1618   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_user3(dbi_result dbires)1619 const char* get_refdb_user3(dbi_result dbires) {
1620   const char* result;
1621 
1622   result = dbi_result_get_string(dbires, "refdb_user3");
1623   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1624     return NULL;
1625   }
1626   else {
1627     return result;
1628   }
1629 }
1630 
1631 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1632   get_refdb_user4(): retrieves the refdb_user4 element from a query result
1633 
1634   char* get_refdb_user4 returns a pointer to a string containing the
1635                      refdb_user1 element
1636 
1637   dbi_result dbires database query result, pointing to the current
1638                     dataset
1639 
1640   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_user4(dbi_result dbires)1641 const char* get_refdb_user4(dbi_result dbires) {
1642   const char* result;
1643 
1644   result = dbi_result_get_string(dbires, "refdb_user4");
1645   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1646     return NULL;
1647   }
1648   else {
1649     return result;
1650   }
1651 }
1652 
1653 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1654   get_refdb_user5(): retrieves the refdb_user5 element from a query result
1655 
1656   char* get_refdb_user5 returns a pointer to a string containing the
1657                      refdb_user5 element
1658 
1659   dbi_result dbires database query result, pointing to the current
1660                     dataset
1661 
1662   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_user5(dbi_result dbires)1663 const char* get_refdb_user5(dbi_result dbires) {
1664   const char* result;
1665 
1666   result = dbi_result_get_string(dbires, "refdb_user5");
1667   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1668     return NULL;
1669   }
1670   else {
1671     return result;
1672   }
1673 }
1674 
1675 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1676   get_refdb_typeofwork(): retrieves the refdb_typeofwork element from a query result
1677 
1678   char* get_refdb_typeofwork returns a pointer to a string containing the
1679                      refdb_typeofwork element
1680 
1681   dbi_result dbires database query result, pointing to the current
1682                     dataset
1683 
1684   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_typeofwork(dbi_result dbires)1685 const char* get_refdb_typeofwork(dbi_result dbires) {
1686   const char* result;
1687 
1688   result = dbi_result_get_string(dbires, "refdb_typeofwork");
1689   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1690     return NULL;
1691   }
1692   else {
1693     return result;
1694   }
1695 }
1696 
1697 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1698   get_refdb_area(): retrieves the refdb_area element from a query result
1699 
1700   char* get_refdb_area returns a pointer to a string containing the
1701                      refdb_area element
1702 
1703   dbi_result dbires database query result, pointing to the current
1704                     dataset
1705 
1706   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_area(dbi_result dbires)1707 const char* get_refdb_area(dbi_result dbires) {
1708   const char* result;
1709 
1710   result = dbi_result_get_string(dbires, "refdb_area");
1711   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1712     return NULL;
1713   }
1714   else {
1715     return result;
1716   }
1717 }
1718 
1719 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1720   get_refdb_ostype(): retrieves the refdb_ostype element from a query result
1721 
1722   char* get_refdb_ostype returns a pointer to a string containing the
1723                      refdb_ostype element
1724 
1725   dbi_result dbires database query result, pointing to the current
1726                     dataset
1727 
1728   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_ostype(dbi_result dbires)1729 const char* get_refdb_ostype(dbi_result dbires) {
1730   const char* result;
1731 
1732   result = dbi_result_get_string(dbires, "refdb_ostype");
1733   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1734     return NULL;
1735   }
1736   else {
1737     return result;
1738   }
1739 }
1740 
1741 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1742   get_refdb_degree(): retrieves the refdb_degree element from a query result
1743 
1744   char* get_refdb_degree returns a pointer to a string containing the
1745                      refdb_degree element
1746 
1747   dbi_result dbires database query result, pointing to the current
1748                     dataset
1749 
1750   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_degree(dbi_result dbires)1751 const char* get_refdb_degree(dbi_result dbires) {
1752   const char* result;
1753 
1754   result = dbi_result_get_string(dbires, "refdb_degree");
1755   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1756     return NULL;
1757   }
1758   else {
1759     return result;
1760   }
1761 }
1762 
1763 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1764   get_refdb_runningtime(): retrieves the refdb_runningtime element from a query result
1765 
1766   char* get_refdb_runningtime returns a pointer to a string containing the
1767                      refdb_runningtime element
1768 
1769   dbi_result dbires database query result, pointing to the current
1770                     dataset
1771 
1772   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_runningtime(dbi_result dbires)1773 const char* get_refdb_runningtime(dbi_result dbires) {
1774   const char* result;
1775 
1776   result = dbi_result_get_string(dbires, "refdb_runningtime");
1777   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1778     return NULL;
1779   }
1780   else {
1781     return result;
1782   }
1783 }
1784 
1785 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1786   get_refdb_classcodeintl(): retrieves the refdb_classcodeintl element
1787                              from a query result
1788 
1789   char* get_refdb_classcodeintl returns a pointer to a string containing the
1790                      refdb_classcodeintl element
1791 
1792   dbi_result dbires database query result, pointing to the current
1793                     dataset
1794 
1795   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_classcodeintl(dbi_result dbires)1796 const char* get_refdb_classcodeintl(dbi_result dbires) {
1797   const char* result;
1798 
1799   result = dbi_result_get_string(dbires, "refdb_classcodeintl");
1800   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1801     return NULL;
1802   }
1803   else {
1804     return result;
1805   }
1806 }
1807 
1808 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1809   get_refdb_classcodeus(): retrieves the refdb_classcodeus element from
1810                            a query result
1811 
1812   char* get_refdb_classcodeus returns a pointer to a string containing the
1813                      refdb_classcodeus element
1814 
1815   dbi_result dbires database query result, pointing to the current
1816                     dataset
1817 
1818   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_classcodeus(dbi_result dbires)1819 const char* get_refdb_classcodeus(dbi_result dbires) {
1820   const char* result;
1821 
1822   result = dbi_result_get_string(dbires, "refdb_classcodeus");
1823   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1824     return NULL;
1825   }
1826   else {
1827     return result;
1828   }
1829 }
1830 
1831 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1832   get_refdb_senderemail(): retrieves the refdb_senderemail element
1833                            from a query result
1834 
1835   char* get_refdb_senderemail returns a pointer to a string containing the
1836                      refdb_senderemail element
1837 
1838   dbi_result dbires database query result, pointing to the current
1839                     dataset
1840 
1841   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_senderemail(dbi_result dbires)1842 const char* get_refdb_senderemail(dbi_result dbires) {
1843   const char* result;
1844 
1845   result = dbi_result_get_string(dbires, "refdb_senderemail");
1846   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1847     return NULL;
1848   }
1849   else {
1850     return result;
1851   }
1852 }
1853 
1854 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1855   get_refdb_recipientemail(): retrieves the refdb_recipientemail element
1856                               from a query result
1857 
1858   char* get_refdb_recipientemail returns a pointer to a string containing the
1859                      refdb_recipientemail element
1860 
1861   dbi_result dbires database query result, pointing to the current
1862                     dataset
1863 
1864   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_recipientemail(dbi_result dbires)1865 const char* get_refdb_recipientemail(dbi_result dbires) {
1866   const char* result;
1867 
1868   result = dbi_result_get_string(dbires, "refdb_recipientemail");
1869   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1870     return NULL;
1871   }
1872   else {
1873     return result;
1874   }
1875 }
1876 
1877 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1878   get_refdb_mediatype(): retrieves the refdb_mediatype element from a
1879                          query result
1880 
1881   char* get_refdb_mediatype returns a pointer to a string containing the
1882                      refdb_mediatype element
1883 
1884   dbi_result dbires database query result, pointing to the current
1885                     dataset
1886 
1887   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_mediatype(dbi_result dbires)1888 const char* get_refdb_mediatype(dbi_result dbires) {
1889   const char* result;
1890 
1891   result = dbi_result_get_string(dbires, "refdb_mediatype");
1892   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1893     return NULL;
1894   }
1895   else {
1896     return result;
1897   }
1898 }
1899 
1900 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1901   get_refdb_numvolumes(): retrieves the refdb_numvolumes element from
1902                           a query result
1903 
1904   char* get_refdb_numvolumes returns a pointer to a string containing the
1905                      refdb_numvolumes element
1906 
1907   dbi_result dbires database query result, pointing to the current
1908                     dataset
1909 
1910   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_numvolumes(dbi_result dbires)1911 const char* get_refdb_numvolumes(dbi_result dbires) {
1912   const char* result;
1913 
1914   result = dbi_result_get_string(dbires, "refdb_numvolumes");
1915   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1916     return NULL;
1917   }
1918   else {
1919     return result;
1920   }
1921 }
1922 
1923 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1924   get_refdb_doi(): retrieves the refdb_doi element from a query result
1925 
1926   char* get_refdb_doi returns a pointer to a string containing the
1927                      refdb_doi element
1928 
1929   dbi_result dbires database query result, pointing to the current
1930                     dataset
1931 
1932   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_doi(dbi_result dbires)1933 const char* get_refdb_doi(dbi_result dbires) {
1934   const char* result;
1935 
1936   result = dbi_result_get_string(dbires, "refdb_doi");
1937   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1938     return NULL;
1939   }
1940   else {
1941     return result;
1942   }
1943 }
1944 
1945 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1946   get_refdb_edition(): retrieves the refdb_edition element from a query result
1947 
1948   char* get_refdb_edition returns a pointer to a string containing the
1949                      refdb_edition element
1950 
1951   dbi_result dbires database query result, pointing to the current
1952                     dataset
1953 
1954   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_edition(dbi_result dbires)1955 const char* get_refdb_edition(dbi_result dbires) {
1956   const char* result;
1957 
1958   result = dbi_result_get_string(dbires, "refdb_edition");
1959   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1960     return NULL;
1961   }
1962   else {
1963     return result;
1964   }
1965 }
1966 
1967 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1968   get_refdb_computer(): retrieves the refdb_computer element from a query result
1969 
1970   char* get_refdb_computer returns a pointer to a string containing the
1971                      refdb_computer element
1972 
1973   dbi_result dbires database query result, pointing to the current
1974                     dataset
1975 
1976   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_computer(dbi_result dbires)1977 const char* get_refdb_computer(dbi_result dbires) {
1978   const char* result;
1979 
1980   result = dbi_result_get_string(dbires, "refdb_computer");
1981   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
1982     return NULL;
1983   }
1984   else {
1985     return result;
1986   }
1987 }
1988 
1989 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1990   get_refdb_conferencelocation(): retrieves the refdb_conferencelocation
1991                                   element from a query result
1992 
1993   char* get_refdb_conferencelocation returns a pointer to a string
1994                      containing the
1995                      refdb_conferencelocation element
1996 
1997   dbi_result dbires database query result, pointing to the current
1998                     dataset
1999 
2000   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_conferencelocation(dbi_result dbires)2001 const char* get_refdb_conferencelocation(dbi_result dbires) {
2002   const char* result;
2003 
2004   result = dbi_result_get_string(dbires, "refdb_conferencelocation");
2005   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
2006     return NULL;
2007   }
2008   else {
2009     return result;
2010   }
2011 }
2012 
2013 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2014   get_refdb_registrynum(): retrieves the refdb_registrynum element
2015                            from a query result
2016 
2017   char* get_refdb_registrynum returns a pointer to a string containing the
2018                      refdb_registrynum element
2019 
2020   dbi_result dbires database query result, pointing to the current
2021                     dataset
2022 
2023   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_registrynum(dbi_result dbires)2024 const char* get_refdb_registrynum(dbi_result dbires) {
2025   const char* result;
2026 
2027   result = dbi_result_get_string(dbires, "refdb_registrynum");
2028   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
2029     return NULL;
2030   }
2031   else {
2032     return result;
2033   }
2034 }
2035 
2036 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2037   get_refdb_classification(): retrieves the refdb_classification element
2038                               from a query result
2039 
2040   char* get_refdb_classification returns a pointer to a string containing the
2041                      refdb_classification element
2042 
2043   dbi_result dbires database query result, pointing to the current
2044                     dataset
2045 
2046   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_classification(dbi_result dbires)2047 const char* get_refdb_classification(dbi_result dbires) {
2048   const char* result;
2049 
2050   result = dbi_result_get_string(dbires, "refdb_classification");
2051   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
2052     return NULL;
2053   }
2054   else {
2055     return result;
2056   }
2057 }
2058 
2059 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2060   get_refdb_section(): retrieves the refdb_section element from a query result
2061 
2062   char* get_refdb_section returns a pointer to a string containing the
2063                      refdb_section element
2064 
2065   dbi_result dbires database query result, pointing to the current
2066                     dataset
2067 
2068   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_section(dbi_result dbires)2069 const char* get_refdb_section(dbi_result dbires) {
2070   const char* result;
2071 
2072   result = dbi_result_get_string(dbires, "refdb_section");
2073   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
2074     return NULL;
2075   }
2076   else {
2077     return result;
2078   }
2079 }
2080 
2081 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2082   get_refdb_pamphletnum(): retrieves the refdb_pamphletnum element from a query result
2083 
2084   char* get_refdb_pamphletnum returns a pointer to a string containing the
2085                      refdb_ element
2086 
2087   dbi_result dbires database query result, pointing to the current
2088                     dataset
2089 
2090   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_pamphletnum(dbi_result dbires)2091 const char* get_refdb_pamphletnum(dbi_result dbires) {
2092   const char* result;
2093 
2094   result = dbi_result_get_string(dbires, "refdb_pamphletnum");
2095   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
2096     return NULL;
2097   }
2098   else {
2099     return result;
2100   }
2101 }
2102 
2103 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2104   get_refdb_chapternum(): retrieves the refdb_chapternum element from a query result
2105 
2106   char* get_refdb_chapternum returns a pointer to a string containing the
2107                      refdb_ element
2108 
2109   dbi_result dbires database query result, pointing to the current
2110                     dataset
2111 
2112   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_refdb_chapternum(dbi_result dbires)2113 const char* get_refdb_chapternum(dbi_result dbires) {
2114   const char* result;
2115 
2116   result = dbi_result_get_string(dbires, "refdb_chapternum");
2117   if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
2118     return NULL;
2119   }
2120   else {
2121     return result;
2122   }
2123 }
2124 
2125 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2126   get_notes_copy(): retrieves the xuser_notes element from a query result
2127 
2128   char* get_notes_copy returns a pointer to a string containing the
2129                      xuser_notes element. The string is allocated and
2130 		     must be freed by the caller
2131 
2132   dbi_result dbires database query result, pointing to the current
2133                     dataset
2134 
2135   char* username ptr to string with the current username, or NULL if
2136                     the search should not be restricted to the
2137                     current user
2138 
2139   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_notes_copy(dbi_result dbires,char * username)2140 char* get_notes_copy(dbi_result dbires, char* username) {
2141   char* sql_command;
2142   const char* notes = NULL;
2143   unsigned long long n_id;
2144   dbi_result dbires1;
2145 
2146   n_id = my_dbi_result_get_idval(dbires, "refdb_id");
2147   if (n_id == 0) { /* all IDs >=1 so this must be an error */
2148     return NULL;
2149   }
2150 
2151   sql_command = malloc(256);
2152 
2153   if (sql_command == NULL) {
2154     return NULL;
2155   }
2156 
2157   if (username != NULL) {
2158     sprintf(sql_command, "SELECT t_xuser.xuser_notes FROM t_xuser INNER JOIN t_user ON t_xuser.user_id=t_user.user_id WHERE t_user.user_name=\'%s\' AND t_xuser.refdb_id="ULLSPEC, username, (unsigned long long)n_id);
2159   }
2160   else { /* use the first entry regardless of which user */
2161     sprintf(sql_command, "SELECT t_xuser.xuser_notes FROM t_xuser INNER JOIN t_user ON t_xuser.user_id=t_user.user_id WHERE t_xuser.refdb_id="ULLSPEC, (unsigned long long)n_id);
2162   }
2163 
2164   LOG_PRINT(LOG_DEBUG, sql_command);
2165   dbires1 = dbi_conn_query(dbi_result_get_conn(dbires), sql_command);
2166   free(sql_command);
2167 
2168   if (!dbires1) {
2169     return NULL;
2170   }
2171 
2172   if (dbi_result_next_row(dbires1)) {
2173     /* the result string will be an allocated copy that we have to free */
2174     notes = my_dbi_result_get_string_copy(dbires1, "xuser_notes");
2175   }
2176   dbi_result_free(dbires1);
2177 
2178   /* notes will still be NULL if result contains zero rows */
2179   return (char*)notes;
2180 }
2181 
2182 
2183 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2184   get_reprint(): retrieves the xuser_reprint element and related
2185                  elements from a query result
2186 
2187   struct REPRINT get_reprint returns a structure which points to
2188                      strings containing the xuser_reprint and
2189                      xuser_date elements. If the previous search
2190                      with request_reprint() was limited to the current
2191                      user, this function will return the reprint status
2192                      of this user. Otherwise it will search for the
2193                      first user that has the reference in file. If no
2194                      one has it in file, it will search for the first
2195                      user that has it on request. If there is still
2196                      no match, it will return any "NOT IN FILE" field.
2197 		     In case of an error, one or both REPRINT structure
2198                      members are NULL
2199 
2200   dbi_result dbires database query result, pointing to the current
2201                     dataset
2202 
2203   struct REPRINT* ptr_reprint ptr to structure which will receive the result
2204 
2205   char* username ptr to string with username or NULL if search should not
2206                  be limited to a particular user
2207 
2208   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_reprint(dbi_result dbires,struct REPRINT * ptr_reprint,char * username,int yeardigits)2209 struct REPRINT* get_reprint(dbi_result dbires, struct REPRINT* ptr_reprint, char* username, int yeardigits) {
2210   char* sql_command;
2211   const char* xuser_reprint;
2212   const char* xuser_avail;
2213   int num_rows;
2214   unsigned long long n_id;
2215   time_t reprint_date;
2216   dbi_conn conn;
2217   dbi_result dbires1;
2218 
2219   sql_command = malloc(256);
2220 
2221   if (sql_command == NULL) {
2222     return NULL;
2223   }
2224 
2225   n_id = my_dbi_result_get_idval(dbires, "refdb_id");
2226 
2227   if (n_id == 0) { /* all IDs > 0, so this must be an error */
2228     free(sql_command);
2229     return NULL;
2230   }
2231 
2232   conn = dbi_result_get_conn(dbires);
2233 
2234   if (username != NULL) {
2235     sprintf(sql_command, "SELECT t_xuser.xuser_reprint, t_xuser.xuser_date, t_xuser.xuser_avail FROM t_xuser INNER JOIN t_user ON t_xuser.user_id=t_user.user_id WHERE t_user.user_name=\'%s\' AND t_xuser.refdb_id="ULLSPEC, username, (unsigned long long)n_id);
2236   }
2237   else {
2238     sprintf(sql_command, "SELECT t_xuser.xuser_reprint, t_xuser.xuser_date, t_xuser.xuser_avail FROM t_xuser WHERE t_xuser.refdb_id="ULLSPEC, (unsigned long long)n_id);
2239   }
2240 
2241   LOG_PRINT(LOG_DEBUG, sql_command);
2242   dbires1 = dbi_conn_query(conn, sql_command);
2243   free(sql_command);
2244 
2245   if (!dbires1) {
2246     return NULL;
2247   }
2248 
2249   /* check how many rows. If > 1, search for first entry IN FILE, or
2250      ON REQUEST if the former is not found. Assemble string from the
2251      user_reprint and user_date columns */
2252 
2253   /* set defaults */
2254   (ptr_reprint->reprint)[0] = '\0';
2255   (ptr_reprint->date)[0] = '\0';
2256   (ptr_reprint->avail)[0] = '\0';
2257 
2258   if ((num_rows = dbi_result_get_numrows(dbires1)) > 1) {
2259     /* find first entry IN FILE */
2260     while (dbi_result_next_row(dbires1)) {
2261       xuser_reprint = dbi_result_get_string_idx(dbires1, 1);
2262       if (!xuser_reprint || dbi_conn_error_flag(conn)) {
2263 	continue;
2264       }
2265       if (strncmp(xuser_reprint, "IN FILE", 7) == 0) {
2266 	strcpy(ptr_reprint->reprint, xuser_reprint);
2267 	reprint_date = dbi_result_get_datetime_idx(dbires1, 2);
2268 	if (reprint_date && !dbi_conn_error_flag(conn)) {
2269 	  print_risdate(&reprint_date, ptr_reprint->date, yeardigits);
2270 	}
2271 	xuser_avail = dbi_result_get_string_idx(dbires1, 3);
2272 	if (xuser_avail && !dbi_conn_error_flag(conn)) {
2273 	  strcpy(ptr_reprint->avail, xuser_avail);
2274 	}
2275 	return ptr_reprint; /* the first IN FILE entry */
2276       }
2277     } /* end while */
2278 
2279     /* rewind... */
2280     dbi_result_first_row(dbires1);
2281 
2282     while (dbi_result_next_row(dbires1)) {
2283       xuser_reprint = dbi_result_get_string_idx(dbires1, 1);
2284       if (!xuser_reprint || dbi_conn_error_flag(conn)) {
2285 	continue;
2286       }
2287       if (strncmp(xuser_reprint, "ON REQUEST", 10) == 0) {
2288 	strcpy(ptr_reprint->reprint, xuser_reprint);
2289 	reprint_date = dbi_result_get_datetime_idx(dbires1, 2);
2290 	if (reprint_date && !dbi_conn_error_flag(conn)) {
2291 	  print_risdate(&reprint_date, ptr_reprint->date, yeardigits);
2292 	}
2293 	xuser_avail = dbi_result_get_string_idx(dbires1, 3);
2294 	if (xuser_avail && !dbi_conn_error_flag(conn)) {
2295 	  strcpy(ptr_reprint->avail, xuser_avail);
2296 	}
2297 	return ptr_reprint; /* the first ON REQUEST entry */
2298       }
2299     } /* end while */
2300 
2301     /* rewind... */
2302     dbi_result_first_row(dbires1);
2303 
2304     if (dbi_result_next_row(dbires1)) {
2305       xuser_reprint = dbi_result_get_string_idx(dbires1, 1);
2306       if (xuser_reprint && !dbi_conn_error_flag(conn)) {
2307 	strcpy(ptr_reprint->reprint, xuser_reprint);
2308       }
2309       reprint_date = dbi_result_get_datetime_idx(dbires1, 2);
2310       if (reprint_date && !dbi_conn_error_flag(conn)) {
2311 	print_risdate(&reprint_date, ptr_reprint->date, yeardigits);
2312       }
2313       xuser_avail = dbi_result_get_string_idx(dbires1, 3);
2314       if (xuser_avail && !dbi_conn_error_flag(conn)) {
2315 	strcpy(ptr_reprint->avail, xuser_avail);
2316       }
2317       return ptr_reprint; /* the first NOT IN FILE entry */
2318     }
2319     else {
2320       return ptr_reprint; /* have nothing */
2321     }
2322   }
2323   else if (num_rows == 1) {
2324     if (dbi_result_next_row(dbires1)) {
2325       xuser_reprint = dbi_result_get_string_idx(dbires1, 1);
2326       if (xuser_reprint && !dbi_conn_error_flag(conn)) {
2327 	strcpy(ptr_reprint->reprint, xuser_reprint);
2328       }
2329       reprint_date = dbi_result_get_datetime_idx(dbires1, 2);
2330       if (reprint_date && !dbi_conn_error_flag(conn)) {
2331 	print_risdate(&reprint_date, ptr_reprint->date, yeardigits);
2332       }
2333       xuser_avail = dbi_result_get_string_idx(dbires1, 3);
2334       if (xuser_avail && !dbi_conn_error_flag(conn)) {
2335 	strcpy(ptr_reprint->avail, xuser_avail);
2336       }
2337       return ptr_reprint; /* the first NOT IN FILE entry */
2338     }
2339     else {
2340       return ptr_reprint; /* have nothing */
2341     }
2342   }
2343   else {
2344     return ptr_reprint; /* have nothing */
2345   }
2346 }
2347 
2348 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2349   get_periodical(): prepares the retrieval of periodical from
2350                            a given database
2351 
2352   char* get_periodical returns the periodical string or NULL if an
2353                     error occurred
2354 
2355   dbi_result dbires database query result, pointing to the current
2356                     dataset
2357 
2358   char* periodical ptr to string that will receive the result. Must
2359                     hold at least 256 characters.
2360 
2361   const char* db string holding the database to search in, or NULL if the
2362                   current database should be used
2363 
2364   int type indicates which periodical name is to be retrieved. 0=name,
2365                      1=custabbrev1, 2=custabbrev2, 3=abbrev, 4=the first
2366                      existing name in the order name, abbrev, custabbrev1,
2367                      custabbrev2
2368 
2369   int* errcode ptr to an int that will receive the error code
2370                (0 = no error, 1 = nothing found, 2 = memory error,
2371 	        3 = database server error)
2372 
2373   int is_temp if 1, query temporary table for a dupcheck
2374               if 2, query temporary tables, but use frequency in
2375                     permanent tables
2376 	      if 0, query permanent tables
2377 
2378   unsigned long long n_id ID of the dataset
2379 
2380   unsigned long long* ptr_frequency will be set to the frequency of the
2381                      periodical in the database unless NULL
2382 
2383   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_periodical(dbi_conn conn,char * periodical,const char * db,int type,int * errcode,int is_temp,unsigned long long n_id,unsigned long long * ptr_frequency)2384 char* get_periodical(dbi_conn conn, char* periodical, const char* db, int type, int* errcode, int is_temp, unsigned long long n_id, unsigned long long* ptr_frequency) {
2385   char prefix[] = TEMP_TABLE_NAME_PREFIX;
2386   char *sql_command;
2387   char *dbstring = NULL;
2388   const char *item;
2389   const char *drivername;
2390   int i;
2391   dbi_result dbires1;
2392 
2393   /* fix the insert */
2394   if (!is_temp) {
2395     *prefix = '\0';
2396   }
2397 
2398   drivername = dbi_driver_get_name(dbi_conn_get_driver(conn));
2399 
2400   sql_command = malloc(1024);
2401 
2402   if (sql_command == NULL) {
2403     *errcode = 2;
2404     return NULL;
2405   }
2406 
2407   if (!n_id) {
2408     *errcode = 1;
2409     return NULL;
2410   }
2411 
2412   /* never use db argument with pgsql driver */
2413   if (db && *db && !strcmp(my_dbi_conn_get_cap(conn, "multiple_db"), "t")) {
2414     dbstring = malloc(strlen(db)+2);
2415 
2416     if (dbstring == NULL) {
2417       *errcode = 2;
2418       return NULL;
2419     }
2420     sprintf(dbstring, "%s.", db);
2421   }
2422   else {
2423     /* this is weird but simplifies the free() calls further down */
2424     dbstring = malloc(1);
2425 
2426     if (dbstring == NULL) {
2427       *errcode = 2;
2428       return NULL;
2429     }
2430     dbstring[0] = '\0';
2431   }
2432 
2433   if (type == 4) {
2434     /* we try all periodical names in a fixed order and return the first
2435        one we can find, or NULL if we don't find anything */
2436     for (i = 0; i < 4; i++) {
2437       switch (i) {
2438       case 0:
2439 	/* first try name */
2440 	sprintf(sql_command, "SELECT %st_%speriodical.periodical_name, %st_%speriodical.periodical_id FROM %st_%speriodical INNER JOIN %st_%srefdb ON %st_%srefdb.refdb_periodical_id=%st_%speriodical.periodical_id WHERE %st_%srefdb.refdb_id="ULLSPEC, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, (unsigned long long)n_id);
2441 	break;
2442       case 1:
2443 	/* then try abbrev */
2444 	sprintf(sql_command, "SELECT %st_%speriodical.periodical_abbrev, %st_%speriodical.periodical_id  FROM %st_%speriodical INNER JOIN %st_%srefdb ON %st_%srefdb.refdb_periodical_id=%st_%speriodical.periodical_id WHERE %st_%srefdb.refdb_id="ULLSPEC, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, (unsigned long long)n_id);
2445 	break;
2446       case 2:
2447 	/* then try custabbrev1 */
2448 	sprintf(sql_command, "SELECT %st_%speriodical.periodical_custabbrev1, %st_%speriodical.periodical_id  FROM %st_%speriodical INNER JOIN %st_%srefdb ON %st_%srefdb.refdb_periodical_id=%st_%speriodical.periodical_id WHERE %st_%srefdb.refdb_id="ULLSPEC, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, (unsigned long long)n_id);
2449 	break;
2450       case 3:
2451 	/* finally try custabbrev2 */
2452 	sprintf(sql_command, "SELECT %st_%speriodical.periodical_custabbrev2, %st_%speriodical.periodical_id  FROM %st_%speriodical INNER JOIN %st_%srefdb ON %st_%srefdb.refdb_periodical_id=%st_%speriodical.periodical_id WHERE %st_%srefdb.refdb_id="ULLSPEC, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, (unsigned long long)n_id);
2453 	break;
2454       default:
2455 	LOG_PRINT(LOG_CRIT, "hope you never see this");
2456 	return NULL;
2457       }
2458 
2459       LOG_PRINT(LOG_DEBUG, sql_command);
2460       dbires1 = dbi_conn_query(conn, sql_command);
2461       if (!dbires1) {
2462 	*errcode = 3;
2463 	free(sql_command);
2464 	free(dbstring);
2465 	return NULL;
2466       }
2467 
2468       item = real_get_periodical(dbires1, is_temp, ptr_frequency);
2469 
2470       if (item && *item) {
2471 	/* we're done, copy string into provided buffer and return it */
2472 	*errcode = 0;
2473 	strcpy(periodical, item);
2474 	dbi_result_free(dbires1);
2475 	free(sql_command);
2476 	free(dbstring);
2477 	return periodical;
2478       }
2479     } /* end for */
2480 
2481 
2482     if (i == 4) { /* nothing found */
2483       *errcode = 1;
2484       free(sql_command);
2485       free(dbstring);
2486       return NULL;
2487     }
2488   }
2489   else {
2490     if (!type) {
2491       sprintf(sql_command, "SELECT %st_%speriodical.periodical_name, %st_%speriodical.periodical_id FROM %st_%speriodical INNER JOIN %st_%srefdb ON %st_%srefdb.refdb_periodical_id=%st_%speriodical.periodical_id WHERE %st_%srefdb.refdb_id="ULLSPEC, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, (unsigned long long)n_id);
2492     }
2493     else if (type == 1) {
2494       sprintf(sql_command, "SELECT %st_%speriodical.periodical_custabbrev1, %st_%speriodical.periodical_id FROM %st_%speriodical INNER JOIN %st_%srefdb ON %st_%srefdb.refdb_periodical_id=%st_%speriodical.periodical_id WHERE %st_%srefdb.refdb_id="ULLSPEC, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, (unsigned long long)n_id);
2495     }
2496     else if (type == 2) {
2497       sprintf(sql_command, "SELECT %st_%speriodical.periodical_custabbrev2, %st_%speriodical.periodical_id FROM %st_%speriodical INNER JOIN %st_%srefdb ON %st_%srefdb.refdb_periodical_id=%st_%speriodical.periodical_id WHERE %st_%srefdb.refdb_id="ULLSPEC, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, (unsigned long long)n_id);
2498     }
2499     else if (type == 3) {
2500       sprintf(sql_command, "SELECT %st_%speriodical.periodical_abbrev, %st_%speriodical.periodical_id FROM %st_%speriodical INNER JOIN %st_%srefdb ON %st_%srefdb.refdb_periodical_id=%st_%speriodical.periodical_id WHERE %st_%srefdb.refdb_id="ULLSPEC, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, (unsigned long long)n_id);
2501     }
2502 
2503     LOG_PRINT(LOG_DEBUG, sql_command);
2504     dbires1 = dbi_conn_query(conn, sql_command);
2505 
2506     free(sql_command);
2507     free(dbstring);
2508 
2509     if (!dbires1) {
2510       *errcode = 3;
2511       return NULL;
2512     }
2513 
2514     item = real_get_periodical(dbires1, is_temp, ptr_frequency);
2515     if (!item) {
2516       *errcode = 1;
2517       dbi_result_free(dbires1);
2518       return NULL;
2519     }
2520     else {
2521       *errcode = 0;
2522       strcpy(periodical, item);
2523       dbi_result_free(dbires1);
2524       return periodical;
2525     }
2526   }
2527   /* we should never arrive here - just to silence the compiler warning */
2528   return NULL;
2529 }
2530 
2531 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2532   real_get_periodical(): retrieves the periodical from a query result
2533 
2534   char* real_get_periodical returns a pointer to a string containing the
2535                      periodical
2536 
2537   dbi_result dbires database query result, pointing to the current
2538                     dataset
2539 
2540   int is_temp if 1, query temporary table for a dupcheck
2541               if 2, query temporary tables, but use frequency in
2542                     permanent tables
2543 	      if 0, query permanent tables
2544 
2545   unsigned long long* ptr_frequency will be set to the frequency of
2546                     the periodical in the database unless NULL
2547 
2548   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
real_get_periodical(dbi_result dbires,int is_temp,unsigned long long * ptr_frequency)2549 static const char* real_get_periodical(dbi_result dbires, int is_temp, unsigned long long* ptr_frequency) {
2550   const char* result;
2551   char prefix[] = TEMP_TABLE_NAME_PREFIX;
2552   char sql_command[256];
2553   unsigned long long periodical_id;
2554   unsigned long long periodical_num;
2555   dbi_result dbires1;
2556 
2557   /* fix the insert */
2558   if (is_temp == 0 || is_temp == 2) {
2559     *prefix = '\0';
2560   }
2561 
2562 
2563 
2564   if (dbi_result_next_row(dbires)) {
2565     result = dbi_result_get_string_idx(dbires, 1);
2566     if (ptr_frequency) {
2567       periodical_id = my_dbi_result_get_idval_idx(dbires, 2);
2568 
2569       sprintf(sql_command, "SELECT count(*) FROM t_%srefdb WHERE t_%srefdb.refdb_periodical_id="ULLSPEC, prefix, prefix, (unsigned long long)periodical_id);
2570 
2571       LOG_PRINT(LOG_DEBUG, sql_command);
2572 
2573       dbires1 = dbi_conn_query(dbi_result_get_conn(dbires), sql_command);
2574       if (!dbires1) {
2575 	*ptr_frequency = 0;
2576 	return NULL;
2577       }
2578 
2579       if (dbi_result_next_row(dbires1)) {
2580 	periodical_num = my_dbi_result_get_idval_idx(dbires1, 1);
2581 	if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
2582 	  dbi_result_free(dbires1);
2583 	  *ptr_frequency = 0;
2584 	  return NULL;
2585 	}
2586 	dbi_result_free(dbires1);
2587 	*ptr_frequency = periodical_num;
2588 	return result;
2589       }
2590       else {
2591 	dbi_result_free(dbires1);
2592 	*ptr_frequency = 0;
2593 	return NULL;
2594       }
2595     }
2596 
2597     if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
2598       return NULL;
2599     }
2600     else {
2601       return result;
2602     }
2603   }
2604   else {
2605     return NULL;
2606   }
2607 }
2608 
2609 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2610   request_authors(): prepares the retrieval of authors from the
2611                      currently selected database
2612 
2613   dbi_result request_authors returns a query result
2614                      which contains the authors
2615 
2616   dbi_conn conn connection to the database server
2617 
2618   int type 1 = part author, 2 = publication author, 3 = set author,
2619            4 = first available, 0 = all of them
2620 
2621   const char* role ptr to a string with contributor role, or NULL
2622 
2623   const char* db ptr to a string with the database name or NULL if the
2624                     current database should be used
2625 
2626   int is_temp if 1, query temporary table for a dupcheck
2627               if 2, query temporary tables, but use frequency in
2628                     permanent tables
2629 	      if 0, query permanent tables
2630 
2631   unsigned long long n_id id of the dataset
2632 
2633   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
request_authors(dbi_conn conn,int type,const char * role,const char * db,int is_temp,unsigned long long n_id)2634 dbi_result request_authors(dbi_conn conn, int type, const char* role, const char* db, int is_temp, unsigned long long n_id) {
2635   char* sql_command;
2636   char* dbstring;
2637   char* type_clause;
2638   char* role_clause;
2639   const char* drivername;
2640   char prefix[] = TEMP_TABLE_NAME_PREFIX;
2641   unsigned long long num_authors = 0;
2642   int i = 1;
2643   dbi_result dbires = NULL;
2644   dbi_driver driver = NULL;
2645 
2646   if (type == 4) {
2647     /* recursively call ourselves with all possible author types */
2648     while (i < 4 && !num_authors) {
2649       dbires = request_authors(conn, i, role, db, is_temp, n_id);
2650       if (dbires) {
2651 	num_authors = get_num_authors(dbires);
2652 	if (!num_authors && i < 3) {
2653 	  clean_request(dbires);
2654 	}
2655       }
2656       i++;
2657     }
2658     return dbires;
2659   }
2660   else {
2661     /* fix the insert */
2662     if (!is_temp) {
2663       *prefix = '\0';
2664     }
2665 
2666     /* never use db argument with pgsql */
2667     if (db && *db && !strcmp(my_dbi_conn_get_cap(conn, "multiple_db"), "t")) {
2668       dbstring = malloc(strlen(db)+2);
2669 
2670       if (dbstring == NULL) {
2671 	LOG_PRINT(LOG_CRIT, get_status_msg(801));
2672 	return NULL;
2673       }
2674       sprintf(dbstring, "%s.", db);
2675     }
2676     else {
2677       /* this is weird but simplifies the free() calls further down */
2678       dbstring = malloc(1);
2679 
2680       if (dbstring == NULL) {
2681 	LOG_PRINT(LOG_CRIT, get_status_msg(801));
2682 	return NULL;
2683       }
2684       *dbstring = '\0';
2685     }
2686 
2687     if ((type_clause = malloc(64+strlen(dbstring)+strlen(prefix))) == NULL) {
2688       LOG_PRINT(LOG_CRIT, get_status_msg(801));
2689       free(dbstring);
2690       return NULL;
2691     }
2692     else {
2693       *type_clause = '\0';
2694     }
2695 
2696     if ((role_clause = malloc(64+strlen(dbstring)+strlen(prefix)+((role) ? strlen(role):0))) == NULL) {
2697       LOG_PRINT(LOG_CRIT, get_status_msg(801));
2698       free(dbstring);
2699       return NULL;
2700     }
2701     else {
2702       *role_clause = '\0';
2703     }
2704 
2705     if (type != 0) {
2706       sprintf(type_clause, " %st_%sxauthor.xauthor_type=%s AND ", dbstring, prefix, get_author_type_string(driver, type));
2707     }
2708 
2709     if (role && *role) {
2710       sprintf(role_clause, " %st_%sxauthor.xauthor_role=\'%s\' AND ", dbstring, prefix, role);
2711     }
2712 
2713     driver = dbi_conn_get_driver(conn);
2714     drivername = dbi_driver_get_name(driver);
2715 
2716     sql_command = malloc(1024);
2717 
2718     if (sql_command == NULL) {
2719       LOG_PRINT(LOG_CRIT, get_status_msg(801));
2720       free(type_clause);
2721       free(role_clause);
2722       return NULL;
2723     }
2724 
2725     sprintf(sql_command, "SELECT %st_%sauthor.author_name,%st_%sauthor.author_lastname,%st_%sauthor.author_firstname,%st_%sauthor.author_middlename,%st_%sauthor.author_suffix,%st_%sxauthor.xauthor_role, %st_%sxauthor.author_id FROM %st_%sauthor INNER JOIN %st_%sxauthor ON %st_%sauthor.author_id=%st_%sxauthor.author_id WHERE %s %s %st_%sxauthor.refdb_id="ULLSPEC" ORDER BY t_%sxauthor.xauthor_position", dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, type_clause, role_clause, dbstring, prefix, (unsigned long long)n_id, prefix);
2726 
2727     LOG_PRINT(LOG_DEBUG, sql_command);
2728     free(type_clause);
2729     free(role_clause);
2730 
2731     dbires = dbi_conn_query(conn, sql_command);
2732 
2733     free(sql_command);
2734     free(dbstring);
2735 
2736     return dbires;
2737   } /* end if type==4 */
2738 }
2739 
2740 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2741   get_num_authors(): retrieves the number of authors
2742 
2743   int get_num_authors returns the number of requested authors
2744 
2745   dbi_result dbires database query result, pointing to the current
2746                     dataset
2747 
2748   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_num_authors(dbi_result dbires)2749 unsigned long long get_num_authors(dbi_result dbires) {
2750   return dbi_result_get_numrows(dbires);
2751 }
2752 
2753 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2754   get_author(): retrieves an author
2755 
2756   char* get_author returns a pointer to a string containing the
2757                      author
2758 
2759   dbi_result dbires database query result, pointing to the current
2760                     dataset
2761 
2762   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_author(dbi_result dbires)2763 const char* get_author(dbi_result dbires) {
2764   const char* result;
2765 
2766   if (dbi_result_next_row(dbires)) {
2767     result = dbi_result_get_string_idx(dbires, 1);
2768     if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
2769       return NULL;
2770     }
2771     else {
2772       return result;
2773     }
2774   }
2775   else {
2776     return NULL;
2777   }
2778 }
2779 
2780 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2781   get_author_parts(): retrieves an author's name parts
2782 
2783   struct AUTHOR_INFO* get_author_parts
2784                       returns a pointer to a struct containing the
2785                       author name parts
2786 
2787   dbi_result dbires database query result, pointing to the current
2788                     dataset
2789 
2790   struct AUTHOR_INFO* ptr_ainfo ptr to a structure that will receive
2791                     the result
2792 
2793   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_author_parts(dbi_result dbires,struct AUTHOR_INFO * ptr_ainfo)2794 struct AUTHOR_INFO* get_author_parts(dbi_result dbires, struct AUTHOR_INFO* ptr_ainfo) {
2795   const char* result;
2796 
2797   /* start with a clean struct */
2798   ptr_ainfo->name[0] = '\0';
2799   ptr_ainfo->lastname[0] = '\0';
2800   ptr_ainfo->firstname[0] = '\0';
2801   ptr_ainfo->middlename[0] = '\0';
2802   ptr_ainfo->suffix[0] = '\0';
2803   ptr_ainfo->role[0] = '\0';
2804 
2805   if (dbi_result_next_row(dbires)) {
2806     /* full name */
2807     result = dbi_result_get_string_idx(dbires, 1);
2808     if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
2809       return NULL;
2810     }
2811     else if (result) {
2812       strcpy(ptr_ainfo->name, result);
2813     }
2814 
2815     /* last name */
2816     result = dbi_result_get_string_idx(dbires, 2);
2817     if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
2818       return NULL;
2819     }
2820     else if (result) {
2821       strcpy(ptr_ainfo->lastname, result);
2822     }
2823 
2824     /* first name */
2825     result = dbi_result_get_string_idx(dbires, 3);
2826     if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
2827       return NULL;
2828     }
2829     else if (result) {
2830       strcpy(ptr_ainfo->firstname, result);
2831     }
2832 
2833     /* middle name */
2834     result = dbi_result_get_string_idx(dbires, 4);
2835     if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
2836       return NULL;
2837     }
2838     else if (result) {
2839       strcpy(ptr_ainfo->middlename, result);
2840     }
2841 
2842     /* suffix */
2843     result = dbi_result_get_string_idx(dbires, 5);
2844     if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
2845       return NULL;
2846     }
2847     else if (result) {
2848       strcpy(ptr_ainfo->suffix, result);
2849     }
2850 
2851     /* role */
2852     result = dbi_result_get_string_idx(dbires, 6);
2853     if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
2854       return NULL;
2855     }
2856     else if (result) {
2857       strcpy(ptr_ainfo->role, result);
2858     }
2859   }
2860   else {
2861     return NULL;
2862   }
2863 
2864   return ptr_ainfo;
2865 }
2866 
2867 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2868   get_extended_author(): retrieves an author along with its frequency
2869 
2870   char* get_extended_author returns a pointer to a string containing the
2871                      author
2872 
2873   dbi_result dbires database query result, pointing to the current
2874                     dataset
2875 
2876   int is_temp if 1, query temporary table for a dupcheck
2877               if 2, query temporary tables, but use frequency in
2878                     permanent tables
2879 	      if 0, query permanent tables
2880 
2881   unsigned long long* ptr_frequency ptr to an integer that will be
2882                     set to the frequency of the author in the database
2883 
2884   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_extended_author(dbi_result dbires,int is_temp,unsigned long long * ptr_frequency)2885 const char* get_extended_author(dbi_result dbires, int is_temp, unsigned long long* ptr_frequency) {
2886   const char* result;
2887   char sql_command[128];
2888   char prefix[] = TEMP_TABLE_NAME_PREFIX;
2889   unsigned long long author_id;
2890   unsigned long long author_num;
2891   dbi_result dbires1;
2892 
2893   /* fix the insert */
2894   if (is_temp == 0 || is_temp == 2) {
2895     *prefix = '\0';
2896   }
2897 
2898   if (dbi_result_next_row(dbires)) {
2899     result = dbi_result_get_string_idx(dbires, 1);
2900     author_id = my_dbi_result_get_idval_idx(dbires, 7);
2901     if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
2902       return NULL;
2903     }
2904 
2905     /* retrieve frequency information */
2906     sprintf(sql_command, "SELECT count(*) FROM t_%sxauthor WHERE author_id="ULLSPEC, prefix, (unsigned long long)author_id);
2907 
2908     LOG_PRINT(LOG_DEBUG, sql_command);
2909     dbires1 = dbi_conn_query(dbi_result_get_conn(dbires), sql_command);
2910     if (!dbires1) {
2911       *ptr_frequency = 0;
2912       return NULL;
2913     }
2914 
2915     if (dbi_result_next_row(dbires1)) {
2916       author_num = my_dbi_result_get_idval_idx(dbires1, 1);
2917       if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
2918 	dbi_result_free(dbires1);
2919 	*ptr_frequency = 0;
2920 	return NULL;
2921       }
2922       dbi_result_free(dbires1);
2923       *ptr_frequency = author_num;
2924       return result;
2925     }
2926     else {
2927       dbi_result_free(dbires1);
2928       *ptr_frequency = 0;
2929       return NULL;
2930     }
2931   }
2932   else {
2933     *ptr_frequency = 0;
2934     return NULL;
2935   }
2936 }
2937 
2938 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2939   get_extended_author_parts(): retrieves an author's name parts including
2940                                the frequency
2941 
2942   struct AUTHOR_INFO* get_extended_author_parts
2943                      returns a pointer to a struct containing the
2944                      author name parts
2945 
2946   dbi_result dbires database query result, pointing to the current
2947                     dataset
2948 
2949   struct AUTHOR_INFO* ptr_ainfo ptr to a structure that will receive
2950                     the result
2951 
2952   int is_temp if 1, query temporary table for a dupcheck
2953               if 2, query temporary tables, but use frequency in
2954                     permanent tables
2955 	      if 0, query permanent tables
2956 
2957   unsigned long long* ptr_frequency ptr to an integer that will be
2958                     set to the frequency of the author in the database
2959 
2960   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_extended_author_parts(dbi_result dbires,struct AUTHOR_INFO * ptr_ainfo,int is_temp,unsigned long long * ptr_frequency)2961 struct AUTHOR_INFO* get_extended_author_parts(dbi_result dbires, struct AUTHOR_INFO* ptr_ainfo, int is_temp, unsigned long long* ptr_frequency) {
2962   const char* result;
2963   char prefix[] = TEMP_TABLE_NAME_PREFIX;
2964   char sql_command[128];
2965   unsigned long long author_id;
2966   unsigned long long author_num;
2967   dbi_result dbires1;
2968 
2969   /* fix the insert */
2970   if (is_temp == 0 || is_temp == 2) {
2971     *prefix = '\0';
2972   }
2973 
2974   /* start with a clean struct */
2975   ptr_ainfo->name[0] = '\0';
2976   ptr_ainfo->lastname[0] = '\0';
2977   ptr_ainfo->firstname[0] = '\0';
2978   ptr_ainfo->middlename[0] = '\0';
2979   ptr_ainfo->suffix[0] = '\0';
2980   ptr_ainfo->role[0] = '\0';
2981 
2982   if (dbi_result_next_row(dbires)) {
2983     /* full name */
2984     result = dbi_result_get_string_idx(dbires, 1);
2985     author_id = my_dbi_result_get_idval_idx(dbires, 7);
2986     if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
2987       return NULL;
2988     }
2989     else if (result) {
2990       strcpy(ptr_ainfo->name, result);
2991     }
2992 
2993     /* last name */
2994     result = dbi_result_get_string_idx(dbires, 2);
2995     if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
2996       return NULL;
2997     }
2998     else if (result) {
2999       strcpy(ptr_ainfo->lastname, result);
3000     }
3001 
3002     /* first name */
3003     result = dbi_result_get_string_idx(dbires, 3);
3004     if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
3005       return NULL;
3006     }
3007     else if (result) {
3008       strcpy(ptr_ainfo->firstname, result);
3009     }
3010 
3011     /* middle name */
3012     result = dbi_result_get_string_idx(dbires, 4);
3013     if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
3014       return NULL;
3015     }
3016     else if (result) {
3017       strcpy(ptr_ainfo->middlename, result);
3018     }
3019 
3020     /* suffix */
3021     result = dbi_result_get_string_idx(dbires, 5);
3022     if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
3023       return NULL;
3024     }
3025     else if (result) {
3026       strcpy(ptr_ainfo->suffix, result);
3027     }
3028 
3029     /* role */
3030     result = dbi_result_get_string_idx(dbires, 6);
3031     if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
3032       return NULL;
3033     }
3034     else if (result) {
3035       strcpy(ptr_ainfo->role, result);
3036     }
3037     /* retrieve frequency information */
3038     sprintf(sql_command, "SELECT count(*) FROM t_%sxauthor WHERE author_id="ULLSPEC, prefix, (unsigned long long)author_id);
3039 
3040     LOG_PRINT(LOG_DEBUG, sql_command);
3041     dbires1 = dbi_conn_query(dbi_result_get_conn(dbires), sql_command);
3042     if (!dbires1) {
3043       *ptr_frequency = 0;
3044       return NULL;
3045     }
3046 
3047     if (dbi_result_next_row(dbires1)) {
3048       author_num = my_dbi_result_get_idval_idx(dbires1, 1);
3049       if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
3050 	dbi_result_free(dbires1);
3051 	*ptr_frequency = 0;
3052 	return NULL;
3053       }
3054       dbi_result_free(dbires1);
3055       *ptr_frequency = author_num;
3056       return ptr_ainfo;
3057     }
3058     else {
3059       dbi_result_free(dbires1);
3060       *ptr_frequency = 0;
3061       return NULL;
3062     }
3063   }
3064   else {
3065     *ptr_frequency = 0;
3066     return NULL;
3067   }
3068 
3069   return ptr_ainfo;
3070 }
3071 
3072 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3073   request_keywords(): prepares the retrieval of keywords
3074 
3075   dbi_result request_keywords returns a pointer to a dbi result structure
3076                      which contains the keywords
3077 
3078   dbi_result dbires database query result, pointing to the current
3079                     dataset (used only to retrieve the connection)
3080 
3081   int is_temp if 1, query temporary table for a dupcheck
3082               if 2, query temporary tables, but use frequency in
3083                     permanent tables
3084 	      if 0, query permanent tables
3085 
3086   int is_temp if 1, query temporary table for a dupcheck
3087 
3088   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
request_keywords(dbi_conn conn,unsigned long long n_id,int mode,int is_temp)3089 dbi_result request_keywords(dbi_conn conn, unsigned long long n_id, int mode, int is_temp) {
3090   char* sql_command;
3091   char keytype[2][10] = {"REFERENCE", "NOTE"};
3092   char prefix[] = TEMP_TABLE_NAME_PREFIX;
3093   dbi_result dbires;
3094 
3095   sql_command = malloc(512);
3096 
3097   if (sql_command == NULL) {
3098     return NULL;
3099   }
3100 
3101   /* fix the insert */
3102   if (!is_temp) {
3103     *prefix = '\0';
3104   }
3105 
3106   /* NB sorting the keywords is not strictly necessary but it
3107      simplifies roundtrip addref/getref analyses */
3108   sprintf(sql_command, "SELECT t_%skeyword.keyword_name, t_%skeyword.keyword_id FROM t_%skeyword INNER JOIN t_%sxkeyword ON t_%skeyword.keyword_id=t_%sxkeyword.keyword_id WHERE t_%sxkeyword.xkeyword_type=\'%s\' AND t_%sxkeyword.xref_id="ULLSPEC" ORDER BY t_%skeyword.keyword_name", prefix, prefix, prefix, prefix, prefix, prefix, prefix, keytype[mode], prefix, (unsigned long long)n_id, prefix);
3109 
3110   LOG_PRINT(LOG_DEBUG, sql_command);
3111   dbires = dbi_conn_query(conn, sql_command);
3112   free(sql_command);
3113   if (!dbires) {
3114     return NULL;
3115   }
3116 
3117   return dbires;
3118 }
3119 
3120 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3121   get_keyword(): retrieves a keyword
3122 
3123   char* get_keyword returns a pointer to a string containing the
3124                      keyword
3125 
3126   dbi_result dbires database query result, pointing to the current
3127                     dataset
3128 
3129   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_keyword(dbi_result dbires)3130 const char* get_keyword(dbi_result dbires) {
3131   const char* result;
3132 
3133   if (dbi_result_next_row(dbires)) {
3134     result = dbi_result_get_string_idx(dbires, 1);
3135     if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
3136       return NULL;
3137     }
3138     else {
3139       return result;
3140     }
3141   }
3142   else {
3143     return NULL;
3144   }
3145 }
3146 
3147 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3148   get_extended_keyword(): retrieves a keyword along with its frequency
3149 
3150   char* get_extended_keyword returns a pointer to a string containing the
3151                      keyword
3152 
3153   dbi_result dbires database query result, pointing to the current
3154                     dataset
3155 
3156   int is_temp if 1, query temporary table for a dupcheck
3157               if 2, query temporary tables, but use frequency in
3158                     permanent tables
3159 	      if 0, query permanent tables
3160 
3161   unsigned long long* ptr_frequency ptr to an integer that will be
3162                     set to the frequency of the keyword in the database
3163 
3164   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_extended_keyword(dbi_result dbires,int is_temp,unsigned long long * ptr_frequency)3165 const char* get_extended_keyword(dbi_result dbires, int is_temp, unsigned long long* ptr_frequency) {
3166   const char* result;
3167   char sql_command[128];
3168   char prefix[] = TEMP_TABLE_NAME_PREFIX;
3169   unsigned long long keyword_id;
3170   unsigned long long keyword_num;
3171   dbi_result dbires1;
3172 
3173   /* fix the insert */
3174   if (is_temp == 0 || is_temp == 2) {
3175     *prefix = '\0';
3176   }
3177 
3178   if (dbi_result_next_row(dbires)) {
3179     result = dbi_result_get_string_idx(dbires, 1);
3180     keyword_id = my_dbi_result_get_idval_idx(dbires, 2);
3181     if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
3182       return NULL;
3183     }
3184 
3185     /* retrieve frequency information */
3186     sprintf(sql_command, "SELECT count(*) FROM t_%sxkeyword WHERE keyword_id="ULLSPEC, prefix, (unsigned long long)keyword_id);
3187 
3188     LOG_PRINT(LOG_DEBUG, sql_command);
3189     dbires1 = dbi_conn_query(dbi_result_get_conn(dbires), sql_command);
3190     if (!dbires1) {
3191       *ptr_frequency = 0;
3192       return NULL;
3193     }
3194 
3195     if (dbi_result_next_row(dbires1)) {
3196       keyword_num = my_dbi_result_get_idval_idx(dbires1, 1);
3197       if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
3198 	dbi_result_free(dbires1);
3199 	*ptr_frequency = 0;
3200 	return NULL;
3201       }
3202       dbi_result_free(dbires1);
3203       *ptr_frequency = keyword_num;
3204       return result;
3205     }
3206     else {
3207       dbi_result_free(dbires1);
3208       *ptr_frequency = 0;
3209       return NULL;
3210     }
3211   }
3212   else {
3213     *ptr_frequency = 0;
3214     return NULL;
3215   }
3216 }
3217 
3218 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3219   get_num_keywords(): retrieves the number of keywords
3220 
3221   int get_num_keywords returns the number of requested keywords
3222 
3223   dbi_result dbires database query result, pointing to the current
3224                     dataset
3225 
3226   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_num_keywords(dbi_result dbires)3227 unsigned long long get_num_keywords(dbi_result dbires) {
3228   return dbi_result_get_numrows(dbires);
3229 }
3230 
3231 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3232   request_ulinks(): prepares the retrieval of ulinks
3233 
3234   dbi_result request_ulinks returns a pointer to a dbi result structure
3235                      which contains the ulinks
3236 
3237   dbi_result dbires database query result, pointing to the current
3238                     dataset (used only to retrieve the connection)
3239 
3240   int mode 0 = reference entry 1 = note entry
3241 
3242   int type 0 = URL, 1 = PDF, 2 = FULLTEXT 3 = RELATED 4 = IMAGE 5 = DOI
3243 
3244   int is_temp if 1, query temporary table for a dupcheck
3245 
3246   const char* username name of user. If NULL or empty, all links will
3247                     be retrieved. If given, only the links of that user
3248                     and all links not associated with a user will
3249                     be retrieved. The name "NULL" (don't confuse with
3250 		    a NULL pointer) will retrieve only those links that are
3251 		    not owned by a particular user (but then don't
3252 		    allow "NULL" as a username!)
3253 
3254   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
request_ulinks(dbi_conn conn,unsigned long long n_id,int mode,int type,int is_temp,const char * username)3255 dbi_result request_ulinks(dbi_conn conn, unsigned long long n_id, int mode, int type, int is_temp, const char* username) {
3256   char* sql_command;
3257   char keymode[2][10] = {"REFERENCE", "NOTE"};
3258   char keytype[6][10] = {"URL", "PDF", "FULLTEXT", "RELATED", "IMAGE", "DOI"};
3259   char prefix[] = TEMP_TABLE_NAME_PREFIX;
3260   dbi_result dbires;
3261 
3262   sql_command = malloc(512);
3263 
3264   if (sql_command == NULL) {
3265     return NULL;
3266   }
3267 
3268   /* fix the insert */
3269   if (!is_temp) {
3270     *prefix = '\0';
3271   }
3272 
3273   if (username && !strcmp(username, "NULL")) {
3274     /* only those not owned by a particular user */
3275     sprintf(sql_command, "SELECT DISTINCT t_%slink.link_url FROM t_%slink INNER JOIN t_%sxlink ON t_%slink.link_id=t_%sxlink.link_id WHERE t_%sxlink.xlink_type=\'%s\' AND t_%sxlink.xlink_source=\'%s\' AND t_%sxlink.xref_id="ULLSPEC" AND t_%sxlink.user_id=0" , prefix, prefix, prefix, prefix, prefix, prefix, keytype[type], prefix, keymode[mode], prefix, (unsigned long long)n_id, prefix);
3276   }
3277   else if (username && *username) {
3278     /* those owned by a particular user, and all not owned by one */
3279     /* NB the order of t_user and t_link in the FROM clause is
3280        critical in PostgreSQL */
3281     sprintf(sql_command, "SELECT DISTINCT t_%slink.link_url FROM t_%suser,t_%slink INNER JOIN t_%sxlink ON t_%slink.link_id=t_%sxlink.link_id WHERE t_%sxlink.xlink_type=\'%s\' AND t_%sxlink.xlink_source=\'%s\' AND t_%sxlink.xref_id="ULLSPEC" AND ((t_%sxlink.user_id=t_%suser.user_id AND t_%suser.user_name=\'%s\') OR t_%sxlink.user_id=0)" , prefix, prefix, prefix, prefix, prefix, prefix, prefix, keytype[type], prefix, keymode[mode], prefix, (unsigned long long)n_id, prefix, prefix, prefix, username, prefix);
3282   }
3283   else {
3284     /* all */
3285     sprintf(sql_command, "SELECT DISTINCT t_%slink.link_url FROM t_%slink INNER JOIN t_%sxlink ON t_%slink.link_id=t_%sxlink.link_id WHERE t_%sxlink.xlink_type=\'%s\' AND t_%sxlink.xlink_source=\'%s\' AND t_%sxlink.xref_id="ULLSPEC, prefix, prefix, prefix, prefix, prefix, prefix, keytype[type], prefix, keymode[mode], prefix, (unsigned long long)n_id);
3286   }
3287 
3288   LOG_PRINT(LOG_DEBUG, sql_command);
3289   dbires = dbi_conn_query(conn, sql_command);
3290   free(sql_command);
3291   if (!dbires) {
3292     return NULL;
3293   }
3294 
3295   return dbires;
3296 }
3297 
3298 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3299   get_ulink(): retrieves an ulink
3300 
3301   char* get_ulink returns a pointer to a string containing the
3302                      ulink
3303 
3304   dbi_result dbires database query result, pointing to the current
3305                     dataset
3306 
3307   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_ulink(dbi_result dbires)3308 const char* get_ulink(dbi_result dbires) {
3309   const char* result;
3310 
3311   if (dbi_result_next_row(dbires)) {
3312     result = my_dbi_result_get_string_idx(dbires, 1);
3313     if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
3314       return NULL;
3315     }
3316     else {
3317       return result;
3318     }
3319   }
3320   else {
3321     return NULL;
3322   }
3323 }
3324 
3325 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3326   request_users(): prepares the retrieval of users of the
3327                      currently selected database
3328 
3329   dbi_result request_users returns a query result
3330                      which contains the users
3331 
3332   dbi_conn conn connection to database server
3333 
3334   const char* db ptr to a string with the database name or NULL if the
3335                     current database should be used
3336 
3337   int is_temp if 1, query temporary table for a dupcheck
3338 
3339   unsigned long long n_id id of the dataset
3340 
3341   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
request_users(dbi_conn conn,const char * db,int is_temp,unsigned long long n_id)3342 dbi_result request_users(dbi_conn conn, const char* db, int is_temp, unsigned long long n_id) {
3343   char prefix[] = TEMP_TABLE_NAME_PREFIX;
3344   char *sql_command;
3345   char *dbstring;
3346   const char *drivername;
3347   dbi_result dbires;
3348   dbi_driver driver;
3349 
3350   driver = dbi_conn_get_driver(conn);
3351   drivername = dbi_driver_get_name(driver);
3352 
3353   sql_command = malloc(1024);
3354 
3355   if (sql_command == NULL) {
3356     return NULL;
3357   }
3358 
3359   /* fix the insert */
3360   if (!is_temp) {
3361     *prefix = '\0';
3362   }
3363 
3364   /* never use db argument with pgsql */
3365   if (db && *db && !strcmp(my_dbi_conn_get_cap(conn, "multiple_db"), "t")) {
3366     dbstring = malloc(strlen(db)+2);
3367 
3368     if (dbstring == NULL) {
3369       return NULL;
3370     }
3371     sprintf(dbstring, "%s.", db);
3372   }
3373   else {
3374     /* this is weird but simplifies the free() calls further down */
3375     dbstring = malloc(1);
3376 
3377     if (dbstring == NULL) {
3378       return NULL;
3379     }
3380     dbstring[0] = '\0';
3381   }
3382 
3383   sprintf(sql_command, "SELECT %st_%suser.user_name FROM %st_%suser INNER JOIN %st_%sxuser ON %st_%suser.user_id=%st_%sxuser.user_id WHERE %st_%sxuser.refdb_id="ULLSPEC, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, dbstring, prefix, (unsigned long long)n_id);
3384 
3385   LOG_PRINT(LOG_DEBUG, sql_command);
3386 
3387   dbires = dbi_conn_query(conn, sql_command);
3388   free(sql_command);
3389   free(dbstring);
3390 
3391   return dbires;
3392 }
3393 
3394 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3395   get_user(): retrieves an user
3396 
3397   char* get_user returns a pointer to a string containing the
3398                      user
3399 
3400   dbi_result dbires database query result, pointing to the current
3401                     dataset
3402 
3403   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_user(dbi_result dbires)3404 const char* get_user(dbi_result dbires) {
3405   const char* result;
3406 
3407   if (dbi_result_next_row(dbires)) {
3408     result = dbi_result_get_string_idx(dbires, 1);
3409     if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
3410       return NULL;
3411     }
3412     else {
3413       return result;
3414     }
3415   }
3416   else {
3417     return NULL;
3418   }
3419 }
3420 
3421 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3422   clean_request() frees the dbi result data structure after a request is
3423                   finished
3424 
3425   void clean_request
3426 
3427   dbi_result dbires database query result, pointing to the current
3428                     dataset
3429 
3430   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
clean_request(dbi_result dbires)3431 void clean_request(dbi_result dbires) {
3432   dbi_result_free(dbires);
3433 }
3434 
3435 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3436   my_dbi_result_get_string_copy(): retrieves a given field which is either a
3437                             string or a binary string from a query result
3438 
3439   char* my_dbi_result_get_string_copy returns a pointer to a string containing the
3440                      requested field element, or NULL in case something
3441 		     went wrong. The returned string must be freed by the
3442 		     calling function
3443 
3444   dbi_result dbires database query result, pointing to the current
3445                     dataset
3446 
3447   const char* fieldname name of the field to retrieve
3448 
3449   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
my_dbi_result_get_string_copy(dbi_result dbires,const char * fieldname)3450 char* my_dbi_result_get_string_copy(dbi_result dbires, const char* fieldname) {
3451   const char* result;
3452   char* myresult;
3453   unsigned short n_field_type;
3454   size_t n_stringsize;
3455 
3456   n_field_type = dbi_result_get_field_type(dbires, fieldname);
3457 
3458   if (n_field_type == DBI_TYPE_BINARY) {
3459     /* binary strings are returned without a terminating \0 so we have
3460        to bend over backwards to treat it as a normal string */
3461     result = (const char*)dbi_result_get_binary(dbires, fieldname);
3462     if (!result || dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
3463       return NULL;
3464     }
3465     else {
3466       n_stringsize = dbi_result_get_field_length(dbires, fieldname);
3467 
3468       /* need one extra byte for a terminating \0 */
3469       myresult = malloc(n_stringsize+1);
3470       if (myresult == NULL) {
3471 	return NULL;
3472       }
3473       memcpy(myresult, result, n_stringsize);
3474       myresult[n_stringsize] = '\0'; /* terminate string */
3475       return myresult;
3476     }
3477   }
3478   else if (n_field_type == DBI_TYPE_STRING) {
3479     result = dbi_result_get_string_copy(dbires, fieldname);
3480     if (dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
3481       return NULL;
3482     }
3483     else {
3484       return (char*)result;
3485     }
3486   }
3487   else {
3488     /* should never happen */
3489     return NULL;
3490   }
3491 }
3492 
3493 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3494   my_dbi_result_get_string_copy_idx(): retrieves a given field which is either a
3495                             string or a binary string from a query result
3496 
3497   char* my_dbi_result_get_string_copy_idx returns a pointer to a string containing the
3498                      requested field element, or NULL in case something
3499 		     went wrong. The returned string must be freed by the
3500 		     calling function
3501 
3502   dbi_result dbires database query result, pointing to the current
3503                     dataset
3504 
3505   unsigned int idx index of field to retrieve (1-base)
3506 
3507   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
my_dbi_result_get_string_copy_idx(dbi_result dbires,unsigned int idx)3508 char* my_dbi_result_get_string_copy_idx(dbi_result dbires, unsigned int idx) {
3509   const char* result;
3510   char* myresult;
3511   unsigned short n_field_type;
3512   size_t n_stringsize;
3513   char debug_msg[128];
3514 
3515   n_field_type = dbi_result_get_field_type_idx(dbires, idx);
3516 
3517 /*   sprintf(debug_msg, "n_field_type went to %d", n_field_type); */
3518 /*   LOG_PRINT(LOG_DEBUG, debug_msg); */
3519 
3520   if (n_field_type == DBI_TYPE_BINARY) {
3521     /* binary strings are returned without a terminating \0 so we have
3522        to bend over backwards to treat it as a normal string */
3523     result = (const char*)dbi_result_get_binary_idx(dbires, idx);
3524     if (!result || dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
3525       return NULL;
3526     }
3527     else {
3528       n_stringsize = dbi_result_get_field_length_idx(dbires, idx);
3529 
3530       /* need one extra byte for a terminating \0 */
3531       myresult = malloc(n_stringsize+1);
3532       if (myresult == NULL) {
3533 	return NULL;
3534       }
3535       memcpy(myresult, result, n_stringsize);
3536       myresult[n_stringsize] = '\0'; /* terminate string */
3537       return myresult;
3538     }
3539   }
3540   else if (n_field_type == DBI_TYPE_STRING) {
3541     result = dbi_result_get_string_copy_idx(dbires, idx);
3542 /*     if (!result) { */
3543 /*       LOG_PRINT(LOG_DEBUG, "result went to NULL"); */
3544 /*     } */
3545     if (!result || dbi_conn_error_flag(dbi_result_get_conn(dbires))) {
3546 /*        sprintf(debug_msg, "error flag went to %d, idx was %d", dbi_conn_error_flag(dbi_result_get_conn(dbires)), idx); */
3547 /*       LOG_PRINT(LOG_DEBUG, debug_msg); */
3548       return NULL;
3549     }
3550     else {
3551       return (char*)result;
3552     }
3553   }
3554   else {
3555     /* should never happen */
3556     return NULL;
3557   }
3558 }
3559 
3560 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3561   my_dbi_result_get_binary_copy(): retrieves a given field which is a
3562                              binary string from a query result
3563 
3564   char* my_dbi_result_get_binary_copy returns a pointer to a string
3565                      containing the requested field element, or NULL
3566 		     in case something went wrong. The returned string
3567 		     must be freed by the calling function
3568 
3569   dbi_result Result database query result, pointing to the current
3570                     dataset
3571 
3572   const char* fieldname name of the field to retrieve
3573 
3574   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
my_dbi_result_get_binary_copy(dbi_result Result,const char * fieldname)3575 char* my_dbi_result_get_binary_copy(dbi_result Result, const char* fieldname) {
3576   /* this is a helper function that should be dropped if libdbi accepts
3577      the patch for dbi_result_get_binary. The issue is whether or not
3578      a terminating \0 is returned by the dbi function or not. This
3579      implementation is necessary if dbi does *not* return the \0 */
3580 
3581   size_t n_stringsize;
3582   char *myresult;
3583   const char *result;
3584   const char *errstring;
3585   dbi_conn conn;
3586 
3587   conn = dbi_result_get_conn(Result);
3588 
3589   result = (const char*)dbi_result_get_binary(Result, fieldname);
3590 
3591   if (dbi_conn_error_flag(conn)) {
3592     dbi_conn_error(conn, &errstring);
3593     LOG_PRINT(LOG_WARNING, errstring);
3594     return NULL;
3595   }
3596 
3597   n_stringsize = dbi_result_get_field_length(Result, fieldname);
3598 
3599   /* need one extra byte for a terminating \0 */
3600   myresult = malloc(n_stringsize+1);
3601   if (myresult == NULL) {
3602     LOG_PRINT(LOG_WARNING, "out of memory");
3603     return NULL;
3604   }
3605   memcpy(myresult, result, n_stringsize);
3606   myresult[n_stringsize] = '\0'; /* terminate string */
3607   return myresult;
3608 }
3609 
3610 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3611   my_dbi_result_get_string(): retrieves a given TEXT field
3612 
3613   const char* my_dbi_result_get_string returns a pointer to a string
3614                      containing the requested field element, or NULL
3615 		     in case something went wrong.
3616 
3617   dbi_result Result database query result, pointing to the current
3618                     dataset
3619 
3620   const char* fieldname name of the field to retrieve
3621 
3622   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
my_dbi_result_get_string(dbi_result Result,const char * fieldname)3623 const char* my_dbi_result_get_string(dbi_result Result, const char* fieldname) {
3624   const char* result;
3625   unsigned short n_field_type;
3626 
3627   /* this kludgy function is necessary because MySQL treats TEXT fields
3628      as binary data */
3629   n_field_type = dbi_result_get_field_type(Result, fieldname);
3630 
3631   if (n_field_type == DBI_TYPE_BINARY) {
3632     /* this implementation assumes that binary strings are
3633        returned by the mysql driver including a trailing \0 */
3634     result = (const char*)dbi_result_get_binary(Result, fieldname);
3635     if (!result && dbi_conn_error_flag(dbi_result_get_conn(Result))) {
3636       return NULL;
3637     }
3638     else {
3639       return result;
3640     }
3641   }
3642   else if (n_field_type == DBI_TYPE_STRING) {
3643     result = dbi_result_get_string(Result, fieldname);
3644     if (dbi_conn_error_flag(dbi_result_get_conn(Result))) {
3645       return NULL;
3646     }
3647     else {
3648       return result;
3649     }
3650   }
3651   else {
3652     /* should never happen */
3653     return NULL;
3654   }
3655 }
3656 
3657 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3658   my_dbi_result_get_string_idx(): retrieves a given TEXT field
3659 
3660   const char* my_dbi_result_get_string_idx returns a pointer to a string
3661                      containing the requested field element, or NULL
3662 		     in case something went wrong.
3663 
3664   dbi_result Result database query result, pointing to the current
3665                     dataset
3666 
3667   unsigned int idx index of the field to retrieve (1-based)
3668 
3669   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
my_dbi_result_get_string_idx(dbi_result Result,unsigned int idx)3670 const char* my_dbi_result_get_string_idx(dbi_result Result, unsigned int idx) {
3671   const char* result;
3672   unsigned short n_field_type;
3673 
3674   /* this kludgy function is necessary because MySQL treats TEXT fields
3675      as binary data */
3676   n_field_type = dbi_result_get_field_type_idx(Result, idx);
3677 
3678   if (n_field_type == DBI_TYPE_BINARY) {
3679     /* this implementation assumes that binary strings are
3680        returned by the mysql driver including a trailing \0 */
3681     result = (const char*)dbi_result_get_binary_idx(Result, idx);
3682     if (!result || dbi_conn_error_flag(dbi_result_get_conn(Result))) {
3683       return NULL;
3684     }
3685     else {
3686       return result;
3687     }
3688   }
3689   else if (n_field_type == DBI_TYPE_STRING) {
3690     result = dbi_result_get_string_idx(Result, idx);
3691     if (dbi_conn_error_flag(dbi_result_get_conn(Result))) {
3692       return NULL;
3693     }
3694     else {
3695       return result;
3696     }
3697   }
3698   else {
3699     /* should never happen */
3700     return NULL;
3701   }
3702 }
3703 
3704 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3705   get_author_type_string(): returns a string that denotes the
3706                 author type depending on the driver
3707 
3708   const char* get_author_type_string returns a ptr to the result string
3709                  or NULL in case of an unsupported driver
3710 
3711   dbi_driver driver ptr to a database driver structure
3712 
3713   int type 1 = primary author, 2 = secondary author, 3 = tertiary author
3714 
3715   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
get_author_type_string(dbi_driver driver,int type)3716 const char* get_author_type_string(dbi_driver driver, int type) {
3717 
3718   if (!strcmp(my_dbi_driver_get_cap(driver, "enum"), "t")) {
3719     return author_type_string[0][type-1];
3720   }
3721   else {
3722     return author_type_string[1][type-1];
3723   }
3724 }
3725 
3726 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3727   is_in_list(): checks from a query result whether a given reference is
3728                 in the personal reference list of a given user
3729 
3730   int is_in_list returns 1 if the reference is in the list, 0 if not,
3731                  -1 if some error occurs
3732 
3733   dbi_result dbires database query result, pointing to the current
3734                     dataset
3735 
3736   char* username ptr to string with a username
3737 
3738   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
is_in_list(dbi_result dbires,char * username)3739 int is_in_list(dbi_result dbires, char* username) {
3740   char *sql_command;
3741   char *quoted_username;
3742   unsigned long long n_id;
3743   dbi_result dbires1;
3744   dbi_conn conn;
3745 
3746   sql_command = malloc(256);
3747 
3748   if (sql_command == NULL) {
3749     return -1;
3750   }
3751 
3752   conn = dbi_result_get_conn(dbires);
3753 
3754   quoted_username = mstrdup(username);
3755   if (!quoted_username) {
3756     free(sql_command);
3757     return -1;
3758   }
3759   if (dbi_conn_quote_string(conn, &quoted_username) == 0) {
3760     free(quoted_username);
3761     free(sql_command);
3762     return -1;
3763   }
3764 
3765   n_id = my_dbi_result_get_idval(dbires, "refdb_id");
3766 
3767   if (username != NULL && !dbi_conn_error_flag(conn)) {
3768     sprintf(sql_command, "SELECT t_xuser.xuser_id FROM t_xuser INNER JOIN t_user ON t_xuser.user_id=t_user.user_id WHERE t_user.user_name=%s AND t_xuser.refdb_id="ULLSPEC, quoted_username, (unsigned long long)n_id);
3769   }
3770   else {
3771     free(quoted_username);
3772     free(sql_command);
3773     return -1; /* should never happen */
3774   }
3775 
3776   free(quoted_username);
3777   LOG_PRINT(LOG_DEBUG, sql_command);
3778   dbires1 = dbi_conn_query(dbi_result_get_conn(dbires), sql_command);
3779   free(sql_command);
3780 
3781   if (!dbires1) {
3782     return -1;
3783   }
3784 
3785   if (dbi_result_next_row(dbires1)) {
3786     dbi_result_free(dbires1);
3787     return 1;
3788   }
3789   else {
3790     dbi_result_free(dbires1);
3791     return 0;
3792   }
3793 }
3794 
3795 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3796   load_style(): loads the style information for a particular publication
3797                 type
3798 
3799   dbi_result load_style returns query result if ok, NULL if an error occurred
3800 
3801   const char* pubtype ptr to string with the publication type
3802 
3803   unsigned int citstyle_id the ID of the citation style
3804 
3805   dbi_conn conn database connection
3806 
3807   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
load_style(const char * pubtype,unsigned int citstyle_id,dbi_conn conn)3808 dbi_result load_style(const char* pubtype, unsigned int citstyle_id, dbi_conn conn) {
3809   char* sql_command;
3810   const char *drivername;
3811 
3812   /* get memory for sql command buffer */
3813   sql_command = malloc(8192);
3814   if (!sql_command) {
3815     LOG_PRINT(LOG_WARNING, "out of memory");
3816     return NULL;
3817   }
3818   drivername = dbi_driver_get_name(dbi_conn_get_driver(conn));
3819 
3820   /*
3821 1	ID
3822 2	AUTHORLISTSTYLE
3823 3	EDITORLISTSTYLE
3824 4	SEDITORLISTSTYLE
3825 5	ALLALISTSTYLE
3826 6	AUTHORLISTALTERNATESTYLE
3827 7	EDITORLISTALTERNATESTYLE
3828 8	SEDITORLISTALTERNATESTYLE
3829 9	ALLALISTALTERNATESTYLE
3830 10	AUTHORLISTALTERNATETEXT
3831 11	EDITORLISTALTERNATETEXT
3832 12	SEDITORLISTALTERNATETEXT
3833 13	ALLALISTALTERNATETEXT
3834 14	AUTHORLISTABBREVIATEFIRST
3835 15	EDITORLISTABBREVIATEFIRST
3836 16	SEDITORLISTABBREVIATEFIRST
3837 17	ALLALISTABBREVIATEFIRST
3838 18	AUTHORLISTABBREVIATESUBSEQ
3839 19	EDITORLISTABBREVIATESUBSEQ
3840 20	SEDITORLISTABBREVIATESUBSEQ
3841 21	ALLALISTABBREVIATESUBSEQ
3842 22	AUTHORLISTABBREVIATEFIRSTMAXAUTHOR
3843 23	EDITORLISTABBREVIATEFIRSTMAXAUTHOR
3844 24	SEDITORLISTABBREVIATEFIRSTMAXAUTHOR
3845 25	ALLALISTABBREVIATEFIRSTMAXAUTHOR
3846 26	AUTHORLISTABBREVIATESUBSEQMAXAUTHOR
3847 27	EDITORLISTABBREVIATESUBSEQMAXAUTHOR
3848 28	SEDITORLISTABBREVIATESUBSEQMAXAUTHOR
3849 29	ALLALISTABBREVIATESUBSEQMAXAUTHOR
3850 30	AUTHORLISTABBREVIATEFIRSTDISPLAYAUTHOR
3851 31	EDITORLISTABBREVIATEFIRSTDISPLAYAUTHOR
3852 32	SEDITORLISTABBREVIATEFIRSTDISPLAYAUTHOR
3853 33	ALLALISTABBREVIATEFIRSTDISPLAYAUTHOR
3854 34	AUTHORLISTABBREVIATESUBSEQDISPLAYAUTHOR
3855 35	EDITORLISTABBREVIATESUBSEQDISPLAYAUTHOR
3856 36	SEDITORLISTABBREVIATESUBSEQDISPLAYAUTHOR
3857 37	ALLALISTABBREVIATESUBSEQDISPLAYAUTHOR
3858 38	AUTHORLISTAEMPTY
3859 39	EDITORLISTAEMPTY
3860 40	SEDITORLISTAEMPTY
3861 41	ALLALISTAEMPTY
3862 42	AUTHORLISTASAME
3863 43	EDITORLISTASAME
3864 44	SEDITORLISTASAME
3865 45	ALLALISTASAME
3866 46	AUTHORLISTPRECEEDING
3867 47	EDITORLISTPRECEEDING
3868 48	SEDITORLISTPRECEEDING
3869 49	ALLALISTPRECEEDING
3870 50	AUTHORLISTFOLLOWING
3871 51	EDITORLISTFOLLOWING
3872 52	SEDITORLISTFOLLOWING
3873 53	ALLALISTFOLLOWING
3874 54	AUTHORLISTAUTHORSEPSTWOSEPS
3875 55	EDITORLISTAUTHORSEPSTWOSEPS
3876 56	SEDITORLISTAUTHORSEPSTWOSEPS
3877 57	ALLALISTAUTHORSEPSTWOSEPS
3878 58	AUTHORLISTAUTHORSEPSTHREESEPSTHREESEPSEACH
3879 59	EDITORLISTAUTHORSEPSTHREESEPSTHREESEPSEACH
3880 60	SEDITORLISTAUTHORSEPSTHREESEPSTHREESEPSEACH
3881 61	ALLALISTAUTHORSEPSTHREESEPSTHREESEPSEACH
3882 62	AUTHORLISTAUTHORSEPSTHREESEPSTHREESEPSLAST
3883 63	EDITORLISTAUTHORSEPSTHREESEPSTHREESEPSLAST
3884 64	SEDITORLISTAUTHORSEPSTHREESEPSTHREESEPSLAST
3885 65	ALLALISTAUTHORSEPSTHREESEPSTHREESEPSLAST
3886 66	AUTHORLISTAUTHORNAMESNAMEFIRSTNAMEORDER
3887 67	EDITORLISTAUTHORNAMESNAMEFIRSTNAMEORDER
3888 68	SEDITORLISTAUTHORNAMESNAMEFIRSTNAMEORDER
3889 69	ALLALISTAUTHORNAMESNAMEFIRSTNAMEORDER
3890 70	AUTHORLISTAUTHORNAMESNAMEFIRSTINITIALSTYLE
3891 71	EDITORLISTAUTHORNAMESNAMEFIRSTINITIALSTYLE
3892 72	SEDITORLISTAUTHORNAMESNAMEFIRSTINITIALSTYLE
3893 73	ALLALISTAUTHORNAMESNAMEFIRSTINITIALSTYLE
3894 74	AUTHORLISTAUTHORNAMESNAMEFIRSTUPPERCASE
3895 75	EDITORLISTAUTHORNAMESNAMEFIRSTUPPERCASE
3896 76	SEDITORLISTAUTHORNAMESNAMEFIRSTUPPERCASE
3897 77	ALLALISTAUTHORNAMESNAMEFIRSTUPPERCASE
3898 78	AUTHORLISTAUTHORNAMESNAMEOTHERNAMEORDER
3899 79	EDITORLISTAUTHORNAMESNAMEOTHERNAMEORDER
3900 80	SEDITORLISTAUTHORNAMESNAMEOTHERNAMEORDER
3901 81	ALLALISTAUTHORNAMESNAMEOTHERNAMEORDER
3902 82	AUTHORLISTAUTHORNAMESNAMEOTHERINITIALSTYLE
3903 83	EDITORLISTAUTHORNAMESNAMEOTHERINITIALSTYLE
3904 84	SEDITORLISTAUTHORNAMESNAMEOTHERINITIALSTYLE
3905 85	ALLALISTAUTHORNAMESNAMEOTHERINITIALSTYLE
3906 86	AUTHORLISTAUTHORNAMESNAMEOTHERUPPERCASE
3907 87	EDITORLISTAUTHORNAMESNAMEOTHERUPPERCASE
3908 88	SEDITORLISTAUTHORNAMESNAMEOTHERUPPERCASE
3909 89	ALLALISTAUTHORNAMESNAMEOTHERUPPERCASE
3910 90	AUTHORLISTTEXTTEXTSINGLEPRECEEDING
3911 91	EDITORLISTTEXTTEXTSINGLEPRECEEDING
3912 92	SEDITORLISTTEXTTEXTSINGLEPRECEEDING
3913 93	ALLALISTTEXTTEXTSINGLEPRECEEDING
3914 94	AUTHORLISTTEXTTEXTSINGLEFOLLOWING
3915 95	EDITORLISTTEXTTEXTSINGLEFOLLOWING
3916 96	SEDITORLISTTEXTTEXTSINGLEFOLLOWING
3917 97	ALLALISTTEXTTEXTSINGLEFOLLOWING
3918 98	AUTHORLISTTEXTTEXTMULTIPLEPRECEEDING
3919 99	EDITORLISTTEXTTEXTMULTIPLEPRECEEDING
3920 100	SEDITORLISTTEXTTEXTMULTIPLEPRECEEDING
3921 101	ALLALISTTEXTTEXTMULTIPLEPRECEEDING
3922 102	AUTHORLISTTEXTTEXTMULTIPLEFOLLOWING
3923 103	EDITORLISTTEXTTEXTMULTIPLEFOLLOWING
3924 104	SEDITORLISTTEXTTEXTMULTIPLEFOLLOWING
3925 105	ALLALISTTEXTTEXTMULTIPLEFOLLOWING
3926 106	AUTHORLISTTEXTEDTEXTSINGLEPRECEEDING
3927 107	EDITORLISTTEXTEDTEXTSINGLEPRECEEDING
3928 108	SEDITORLISTTEXTEDTEXTSINGLEPRECEEDING
3929 109	ALLALISTTEXTEDTEXTSINGLEPRECEEDING
3930 110	AUTHORLISTTEXTEDTEXTSINGLEFOLLOWING
3931 111	EDITORLISTTEXTEDTEXTSINGLEFOLLOWING
3932 112	SEDITORLISTTEXTEDTEXTSINGLEFOLLOWING
3933 113	ALLALISTTEXTEDTEXTSINGLEFOLLOWING
3934 114	AUTHORLISTTEXTEDTEXTMULTIPLEPRECEEDING
3935 115	EDITORLISTTEXTEDTEXTMULTIPLEPRECEEDING
3936 116	SEDITORLISTTEXTEDTEXTMULTIPLEPRECEEDING
3937 117	ALLALISTTEXTEDTEXTMULTIPLEPRECEEDING
3938 118	AUTHORLISTTEXTEDTEXTMULTIPLEFOLLOWING
3939 119	EDITORLISTTEXTEDTEXTMULTIPLEFOLLOWING
3940 120	SEDITORLISTTEXTEDTEXTMULTIPLEFOLLOWING
3941 121	ALLALISTTEXTEDTEXTMULTIPLEFOLLOWING
3942 122	PUBDATEPRECEEDING
3943 123	PUBDATEFOLLOWING
3944 124	PUBDATEFORMAT
3945 125	PUBDATESEQUENCE
3946 126	PUBDATEMONTHFORMAT
3947 127	PUBDATEDAYFORMAT
3948 128	PUBDATEYEARFORMAT
3949 129	PUBDATEPADLEADINGZERO
3950 130	PUBDATESTYLE
3951 131	PUBDATESECPRECEEDING
3952 132	PUBDATESECFOLLOWING
3953 133	PUBDATESECFORMAT
3954 134	PUBDATESECSEQUENCE
3955 135	PUBDATESECMONTHFORMAT
3956 136	PUBDATESECDAYFORMAT
3957 137	PUBDATESECYEARFORMAT
3958 138	PUBDATESECPADLEADINGZERO
3959 139	PUBDATESECSTYLE
3960 140	PUBDATEALLPRECEEDING
3961 141	PUBDATEALLFOLLOWING
3962 142	PUBDATEALLFORMAT
3963 143	PUBDATEALLSEQUENCE
3964 144	PUBDATEALLMONTHFORMAT
3965 145	PUBDATEALLDAYFORMAT
3966 146	PUBDATEALLYEARFORMAT
3967 147	PUBDATEALLPADLEADINGZERO
3968 148	PUBDATEALLSTYLE
3969 149	TITLEPRECEEDING
3970 150	TITLEFOLLOWING
3971 151	TITLECASE
3972 152	TITLESTYLE
3973 153	BOOKTITLEPRECEEDING
3974 154	BOOKTITLEFOLLOWING
3975 155	BOOKTITLECASE
3976 156	BOOKTITLESTYLE
3977 157	SERIESTITLEPRECEEDING
3978 158	SERIESTITLEFOLLOWING
3979 159	SERIESTITLECASE
3980 160	SERIESTITLESTYLE
3981 161	ALLTITLEPRECEEDING
3982 162	ALLTITLEFOLLOWING
3983 163	ALLTITLECASE
3984 164	ALLTITLESTYLE
3985 165	JOURNALNAMEPRECEEDING
3986 166	JOURNALNAMEFOLLOWING
3987 167	JOURNALNAMECASE
3988 168	JOURNALNAMEDEFAULTTEXT
3989 169	JOURNALNAMEALTERNATETEXT
3990 170	JOURNALNAMEPUNCTUATION
3991 171	JOURNALNAMESTYLE
3992 172	VOLUMEPRECEEDING
3993 173	VOLUMEFOLLOWING
3994 174	VOLUMESTYLE
3995 175	ISSUEPRECEEDING
3996 176	ISSUEFOLLOWING
3997 177	ISSUESTYLE
3998 178	PAGESSTYLE
3999 179	PAGESSINGLEPAGEPRECEEDING
4000 180	PAGESSINGLEPAGEFOLLOWING
4001 181	PAGESPAGERANGEPRECEEDING
4002 182	PAGESPAGERANGEFOLLOWING
4003 183	PAGESPAGERANGETYPE
4004 184	PUBLISHERPRECEEDING
4005 185	PUBLISHERFOLLOWING
4006 186	PUBLISHERSTYLE
4007 187	PUBPLACEPRECEEDING
4008 188	PUBPLACEFOLLOWING
4009 189	PUBPLACESTYLE
4010 190	PAGESPRECEEDING
4011 191	PAGESFOLLOWING
4012 192	REFNUMBERPRECEEDING
4013 193	REFNUMBERFOLLOWING
4014 194	REFNUMBERSTYLE
4015 195	PUBDATEFIRSTSEP
4016 196	PUBDATESECONDSEP
4017 197	PUBDATESECFIRSTSEP
4018 198	PUBDATESECSECONDSEP
4019 199	PUBDATEALLFIRSTSEP
4020 200	PUBDATEALLSECONDSEP
4021 201	PAGESPAGERANGERANGESEPARATOR
4022 202	SERIALPRECEEDING
4023 203	SERIALFOLLOWING
4024 204	SERIALSTYLE
4025 205	ADDRESSPRECEEDING
4026 206	ADDRESSFOLLOWING
4027 207	ADDRESSSTYLE
4028 208	USERDEF1PRECEEDING
4029 209	USERDEF1FOLLOWING
4030 210	USERDEF1STYLE
4031 211	USERDEF2PRECEEDING
4032 212	USERDEF2FOLLOWING
4033 213	USERDEF2STYLE
4034 214	USERDEF3PRECEEDING
4035 215	USERDEF3FOLLOWING
4036 216	USERDEF3STYLE
4037 217	USERDEF4PRECEEDING
4038 218	USERDEF4FOLLOWING
4039 219	USERDEF4STYLE
4040 220	USERDEF5PRECEEDING
4041 221	USERDEF5FOLLOWING
4042 222	USERDEF5STYLE
4043 232	NOTESPRECEEDING
4044 233	NOTESFOLLOWING
4045 234	NOTESSTYLE
4046 235	ABSTRACTPRECEEDING
4047 236	ABSTRACTFOLLOWING
4048 237	ABSTRACTSTYLE
4049 TYPEOFWORKPRECEEDING
4050 TYPEOFWORKFOLLOWING
4051 TYPEOFWORKSTYLE
4052 AREAPRECEEDING
4053 AREAFOLLOWING
4054 AREASTYLE
4055 OSTYPEPRECEEDING
4056 OSTYPEFOLLOWING
4057 OSTYPESTYLE
4058 DEGREEPRECEEDING
4059 DEGREEFOLLOWING
4060 DEGREESTYLE
4061 RUNNINGTIMEPRECEEDING
4062 RUNNINGTIMEFOLLOWING
4063 RUNNINGTIMESTYLE
4064 CLASSCODEINTLPRECEEDING
4065 CLASSCODEINTLFOLLOWING
4066 CLASSCODEINTLSTYLE
4067 CLASSCODEUSPRECEEDING
4068 CLASSCODEUSFOLLOWING
4069 CLASSCODEUSSTYLE
4070 SENDEREMAILPRECEEDING
4071 SENDEREMAILFOLLOWING
4072 SENDEREMAILSTYLE
4073 RECIPIENTEMAILPRECEEDING
4074 RECIPIENTEMAILFOLLOWING
4075 RECIPIENTEMAILSTYLE
4076 MEDIATYPEPRECEEDING
4077 MEDIATYPEFOLLOWING
4078 MEDIATYPESTYLE
4079 NUMVOLUMESPRECEEDING
4080 NUMVOLUMESFOLLOWING
4081 NUMVOLUMESSTYLE
4082 EDITIONPRECEEDING
4083 EDITIONFOLLOWING
4084 EDITIONSTYLE
4085 COMPUTERPRECEEDING
4086 COMPUTERFOLLOWING
4087 COMPUTERSTYLE
4088 CONFERENCELOCATIONPRECEEDING
4089 CONFERENCELOCATIONFOLLOWING
4090 CONFERENCELOCATIONSTYLE
4091 REGISTRYNUMPRECEEDING
4092 REGISTRYNUMFOLLOWING
4093 REGISTRYNUMSTYLE
4094 CLASSIFICATIONPRECEEDING
4095 CLASSIFICATIONFOLLOWING
4096 CLASSIFICATIONSTYLE
4097 SECTIONPRECEEDING
4098 SECTIONFOLLOWING
4099 SECTIONSTYLE
4100 PAMPHLETNUMPRECEEDING
4101 PAMPHLETNUMFOLLOWING
4102 PAMPHLETNUMSTYLE
4103 CHAPTERNUMPRECEEDING
4104 CHAPTERNUMFOLLOWING
4105 CHAPTERNUMSTYLE
4106 238	LINK0PRECEEDING
4107 239	LINK0FOLLOWING
4108 240	LINK0STYLE
4109 241	LINK1PRECEEDING
4110 242	LINK1FOLLOWING
4111 243	LINK1STYLE
4112 244	LINK2PRECEEDING
4113 245	LINK2FOLLOWING
4114 246	LINK2STYLE
4115 247	LINK3PRECEEDING
4116 248	LINK3FOLLOWING
4117 249	LINK3STYLE
4118 250	LINK4PRECEEDING
4119 251	LINK4FOLLOWING
4120 252	LINK4STYLE
4121 253	CITEKEYPRECEEDING
4122 254	CITEKEYFOLLOWING
4123 255	CITEKEYSTYLE
4124    */
4125 
4126   /* now retrieve matching style information from REFSTYLE into*/
4127   if (!strcmp(my_dbi_conn_get_cap(conn, "multiple_db"), "t")) {
4128     sprintf(sql_command, "SELECT ID, QSTYLE, XSTYLE, YSTYLE, ZSTYLE, QALTERNATESTYLE, XALTERNATESTYLE, YALTERNATESTYLE, ZALTERNATESTYLE, QALTERNATETEXT, XALTERNATETEXT, YALTERNATETEXT, ZALTERNATETEXT, QABBREVIATEFIRST, XABBREVIATEFIRST, YABBREVIATEFIRST, ZABBREVIATEFIRST, QABBREVIATESUBSEQ, XABBREVIATESUBSEQ, YABBREVIATESUBSEQ, ZABBREVIATESUBSEQ, QABBREVIATEFIRSTMAXAUTHOR, XABBREVIATEFIRSTMAXAUTHOR, YABBREVIATEFIRSTMAXAUTHOR, ZABBREVIATEFIRSTMAXAUTHOR, QABBREVIATESUBSEQMAXAUTHOR, XABBREVIATESUBSEQMAXAUTHOR, YABBREVIATESUBSEQMAXAUTHOR, ZABBREVIATESUBSEQMAXAUTHOR, QABBREVIATEFIRSTDISPLAYAUTHOR, XABBREVIATEFIRSTDISPLAYAUTHOR, YABBREVIATEFIRSTDISPLAYAUTHOR, ZABBREVIATEFIRSTDISPLAYAUTHOR, QABBREVIATESUBSEQDISPLAYAUTHOR, XABBREVIATESUBSEQDISPLAYAUTHOR, YABBREVIATESUBSEQDISPLAYAUTHOR, ZABBREVIATESUBSEQDISPLAYAUTHOR, QAEMPTY, XAEMPTY, YAEMPTY, ZAEMPTY, QASAME, XASAME, YASAME, ZASAME, QPRECEEDING, XPRECEEDING, YPRECEEDING, ZPRECEEDING, QFOLLOWING, XFOLLOWING, YFOLLOWING, ZFOLLOWING, QAUTHORSEPSTWOSEPS, XAUTHORSEPSTWOSEPS, YAUTHORSEPSTWOSEPS, ZAUTHORSEPSTWOSEPS, QAUTHORSEPSTHREESEPSTHREESEPSEACH, XAUTHORSEPSTHREESEPSTHREESEPSEACH, YAUTHORSEPSTHREESEPSTHREESEPSEACH, ZAUTHORSEPSTHREESEPSTHREESEPSEACH, QAUTHORSEPSTHREESEPSTHREESEPSLAST, XAUTHORSEPSTHREESEPSTHREESEPSLAST, YAUTHORSEPSTHREESEPSTHREESEPSLAST, ZAUTHORSEPSTHREESEPSTHREESEPSLAST, QAUTHORNAMESNAMEFIRSTNAMEORDER, XAUTHORNAMESNAMEFIRSTNAMEORDER, YAUTHORNAMESNAMEFIRSTNAMEORDER, ZAUTHORNAMESNAMEFIRSTNAMEORDER, QAUTHORNAMESNAMEFIRSTINITIALSTYLE, XAUTHORNAMESNAMEFIRSTINITIALSTYLE, YAUTHORNAMESNAMEFIRSTINITIALSTYLE, ZAUTHORNAMESNAMEFIRSTINITIALSTYLE, QAUTHORNAMESNAMEFIRSTUPPERCASE, XAUTHORNAMESNAMEFIRSTUPPERCASE, YAUTHORNAMESNAMEFIRSTUPPERCASE, ZAUTHORNAMESNAMEFIRSTUPPERCASE, QAUTHORNAMESNAMEOTHERNAMEORDER, XAUTHORNAMESNAMEOTHERNAMEORDER, YAUTHORNAMESNAMEOTHERNAMEORDER, ZAUTHORNAMESNAMEOTHERNAMEORDER, QAUTHORNAMESNAMEOTHERINITIALSTYLE, XAUTHORNAMESNAMEOTHERINITIALSTYLE, YAUTHORNAMESNAMEOTHERINITIALSTYLE, ZAUTHORNAMESNAMEOTHERINITIALSTYLE, QAUTHORNAMESNAMEOTHERUPPERCASE, XAUTHORNAMESNAMEOTHERUPPERCASE, YAUTHORNAMESNAMEOTHERUPPERCASE, ZAUTHORNAMESNAMEOTHERUPPERCASE, QTEXTTEXTSINGLEPRECEEDING, XTEXTTEXTSINGLEPRECEEDING, YTEXTTEXTSINGLEPRECEEDING, ZTEXTTEXTSINGLEPRECEEDING, QTEXTTEXTSINGLEFOLLOWING, XTEXTTEXTSINGLEFOLLOWING, YTEXTTEXTSINGLEFOLLOWING, ZTEXTTEXTSINGLEFOLLOWING, QTEXTTEXTMULTIPLEPRECEEDING, XTEXTTEXTMULTIPLEPRECEEDING, YTEXTTEXTMULTIPLEPRECEEDING, ZTEXTTEXTMULTIPLEPRECEEDING, QTEXTTEXTMULTIPLEFOLLOWING, XTEXTTEXTMULTIPLEFOLLOWING, YTEXTTEXTMULTIPLEFOLLOWING, ZTEXTTEXTMULTIPLEFOLLOWING, QTEXTEDTEXTSINGLEPRECEEDING, XTEXTEDTEXTSINGLEPRECEEDING, YTEXTEDTEXTSINGLEPRECEEDING, ZTEXTEDTEXTSINGLEPRECEEDING, QTEXTEDTEXTSINGLEFOLLOWING, XTEXTEDTEXTSINGLEFOLLOWING, YTEXTEDTEXTSINGLEFOLLOWING, ZTEXTEDTEXTSINGLEFOLLOWING, QTEXTEDTEXTMULTIPLEPRECEEDING, XTEXTEDTEXTMULTIPLEPRECEEDING, YTEXTEDTEXTMULTIPLEPRECEEDING, ZTEXTEDTEXTMULTIPLEPRECEEDING, QTEXTEDTEXTMULTIPLEFOLLOWING, XTEXTEDTEXTMULTIPLEFOLLOWING, YTEXTEDTEXTMULTIPLEFOLLOWING, ZTEXTEDTEXTMULTIPLEFOLLOWING, PUBDATEPRECEEDING, PUBDATEFOLLOWING, PUBDATEFORMAT, PUBDATESEQUENCE, PUBDATEMONTHFORMAT, PUBDATEDAYFORMAT, PUBDATEYEARFORMAT, PUBDATEPADLEADINGZERO, PUBDATESTYLE, PUBDATESECPRECEEDING, PUBDATESECFOLLOWING, PUBDATESECFORMAT, PUBDATESECSEQUENCE, PUBDATESECMONTHFORMAT, PUBDATESECDAYFORMAT, PUBDATESECYEARFORMAT, PUBDATESECPADLEADINGZERO, PUBDATESECSTYLE, PUBDATEALLPRECEEDING, PUBDATEALLFOLLOWING, PUBDATEALLFORMAT, PUBDATEALLSEQUENCE, PUBDATEALLMONTHFORMAT, PUBDATEALLDAYFORMAT, PUBDATEALLYEARFORMAT, PUBDATEALLPADLEADINGZERO, PUBDATEALLSTYLE, TITLEPRECEEDING, TITLEFOLLOWING, TITLECASE, TITLESTYLE, BOOKTITLEPRECEEDING, BOOKTITLEFOLLOWING, BOOKTITLECASE, BOOKTITLESTYLE, SERIESTITLEPRECEEDING, SERIESTITLEFOLLOWING, SERIESTITLECASE, SERIESTITLESTYLE, ALLTITLEPRECEEDING, ALLTITLEFOLLOWING, ALLTITLECASE, ALLTITLESTYLE, JOURNALNAMEPRECEEDING, JOURNALNAMEFOLLOWING, JOURNALNAMECASE, JOURNALNAMEDEFAULTTEXT, JOURNALNAMEALTERNATETEXT, JOURNALNAMEPUNCTUATION, JOURNALNAMESTYLE, VOLUMEPRECEEDING, VOLUMEFOLLOWING, VOLUMESTYLE, ISSUEPRECEEDING, ISSUEFOLLOWING, ISSUESTYLE, PAGESSTYLE, PAGESSINGLEPAGEPRECEEDING, PAGESSINGLEPAGEFOLLOWING, PAGESPAGERANGEPRECEEDING, PAGESPAGERANGEFOLLOWING, PAGESPAGERANGETYPE, PUBLISHERPRECEEDING, PUBLISHERFOLLOWING, PUBLISHERSTYLE, PUBPLACEPRECEEDING, PUBPLACEFOLLOWING, PUBPLACESTYLE, PAGESPRECEEDING, PAGESFOLLOWING, REFNUMBERPRECEEDING, REFNUMBERFOLLOWING, REFNUMBERSTYLE, PUBDATEFIRSTSEP, PUBDATESECONDSEP, PUBDATESECFIRSTSEP, PUBDATESECSECONDSEP, PUBDATEALLFIRSTSEP, PUBDATEALLSECONDSEP, PAGESPAGERANGERANGESEPARATOR, SERIALPRECEEDING, SERIALFOLLOWING, SERIALSTYLE, ADDRESSPRECEEDING, ADDRESSFOLLOWING, ADDRESSSTYLE, USERDEF1PRECEEDING, USERDEF1FOLLOWING, USERDEF1STYLE, USERDEF2PRECEEDING, USERDEF2FOLLOWING, USERDEF2STYLE, USERDEF3PRECEEDING, USERDEF3FOLLOWING, USERDEF3STYLE, USERDEF4PRECEEDING, USERDEF4FOLLOWING, USERDEF4STYLE, USERDEF5PRECEEDING, USERDEF5FOLLOWING, USERDEF5STYLE, NOTESPRECEEDING, NOTESFOLLOWING, NOTESSTYLE, ABSTRACTPRECEEDING, ABSTRACTFOLLOWING, ABSTRACTSTYLE, TYPEOFWORKPRECEEDING, TYPEOFWORKFOLLOWING, TYPEOFWORKSTYLE, AREAPRECEEDING, AREAFOLLOWING, AREASTYLE, OSTYPEPRECEEDING, OSTYPEFOLLOWING, OSTYPESTYLE, DEGREEPRECEEDING, DEGREEFOLLOWING, DEGREESTYLE, RUNNINGTIMEPRECEEDING, RUNNINGTIMEFOLLOWING, RUNNINGTIMESTYLE, CLASSCODEINTLPRECEEDING, CLASSCODEINTLFOLLOWING, CLASSCODEINTLSTYLE, CLASSCODEUSPRECEEDING, CLASSCODEUSFOLLOWING, CLASSCODEUSSTYLE, SENDEREMAILPRECEEDING, SENDEREMAILFOLLOWING, SENDEREMAILSTYLE, RECIPIENTEMAILPRECEEDING, RECIPIENTEMAILFOLLOWING, RECIPIENTEMAILSTYLE, MEDIATYPEPRECEEDING, MEDIATYPEFOLLOWING, MEDIATYPESTYLE, NUMVOLUMESPRECEEDING, NUMVOLUMESFOLLOWING, NUMVOLUMESSTYLE, EDITIONPRECEEDING, EDITIONFOLLOWING, EDITIONSTYLE, COMPUTERPRECEEDING, COMPUTERFOLLOWING, COMPUTERSTYLE, CONFERENCELOCATIONPRECEEDING, CONFERENCELOCATIONFOLLOWING, CONFERENCELOCATIONSTYLE, REGISTRYNUMPRECEEDING, REGISTRYNUMFOLLOWING, REGISTRYNUMSTYLE, CLASSIFICATIONPRECEEDING, CLASSIFICATIONFOLLOWING, CLASSIFICATIONSTYLE, SECTIONPRECEEDING, SECTIONFOLLOWING, SECTIONSTYLE, PAMPHLETNUMPRECEEDING, PAMPHLETNUMFOLLOWING, PAMPHLETNUMSTYLE, CHAPTERNUMPRECEEDING, CHAPTERNUMFOLLOWING, CHAPTERNUMSTYLE, LINK0PRECEEDING, LINK0FOLLOWING, LINK0STYLE, LINK1PRECEEDING, LINK1FOLLOWING, LINK1STYLE, LINK2PRECEEDING, LINK2FOLLOWING, LINK2STYLE, LINK3PRECEEDING, LINK3FOLLOWING, LINK3STYLE, LINK4PRECEEDING, LINK4FOLLOWING, LINK4STYLE, CITEKEYPRECEEDING, CITEKEYFOLLOWING, CITEKEYSTYLE from %s.REFSTYLE where PUBTYPE='%s' and CITSTYLEID=%u", main_db, pubtype, citstyle_id);
4129   }
4130   else {
4131     sprintf(sql_command, "SELECT ID, QSTYLE, XSTYLE, YSTYLE, ZSTYLE, QALTERNATESTYLE, XALTERNATESTYLE, YALTERNATESTYLE, ZALTERNATESTYLE, QALTERNATETEXT, XALTERNATETEXT, YALTERNATETEXT, ZALTERNATETEXT, QABBREVIATEFIRST, XABBREVIATEFIRST, YABBREVIATEFIRST, ZABBREVIATEFIRST, QABBREVIATESUBSEQ, XABBREVIATESUBSEQ, YABBREVIATESUBSEQ, ZABBREVIATESUBSEQ, QABBREVIATEFIRSTMAXAUTHOR, XABBREVIATEFIRSTMAXAUTHOR, YABBREVIATEFIRSTMAXAUTHOR, ZABBREVIATEFIRSTMAXAUTHOR, QABBREVIATESUBSEQMAXAUTHOR, XABBREVIATESUBSEQMAXAUTHOR, YABBREVIATESUBSEQMAXAUTHOR, ZABBREVIATESUBSEQMAXAUTHOR, QABBREVIATEFIRSTDISPLAYAUTHOR, XABBREVIATEFIRSTDISPLAYAUTHOR, YABBREVIATEFIRSTDISPLAYAUTHOR, ZABBREVIATEFIRSTDISPLAYAUTHOR, QABBREVIATESUBSEQDISPLAYAUTHOR, XABBREVIATESUBSEQDISPLAYAUTHOR, YABBREVIATESUBSEQDISPLAYAUTHOR, ZABBREVIATESUBSEQDISPLAYAUTHOR, QAEMPTY, XAEMPTY, YAEMPTY, ZAEMPTY, QASAME, XASAME, YASAME, ZASAME, QPRECEEDING, XPRECEEDING, YPRECEEDING, ZPRECEEDING, QFOLLOWING, XFOLLOWING, YFOLLOWING, ZFOLLOWING, QAUTHORSEPSTWOSEPS, XAUTHORSEPSTWOSEPS, YAUTHORSEPSTWOSEPS, ZAUTHORSEPSTWOSEPS, QAUTHORSEPSTHREESEPSTHREESEPSEACH, XAUTHORSEPSTHREESEPSTHREESEPSEACH, YAUTHORSEPSTHREESEPSTHREESEPSEACH, ZAUTHORSEPSTHREESEPSTHREESEPSEACH, QAUTHORSEPSTHREESEPSTHREESEPSLAST, XAUTHORSEPSTHREESEPSTHREESEPSLAST, YAUTHORSEPSTHREESEPSTHREESEPSLAST, ZAUTHORSEPSTHREESEPSTHREESEPSLAST, QAUTHORNAMESNAMEFIRSTNAMEORDER, XAUTHORNAMESNAMEFIRSTNAMEORDER, YAUTHORNAMESNAMEFIRSTNAMEORDER, ZAUTHORNAMESNAMEFIRSTNAMEORDER, QAUTHORNAMESNAMEFIRSTINITIALSTYLE, XAUTHORNAMESNAMEFIRSTINITIALSTYLE, YAUTHORNAMESNAMEFIRSTINITIALSTYLE, ZAUTHORNAMESNAMEFIRSTINITIALSTYLE, QAUTHORNAMESNAMEFIRSTUPPERCASE, XAUTHORNAMESNAMEFIRSTUPPERCASE, YAUTHORNAMESNAMEFIRSTUPPERCASE, ZAUTHORNAMESNAMEFIRSTUPPERCASE, QAUTHORNAMESNAMEOTHERNAMEORDER, XAUTHORNAMESNAMEOTHERNAMEORDER, YAUTHORNAMESNAMEOTHERNAMEORDER, ZAUTHORNAMESNAMEOTHERNAMEORDER, QAUTHORNAMESNAMEOTHERINITIALSTYLE, XAUTHORNAMESNAMEOTHERINITIALSTYLE, YAUTHORNAMESNAMEOTHERINITIALSTYLE, ZAUTHORNAMESNAMEOTHERINITIALSTYLE, QAUTHORNAMESNAMEOTHERUPPERCASE, XAUTHORNAMESNAMEOTHERUPPERCASE, YAUTHORNAMESNAMEOTHERUPPERCASE, ZAUTHORNAMESNAMEOTHERUPPERCASE, QTEXTTEXTSINGLEPRECEEDING, XTEXTTEXTSINGLEPRECEEDING, YTEXTTEXTSINGLEPRECEEDING, ZTEXTTEXTSINGLEPRECEEDING, QTEXTTEXTSINGLEFOLLOWING, XTEXTTEXTSINGLEFOLLOWING, YTEXTTEXTSINGLEFOLLOWING, ZTEXTTEXTSINGLEFOLLOWING, QTEXTTEXTMULTIPLEPRECEEDING, XTEXTTEXTMULTIPLEPRECEEDING, YTEXTTEXTMULTIPLEPRECEEDING, ZTEXTTEXTMULTIPLEPRECEEDING, QTEXTTEXTMULTIPLEFOLLOWING, XTEXTTEXTMULTIPLEFOLLOWING, YTEXTTEXTMULTIPLEFOLLOWING, ZTEXTTEXTMULTIPLEFOLLOWING, QTEXTEDTEXTSINGLEPRECEEDING, XTEXTEDTEXTSINGLEPRECEEDING, YTEXTEDTEXTSINGLEPRECEEDING, ZTEXTEDTEXTSINGLEPRECEEDING, QTEXTEDTEXTSINGLEFOLLOWING, XTEXTEDTEXTSINGLEFOLLOWING, YTEXTEDTEXTSINGLEFOLLOWING, ZTEXTEDTEXTSINGLEFOLLOWING, QTEXTEDTEXTMULTIPLEPRECEEDING, XTEXTEDTEXTMULTIPLEPRECEEDING, YTEXTEDTEXTMULTIPLEPRECEEDING, ZTEXTEDTEXTMULTIPLEPRECEEDING, QTEXTEDTEXTMULTIPLEFOLLOWING, XTEXTEDTEXTMULTIPLEFOLLOWING, YTEXTEDTEXTMULTIPLEFOLLOWING, ZTEXTEDTEXTMULTIPLEFOLLOWING, PUBDATEPRECEEDING, PUBDATEFOLLOWING, PUBDATEFORMAT, PUBDATESEQUENCE, PUBDATEMONTHFORMAT, PUBDATEDAYFORMAT, PUBDATEYEARFORMAT, PUBDATEPADLEADINGZERO, PUBDATESTYLE, PUBDATESECPRECEEDING, PUBDATESECFOLLOWING, PUBDATESECFORMAT, PUBDATESECSEQUENCE, PUBDATESECMONTHFORMAT, PUBDATESECDAYFORMAT, PUBDATESECYEARFORMAT, PUBDATESECPADLEADINGZERO, PUBDATESECSTYLE, PUBDATEALLPRECEEDING, PUBDATEALLFOLLOWING, PUBDATEALLFORMAT, PUBDATEALLSEQUENCE, PUBDATEALLMONTHFORMAT, PUBDATEALLDAYFORMAT, PUBDATEALLYEARFORMAT, PUBDATEALLPADLEADINGZERO, PUBDATEALLSTYLE, TITLEPRECEEDING, TITLEFOLLOWING, TITLECASE, TITLESTYLE, BOOKTITLEPRECEEDING, BOOKTITLEFOLLOWING, BOOKTITLECASE, BOOKTITLESTYLE, SERIESTITLEPRECEEDING, SERIESTITLEFOLLOWING, SERIESTITLECASE, SERIESTITLESTYLE, ALLTITLEPRECEEDING, ALLTITLEFOLLOWING, ALLTITLECASE, ALLTITLESTYLE, JOURNALNAMEPRECEEDING, JOURNALNAMEFOLLOWING, JOURNALNAMECASE, JOURNALNAMEDEFAULTTEXT, JOURNALNAMEALTERNATETEXT, JOURNALNAMEPUNCTUATION, JOURNALNAMESTYLE, VOLUMEPRECEEDING, VOLUMEFOLLOWING, VOLUMESTYLE, ISSUEPRECEEDING, ISSUEFOLLOWING, ISSUESTYLE, PAGESSTYLE, PAGESSINGLEPAGEPRECEEDING, PAGESSINGLEPAGEFOLLOWING, PAGESPAGERANGEPRECEEDING, PAGESPAGERANGEFOLLOWING, PAGESPAGERANGETYPE, PUBLISHERPRECEEDING, PUBLISHERFOLLOWING, PUBLISHERSTYLE, PUBPLACEPRECEEDING, PUBPLACEFOLLOWING, PUBPLACESTYLE, PAGESPRECEEDING, PAGESFOLLOWING, REFNUMBERPRECEEDING, REFNUMBERFOLLOWING, REFNUMBERSTYLE, PUBDATEFIRSTSEP, PUBDATESECONDSEP, PUBDATESECFIRSTSEP, PUBDATESECSECONDSEP, PUBDATEALLFIRSTSEP, PUBDATEALLSECONDSEP, PAGESPAGERANGERANGESEPARATOR, SERIALPRECEEDING, SERIALFOLLOWING, SERIALSTYLE, ADDRESSPRECEEDING, ADDRESSFOLLOWING, ADDRESSSTYLE, USERDEF1PRECEEDING, USERDEF1FOLLOWING, USERDEF1STYLE, USERDEF2PRECEEDING, USERDEF2FOLLOWING, USERDEF2STYLE, USERDEF3PRECEEDING, USERDEF3FOLLOWING, USERDEF3STYLE, USERDEF4PRECEEDING, USERDEF4FOLLOWING, USERDEF4STYLE, USERDEF5PRECEEDING, USERDEF5FOLLOWING, USERDEF5STYLE, NOTESPRECEEDING, NOTESFOLLOWING, NOTESSTYLE, ABSTRACTPRECEEDING, ABSTRACTFOLLOWING, ABSTRACTSTYLE, TYPEOFWORKPRECEEDING, TYPEOFWORKFOLLOWING, TYPEOFWORKSTYLE, AREAPRECEEDING, AREAFOLLOWING, AREASTYLE, OSTYPEPRECEEDING, OSTYPEFOLLOWING, OSTYPESTYLE, DEGREEPRECEEDING, DEGREEFOLLOWING, DEGREESTYLE, RUNNINGTIMEPRECEEDING, RUNNINGTIMEFOLLOWING, RUNNINGTIMESTYLE, CLASSCODEINTLPRECEEDING, CLASSCODEINTLFOLLOWING, CLASSCODEINTLSTYLE, CLASSCODEUSPRECEEDING, CLASSCODEUSFOLLOWING, CLASSCODEUSSTYLE, SENDEREMAILPRECEEDING, SENDEREMAILFOLLOWING, SENDEREMAILSTYLE, RECIPIENTEMAILPRECEEDING, RECIPIENTEMAILFOLLOWING, RECIPIENTEMAILSTYLE, MEDIATYPEPRECEEDING, MEDIATYPEFOLLOWING, MEDIATYPESTYLE, NUMVOLUMESPRECEEDING, NUMVOLUMESFOLLOWING, NUMVOLUMESSTYLE, EDITIONPRECEEDING, EDITIONFOLLOWING, EDITIONSTYLE, COMPUTERPRECEEDING, COMPUTERFOLLOWING, COMPUTERSTYLE, CONFERENCELOCATIONPRECEEDING, CONFERENCELOCATIONFOLLOWING, CONFERENCELOCATIONSTYLE, REGISTRYNUMPRECEEDING, REGISTRYNUMFOLLOWING, REGISTRYNUMSTYLE, CLASSIFICATIONPRECEEDING, CLASSIFICATIONFOLLOWING, CLASSIFICATIONSTYLE, SECTIONPRECEEDING, SECTIONFOLLOWING, SECTIONSTYLE, PAMPHLETNUMPRECEEDING, PAMPHLETNUMFOLLOWING, PAMPHLETNUMSTYLE, CHAPTERNUMPRECEEDING, CHAPTERNUMFOLLOWING, CHAPTERNUMSTYLE, LINK0PRECEEDING, LINK0FOLLOWING, LINK0STYLE, LINK1PRECEEDING, LINK1FOLLOWING, LINK1STYLE, LINK2PRECEEDING, LINK2FOLLOWING, LINK2STYLE, LINK3PRECEEDING, LINK3FOLLOWING, LINK3STYLE, LINK4PRECEEDING, LINK4FOLLOWING, LINK4STYLE, CITEKEYPRECEEDING, CITEKEYFOLLOWING, CITEKEYSTYLE from REFSTYLE where PUBTYPE='%s' and CITSTYLEID=%u", pubtype, citstyle_id);
4132   }
4133 
4134   LOG_PRINT(LOG_DEBUG, sql_command);
4135   dbi_style_res = dbi_conn_query(conn, sql_command);
4136 
4137   if (!dbi_style_res) {
4138     dbi_conn_error(conn, (const char**)&sql_command);
4139     LOG_PRINT(LOG_WARNING, "CITSTYLE select failed");
4140     LOG_PRINT(LOG_WARNING, sql_command);
4141     free(sql_command);
4142     return NULL;
4143   }
4144 
4145   if (dbi_result_next_row(dbi_style_res) == 0) {
4146     /* there is no style for this citation type. Try the generic type instead */
4147     dbi_result_free(dbi_style_res);
4148     if (!strcmp(my_dbi_conn_get_cap(conn, "multiple_db"), "t")) {
4149       sprintf(sql_command, "SELECT ID, QSTYLE, XSTYLE, YSTYLE, ZSTYLE, QALTERNATESTYLE, XALTERNATESTYLE, YALTERNATESTYLE, ZALTERNATESTYLE, QALTERNATETEXT, XALTERNATETEXT, YALTERNATETEXT, ZALTERNATETEXT, QABBREVIATEFIRST, XABBREVIATEFIRST, YABBREVIATEFIRST, ZABBREVIATEFIRST, QABBREVIATESUBSEQ, XABBREVIATESUBSEQ, YABBREVIATESUBSEQ, ZABBREVIATESUBSEQ, QABBREVIATEFIRSTMAXAUTHOR, XABBREVIATEFIRSTMAXAUTHOR, YABBREVIATEFIRSTMAXAUTHOR, ZABBREVIATEFIRSTMAXAUTHOR, QABBREVIATESUBSEQMAXAUTHOR, XABBREVIATESUBSEQMAXAUTHOR, YABBREVIATESUBSEQMAXAUTHOR, ZABBREVIATESUBSEQMAXAUTHOR, QABBREVIATEFIRSTDISPLAYAUTHOR, XABBREVIATEFIRSTDISPLAYAUTHOR, YABBREVIATEFIRSTDISPLAYAUTHOR, ZABBREVIATEFIRSTDISPLAYAUTHOR, QABBREVIATESUBSEQDISPLAYAUTHOR, XABBREVIATESUBSEQDISPLAYAUTHOR, YABBREVIATESUBSEQDISPLAYAUTHOR, ZABBREVIATESUBSEQDISPLAYAUTHOR, QAEMPTY, XAEMPTY, YAEMPTY, ZAEMPTY, QASAME, XASAME, YASAME, ZASAME, QPRECEEDING, XPRECEEDING, YPRECEEDING, ZPRECEEDING, QFOLLOWING, XFOLLOWING, YFOLLOWING, ZFOLLOWING, QAUTHORSEPSTWOSEPS, XAUTHORSEPSTWOSEPS, YAUTHORSEPSTWOSEPS, ZAUTHORSEPSTWOSEPS, QAUTHORSEPSTHREESEPSTHREESEPSEACH, XAUTHORSEPSTHREESEPSTHREESEPSEACH, YAUTHORSEPSTHREESEPSTHREESEPSEACH, ZAUTHORSEPSTHREESEPSTHREESEPSEACH, QAUTHORSEPSTHREESEPSTHREESEPSLAST, XAUTHORSEPSTHREESEPSTHREESEPSLAST, YAUTHORSEPSTHREESEPSTHREESEPSLAST, ZAUTHORSEPSTHREESEPSTHREESEPSLAST, QAUTHORNAMESNAMEFIRSTNAMEORDER, XAUTHORNAMESNAMEFIRSTNAMEORDER, YAUTHORNAMESNAMEFIRSTNAMEORDER, ZAUTHORNAMESNAMEFIRSTNAMEORDER, QAUTHORNAMESNAMEFIRSTINITIALSTYLE, XAUTHORNAMESNAMEFIRSTINITIALSTYLE, YAUTHORNAMESNAMEFIRSTINITIALSTYLE, ZAUTHORNAMESNAMEFIRSTINITIALSTYLE, QAUTHORNAMESNAMEFIRSTUPPERCASE, XAUTHORNAMESNAMEFIRSTUPPERCASE, YAUTHORNAMESNAMEFIRSTUPPERCASE, ZAUTHORNAMESNAMEFIRSTUPPERCASE, QAUTHORNAMESNAMEOTHERNAMEORDER, XAUTHORNAMESNAMEOTHERNAMEORDER, YAUTHORNAMESNAMEOTHERNAMEORDER, ZAUTHORNAMESNAMEOTHERNAMEORDER, QAUTHORNAMESNAMEOTHERINITIALSTYLE, XAUTHORNAMESNAMEOTHERINITIALSTYLE, YAUTHORNAMESNAMEOTHERINITIALSTYLE, ZAUTHORNAMESNAMEOTHERINITIALSTYLE, QAUTHORNAMESNAMEOTHERUPPERCASE, XAUTHORNAMESNAMEOTHERUPPERCASE, YAUTHORNAMESNAMEOTHERUPPERCASE, ZAUTHORNAMESNAMEOTHERUPPERCASE, QTEXTTEXTSINGLEPRECEEDING, XTEXTTEXTSINGLEPRECEEDING, YTEXTTEXTSINGLEPRECEEDING, ZTEXTTEXTSINGLEPRECEEDING, QTEXTTEXTSINGLEFOLLOWING, XTEXTTEXTSINGLEFOLLOWING, YTEXTTEXTSINGLEFOLLOWING, ZTEXTTEXTSINGLEFOLLOWING, QTEXTTEXTMULTIPLEPRECEEDING, XTEXTTEXTMULTIPLEPRECEEDING, YTEXTTEXTMULTIPLEPRECEEDING, ZTEXTTEXTMULTIPLEPRECEEDING, QTEXTTEXTMULTIPLEFOLLOWING, XTEXTTEXTMULTIPLEFOLLOWING, YTEXTTEXTMULTIPLEFOLLOWING, ZTEXTTEXTMULTIPLEFOLLOWING, QTEXTEDTEXTSINGLEPRECEEDING, XTEXTEDTEXTSINGLEPRECEEDING, YTEXTEDTEXTSINGLEPRECEEDING, ZTEXTEDTEXTSINGLEPRECEEDING, QTEXTEDTEXTSINGLEFOLLOWING, XTEXTEDTEXTSINGLEFOLLOWING, YTEXTEDTEXTSINGLEFOLLOWING, ZTEXTEDTEXTSINGLEFOLLOWING, QTEXTEDTEXTMULTIPLEPRECEEDING, XTEXTEDTEXTMULTIPLEPRECEEDING, YTEXTEDTEXTMULTIPLEPRECEEDING, ZTEXTEDTEXTMULTIPLEPRECEEDING, QTEXTEDTEXTMULTIPLEFOLLOWING, XTEXTEDTEXTMULTIPLEFOLLOWING, YTEXTEDTEXTMULTIPLEFOLLOWING, ZTEXTEDTEXTMULTIPLEFOLLOWING, PUBDATEPRECEEDING, PUBDATEFOLLOWING, PUBDATEFORMAT, PUBDATESEQUENCE, PUBDATEMONTHFORMAT, PUBDATEDAYFORMAT, PUBDATEYEARFORMAT, PUBDATEPADLEADINGZERO, PUBDATESTYLE, PUBDATESECPRECEEDING, PUBDATESECFOLLOWING, PUBDATESECFORMAT, PUBDATESECSEQUENCE, PUBDATESECMONTHFORMAT, PUBDATESECDAYFORMAT, PUBDATESECYEARFORMAT, PUBDATESECPADLEADINGZERO, PUBDATESECSTYLE, PUBDATEALLPRECEEDING, PUBDATEALLFOLLOWING, PUBDATEALLFORMAT, PUBDATEALLSEQUENCE, PUBDATEALLMONTHFORMAT, PUBDATEALLDAYFORMAT, PUBDATEALLYEARFORMAT, PUBDATEALLPADLEADINGZERO, PUBDATEALLSTYLE, TITLEPRECEEDING, TITLEFOLLOWING, TITLECASE, TITLESTYLE, BOOKTITLEPRECEEDING, BOOKTITLEFOLLOWING, BOOKTITLECASE, BOOKTITLESTYLE, SERIESTITLEPRECEEDING, SERIESTITLEFOLLOWING, SERIESTITLECASE, SERIESTITLESTYLE, ALLTITLEPRECEEDING, ALLTITLEFOLLOWING, ALLTITLECASE, ALLTITLESTYLE, JOURNALNAMEPRECEEDING, JOURNALNAMEFOLLOWING, JOURNALNAMECASE, JOURNALNAMEDEFAULTTEXT, JOURNALNAMEALTERNATETEXT, JOURNALNAMEPUNCTUATION, JOURNALNAMESTYLE, VOLUMEPRECEEDING, VOLUMEFOLLOWING, VOLUMESTYLE, ISSUEPRECEEDING, ISSUEFOLLOWING, ISSUESTYLE, PAGESSTYLE, PAGESSINGLEPAGEPRECEEDING, PAGESSINGLEPAGEFOLLOWING, PAGESPAGERANGEPRECEEDING, PAGESPAGERANGEFOLLOWING, PAGESPAGERANGETYPE, PUBLISHERPRECEEDING, PUBLISHERFOLLOWING, PUBLISHERSTYLE, PUBPLACEPRECEEDING, PUBPLACEFOLLOWING, PUBPLACESTYLE, PAGESPRECEEDING, PAGESFOLLOWING, REFNUMBERPRECEEDING, REFNUMBERFOLLOWING, REFNUMBERSTYLE, PUBDATEFIRSTSEP, PUBDATESECONDSEP, PUBDATESECFIRSTSEP, PUBDATESECSECONDSEP, PUBDATEALLFIRSTSEP, PUBDATEALLSECONDSEP, PAGESPAGERANGERANGESEPARATOR, SERIALPRECEEDING, SERIALFOLLOWING, SERIALSTYLE, ADDRESSPRECEEDING, ADDRESSFOLLOWING, ADDRESSSTYLE, USERDEF1PRECEEDING, USERDEF1FOLLOWING, USERDEF1STYLE, USERDEF2PRECEEDING, USERDEF2FOLLOWING, USERDEF2STYLE, USERDEF3PRECEEDING, USERDEF3FOLLOWING, USERDEF3STYLE, USERDEF4PRECEEDING, USERDEF4FOLLOWING, USERDEF4STYLE, USERDEF5PRECEEDING, USERDEF5FOLLOWING, USERDEF5STYLE, NOTESPRECEEDING, NOTESFOLLOWING, NOTESSTYLE, ABSTRACTPRECEEDING, ABSTRACTFOLLOWING, ABSTRACTSTYLE, TYPEOFWORKPRECEEDING, TYPEOFWORKFOLLOWING, TYPEOFWORKSTYLE, AREAPRECEEDING, AREAFOLLOWING, AREASTYLE, OSTYPEPRECEEDING, OSTYPEFOLLOWING, OSTYPESTYLE, DEGREEPRECEEDING, DEGREEFOLLOWING, DEGREESTYLE, RUNNINGTIMEPRECEEDING, RUNNINGTIMEFOLLOWING, RUNNINGTIMESTYLE, CLASSCODEINTLPRECEEDING, CLASSCODEINTLFOLLOWING, CLASSCODEINTLSTYLE, CLASSCODEUSPRECEEDING, CLASSCODEUSFOLLOWING, CLASSCODEUSSTYLE, SENDEREMAILPRECEEDING, SENDEREMAILFOLLOWING, SENDEREMAILSTYLE, RECIPIENTEMAILPRECEEDING, RECIPIENTEMAILFOLLOWING, RECIPIENTEMAILSTYLE, MEDIATYPEPRECEEDING, MEDIATYPEFOLLOWING, MEDIATYPESTYLE, NUMVOLUMESPRECEEDING, NUMVOLUMESFOLLOWING, NUMVOLUMESSTYLE, EDITIONPRECEEDING, EDITIONFOLLOWING, EDITIONSTYLE, COMPUTERPRECEEDING, COMPUTERFOLLOWING, COMPUTERSTYLE, CONFERENCELOCATIONPRECEEDING, CONFERENCELOCATIONFOLLOWING, CONFERENCELOCATIONSTYLE, REGISTRYNUMPRECEEDING, REGISTRYNUMFOLLOWING, REGISTRYNUMSTYLE, CLASSIFICATIONPRECEEDING, CLASSIFICATIONFOLLOWING, CLASSIFICATIONSTYLE, SECTIONPRECEEDING, SECTIONFOLLOWING, SECTIONSTYLE, PAMPHLETNUMPRECEEDING, PAMPHLETNUMFOLLOWING, PAMPHLETNUMSTYLE, CHAPTERNUMPRECEEDING, CHAPTERNUMFOLLOWING, CHAPTERNUMSTYLE, LINK0PRECEEDING, LINK0FOLLOWING, LINK0STYLE, LINK1PRECEEDING, LINK1FOLLOWING, LINK1STYLE, LINK2PRECEEDING, LINK2FOLLOWING, LINK2STYLE, LINK3PRECEEDING, LINK3FOLLOWING, LINK3STYLE, LINK4PRECEEDING, LINK4FOLLOWING, LINK4STYLE, CITEKEYPRECEEDING, CITEKEYFOLLOWING, CITEKEYSTYLE from %s.REFSTYLE where PUBTYPE='GEN' and CITSTYLEID=%u", main_db, citstyle_id);
4150     }
4151     else {
4152       sprintf(sql_command, "SELECT ID, QSTYLE, XSTYLE, YSTYLE, ZSTYLE, QALTERNATESTYLE, XALTERNATESTYLE, YALTERNATESTYLE, ZALTERNATESTYLE, QALTERNATETEXT, XALTERNATETEXT, YALTERNATETEXT, ZALTERNATETEXT, QABBREVIATEFIRST, XABBREVIATEFIRST, YABBREVIATEFIRST, ZABBREVIATEFIRST, QABBREVIATESUBSEQ, XABBREVIATESUBSEQ, YABBREVIATESUBSEQ, ZABBREVIATESUBSEQ, QABBREVIATEFIRSTMAXAUTHOR, XABBREVIATEFIRSTMAXAUTHOR, YABBREVIATEFIRSTMAXAUTHOR, ZABBREVIATEFIRSTMAXAUTHOR, QABBREVIATESUBSEQMAXAUTHOR, XABBREVIATESUBSEQMAXAUTHOR, YABBREVIATESUBSEQMAXAUTHOR, ZABBREVIATESUBSEQMAXAUTHOR, QABBREVIATEFIRSTDISPLAYAUTHOR, XABBREVIATEFIRSTDISPLAYAUTHOR, YABBREVIATEFIRSTDISPLAYAUTHOR, ZABBREVIATEFIRSTDISPLAYAUTHOR, QABBREVIATESUBSEQDISPLAYAUTHOR, XABBREVIATESUBSEQDISPLAYAUTHOR, YABBREVIATESUBSEQDISPLAYAUTHOR, ZABBREVIATESUBSEQDISPLAYAUTHOR, QAEMPTY, XAEMPTY, YAEMPTY, ZAEMPTY, QASAME, XASAME, YASAME, ZASAME, QPRECEEDING, XPRECEEDING, YPRECEEDING, ZPRECEEDING, QFOLLOWING, XFOLLOWING, YFOLLOWING, ZFOLLOWING, QAUTHORSEPSTWOSEPS, XAUTHORSEPSTWOSEPS, YAUTHORSEPSTWOSEPS, ZAUTHORSEPSTWOSEPS, QAUTHORSEPSTHREESEPSTHREESEPSEACH, XAUTHORSEPSTHREESEPSTHREESEPSEACH, YAUTHORSEPSTHREESEPSTHREESEPSEACH, ZAUTHORSEPSTHREESEPSTHREESEPSEACH, QAUTHORSEPSTHREESEPSTHREESEPSLAST, XAUTHORSEPSTHREESEPSTHREESEPSLAST, YAUTHORSEPSTHREESEPSTHREESEPSLAST, ZAUTHORSEPSTHREESEPSTHREESEPSLAST, QAUTHORNAMESNAMEFIRSTNAMEORDER, XAUTHORNAMESNAMEFIRSTNAMEORDER, YAUTHORNAMESNAMEFIRSTNAMEORDER, ZAUTHORNAMESNAMEFIRSTNAMEORDER, QAUTHORNAMESNAMEFIRSTINITIALSTYLE, XAUTHORNAMESNAMEFIRSTINITIALSTYLE, YAUTHORNAMESNAMEFIRSTINITIALSTYLE, ZAUTHORNAMESNAMEFIRSTINITIALSTYLE, QAUTHORNAMESNAMEFIRSTUPPERCASE, XAUTHORNAMESNAMEFIRSTUPPERCASE, YAUTHORNAMESNAMEFIRSTUPPERCASE, ZAUTHORNAMESNAMEFIRSTUPPERCASE, QAUTHORNAMESNAMEOTHERNAMEORDER, XAUTHORNAMESNAMEOTHERNAMEORDER, YAUTHORNAMESNAMEOTHERNAMEORDER, ZAUTHORNAMESNAMEOTHERNAMEORDER, QAUTHORNAMESNAMEOTHERINITIALSTYLE, XAUTHORNAMESNAMEOTHERINITIALSTYLE, YAUTHORNAMESNAMEOTHERINITIALSTYLE, ZAUTHORNAMESNAMEOTHERINITIALSTYLE, QAUTHORNAMESNAMEOTHERUPPERCASE, XAUTHORNAMESNAMEOTHERUPPERCASE, YAUTHORNAMESNAMEOTHERUPPERCASE, ZAUTHORNAMESNAMEOTHERUPPERCASE, QTEXTTEXTSINGLEPRECEEDING, XTEXTTEXTSINGLEPRECEEDING, YTEXTTEXTSINGLEPRECEEDING, ZTEXTTEXTSINGLEPRECEEDING, QTEXTTEXTSINGLEFOLLOWING, XTEXTTEXTSINGLEFOLLOWING, YTEXTTEXTSINGLEFOLLOWING, ZTEXTTEXTSINGLEFOLLOWING, QTEXTTEXTMULTIPLEPRECEEDING, XTEXTTEXTMULTIPLEPRECEEDING, YTEXTTEXTMULTIPLEPRECEEDING, ZTEXTTEXTMULTIPLEPRECEEDING, QTEXTTEXTMULTIPLEFOLLOWING, XTEXTTEXTMULTIPLEFOLLOWING, YTEXTTEXTMULTIPLEFOLLOWING, ZTEXTTEXTMULTIPLEFOLLOWING, QTEXTEDTEXTSINGLEPRECEEDING, XTEXTEDTEXTSINGLEPRECEEDING, YTEXTEDTEXTSINGLEPRECEEDING, ZTEXTEDTEXTSINGLEPRECEEDING, QTEXTEDTEXTSINGLEFOLLOWING, XTEXTEDTEXTSINGLEFOLLOWING, YTEXTEDTEXTSINGLEFOLLOWING, ZTEXTEDTEXTSINGLEFOLLOWING, QTEXTEDTEXTMULTIPLEPRECEEDING, XTEXTEDTEXTMULTIPLEPRECEEDING, YTEXTEDTEXTMULTIPLEPRECEEDING, ZTEXTEDTEXTMULTIPLEPRECEEDING, QTEXTEDTEXTMULTIPLEFOLLOWING, XTEXTEDTEXTMULTIPLEFOLLOWING, YTEXTEDTEXTMULTIPLEFOLLOWING, ZTEXTEDTEXTMULTIPLEFOLLOWING, PUBDATEPRECEEDING, PUBDATEFOLLOWING, PUBDATEFORMAT, PUBDATESEQUENCE, PUBDATEMONTHFORMAT, PUBDATEDAYFORMAT, PUBDATEYEARFORMAT, PUBDATEPADLEADINGZERO, PUBDATESTYLE, PUBDATESECPRECEEDING, PUBDATESECFOLLOWING, PUBDATESECFORMAT, PUBDATESECSEQUENCE, PUBDATESECMONTHFORMAT, PUBDATESECDAYFORMAT, PUBDATESECYEARFORMAT, PUBDATESECPADLEADINGZERO, PUBDATESECSTYLE, PUBDATEALLPRECEEDING, PUBDATEALLFOLLOWING, PUBDATEALLFORMAT, PUBDATEALLSEQUENCE, PUBDATEALLMONTHFORMAT, PUBDATEALLDAYFORMAT, PUBDATEALLYEARFORMAT, PUBDATEALLPADLEADINGZERO, PUBDATEALLSTYLE, TITLEPRECEEDING, TITLEFOLLOWING, TITLECASE, TITLESTYLE, BOOKTITLEPRECEEDING, BOOKTITLEFOLLOWING, BOOKTITLECASE, BOOKTITLESTYLE, SERIESTITLEPRECEEDING, SERIESTITLEFOLLOWING, SERIESTITLECASE, SERIESTITLESTYLE, ALLTITLEPRECEEDING, ALLTITLEFOLLOWING, ALLTITLECASE, ALLTITLESTYLE, JOURNALNAMEPRECEEDING, JOURNALNAMEFOLLOWING, JOURNALNAMECASE, JOURNALNAMEDEFAULTTEXT, JOURNALNAMEALTERNATETEXT, JOURNALNAMEPUNCTUATION, JOURNALNAMESTYLE, VOLUMEPRECEEDING, VOLUMEFOLLOWING, VOLUMESTYLE, ISSUEPRECEEDING, ISSUEFOLLOWING, ISSUESTYLE, PAGESSTYLE, PAGESSINGLEPAGEPRECEEDING, PAGESSINGLEPAGEFOLLOWING, PAGESPAGERANGEPRECEEDING, PAGESPAGERANGEFOLLOWING, PAGESPAGERANGETYPE, PUBLISHERPRECEEDING, PUBLISHERFOLLOWING, PUBLISHERSTYLE, PUBPLACEPRECEEDING, PUBPLACEFOLLOWING, PUBPLACESTYLE, PAGESPRECEEDING, PAGESFOLLOWING, REFNUMBERPRECEEDING, REFNUMBERFOLLOWING, REFNUMBERSTYLE, PUBDATEFIRSTSEP, PUBDATESECONDSEP, PUBDATESECFIRSTSEP, PUBDATESECSECONDSEP, PUBDATEALLFIRSTSEP, PUBDATEALLSECONDSEP, PAGESPAGERANGERANGESEPARATOR, SERIALPRECEEDING, SERIALFOLLOWING, SERIALSTYLE, ADDRESSPRECEEDING, ADDRESSFOLLOWING, ADDRESSSTYLE, USERDEF1PRECEEDING, USERDEF1FOLLOWING, USERDEF1STYLE, USERDEF2PRECEEDING, USERDEF2FOLLOWING, USERDEF2STYLE, USERDEF3PRECEEDING, USERDEF3FOLLOWING, USERDEF3STYLE, USERDEF4PRECEEDING, USERDEF4FOLLOWING, USERDEF4STYLE, USERDEF5PRECEEDING, USERDEF5FOLLOWING, USERDEF5STYLE, NOTESPRECEEDING, NOTESFOLLOWING, NOTESSTYLE, ABSTRACTPRECEEDING, ABSTRACTFOLLOWING, ABSTRACTSTYLE, TYPEOFWORKPRECEEDING, TYPEOFWORKFOLLOWING, TYPEOFWORKSTYLE, AREAPRECEEDING, AREAFOLLOWING, AREASTYLE, OSTYPEPRECEEDING, OSTYPEFOLLOWING, OSTYPESTYLE, DEGREEPRECEEDING, DEGREEFOLLOWING, DEGREESTYLE, RUNNINGTIMEPRECEEDING, RUNNINGTIMEFOLLOWING, RUNNINGTIMESTYLE, CLASSCODEINTLPRECEEDING, CLASSCODEINTLFOLLOWING, CLASSCODEINTLSTYLE, CLASSCODEUSPRECEEDING, CLASSCODEUSFOLLOWING, CLASSCODEUSSTYLE, SENDEREMAILPRECEEDING, SENDEREMAILFOLLOWING, SENDEREMAILSTYLE, RECIPIENTEMAILPRECEEDING, RECIPIENTEMAILFOLLOWING, RECIPIENTEMAILSTYLE, MEDIATYPEPRECEEDING, MEDIATYPEFOLLOWING, MEDIATYPESTYLE, NUMVOLUMESPRECEEDING, NUMVOLUMESFOLLOWING, NUMVOLUMESSTYLE, EDITIONPRECEEDING, EDITIONFOLLOWING, EDITIONSTYLE, COMPUTERPRECEEDING, COMPUTERFOLLOWING, COMPUTERSTYLE, CONFERENCELOCATIONPRECEEDING, CONFERENCELOCATIONFOLLOWING, CONFERENCELOCATIONSTYLE, REGISTRYNUMPRECEEDING, REGISTRYNUMFOLLOWING, REGISTRYNUMSTYLE, CLASSIFICATIONPRECEEDING, CLASSIFICATIONFOLLOWING, CLASSIFICATIONSTYLE, SECTIONPRECEEDING, SECTIONFOLLOWING, SECTIONSTYLE, PAMPHLETNUMPRECEEDING, PAMPHLETNUMFOLLOWING, PAMPHLETNUMSTYLE, CHAPTERNUMPRECEEDING, CHAPTERNUMFOLLOWING, CHAPTERNUMSTYLE, LINK0PRECEEDING, LINK0FOLLOWING, LINK0STYLE, LINK1PRECEEDING, LINK1FOLLOWING, LINK1STYLE, LINK2PRECEEDING, LINK2FOLLOWING, LINK2STYLE, LINK3PRECEEDING, LINK3FOLLOWING, LINK3STYLE, LINK4PRECEEDING, LINK4FOLLOWING, LINK4STYLE, CITEKEYPRECEEDING, CITEKEYFOLLOWING, CITEKEYSTYLE from REFSTYLE where PUBTYPE='GEN' and CITSTYLEID=%u", citstyle_id);
4153     }
4154 
4155     LOG_PRINT(LOG_DEBUG, sql_command);
4156     dbi_style_res = dbi_conn_query(conn, sql_command);
4157     if (!dbi_style_res) {
4158       LOG_PRINT(LOG_WARNING, "CITSTYLE select failed");
4159       free(sql_command);
4160       return NULL;
4161     }
4162 
4163     if (dbi_result_next_row(dbi_style_res) == 0) {
4164       LOG_PRINT(LOG_WARNING, "no CITSTYLE found");
4165       dbi_result_free(dbi_style_res);
4166       dbi_style_res = NULL;
4167       free(sql_command);
4168       return NULL;
4169     }
4170   }
4171 
4172   return dbi_style_res;
4173 }
4174 
4175 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4176   unload_style(): frees the memory used by load_style(). If no memory
4177                   was allocated previously this function will do
4178 		  nothing instead of crash
4179 
4180   void unload_style has no return value
4181 
4182   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
unload_style(void)4183 void unload_style(void) {
4184   if (dbi_style_res != NULL) {
4185     dbi_result_free(dbi_style_res);
4186     dbi_style_res = NULL;
4187   }
4188 }
4189 
4190 
4191 
4192 
4193 
4194 
4195 
4196 
4197 
4198 
4199 
4200 
4201