GRASS Programmer's Manual  6.4.3(2013)-r
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Pages
generate.c
Go to the documentation of this file.
1 #include <stdlib.h>
2 #include <string.h>
3 #include <grass/gis.h>
4 #include <grass/dbmi.h>
5 #include <grass/form.h>
6 
7 /* Escape string for use in TCL */
8 char *escape_tcl_string(char *input)
9 {
10  char *escaped;
11 
12  escaped = G_str_replace(input, "\\", "\\\\");
13  escaped = G_str_replace(escaped, "[", "\\[");
14  escaped = G_str_replace(escaped, "]", "\\]");
15  escaped = G_str_replace(escaped, "$", "\\$");
16 
17  return escaped;
18 }
19 
20 /* Generate form in HTML/TXT format.
21  * Pointer to resulting string is stored to 'form'. This string must be freed by application.
22  *
23  * returns: -1 error
24  * 0 success
25  */
26 int
27 F_generate(char *drvname, char *dbname, char *tblname, char *key, int keyval,
28  char *frmname, char *frmmapset,
29  int edit_mode, int format, char **form)
30 {
31  int col, ncols, ctype, sqltype, more;
32  char buf[5000], buf1[100];
33  const char *colname;
34  dbString sql, html, str;
35  dbDriver *driver;
36  dbHandle handle;
37  dbCursor cursor;
38  dbTable *table;
39  dbColumn *column;
40  dbValue *value;
41 
42  int i = 0;
43 
44  /* see /usr/lib/tcl8.4/encoding/ */
45  static char *encoding_list[] = {
46  "utf-8",
47  "ascii",
48  "iso8859-1",
49  "iso8859-2",
50  "iso8859-15",
51  "iso2022-jp",
52  "koi8-r",
53  "euc-jp",
54  NULL
55  };
56  char *enc_env;
57 
58  G__read_env();
59  enc_env = G__getenv("GRASS_DB_ENCODING");
60 
61  /* TODO: support 'format' (txt, html), currently html only */
62 
63  G_debug(2,
64  "F_generate(): drvname = '%s', dbname = '%s'\n tblname = '%s', key = '%s', keyval = %d\n"
65  " form = '%s', form_mapset = '%s'\n edit_mode = %d",
66  drvname, dbname, tblname, key, keyval, frmname, frmmapset,
67  edit_mode);
68 
69  db_init_string(&sql);
70  db_init_string(&html); /* here is the result stored */
71  db_init_string(&str);
72 
73  G_debug(2, "Open driver");
74  driver = db_start_driver(drvname);
75  if (driver == NULL) {
76  G_warning("Cannot open driver");
77  sprintf(buf, "Cannot open driver '%s'<BR>",
78  escape_tcl_string(drvname));
79  *form = G_store(buf);
80  return -1;
81  }
82  G_debug(2, "Driver opened");
83 
84  db_init_handle(&handle);
85  db_set_handle(&handle, dbname, NULL);
86  G_debug(2, "Open database");
87  if (db_open_database(driver, &handle) != DB_OK) {
88  G_warning("Cannot open database");
89  db_shutdown_driver(driver);
90  sprintf(buf, "Cannot open database '%s' by driver '%s'<BR>",
91  escape_tcl_string(dbname), escape_tcl_string(drvname));
92  *form = G_store(buf);
93  return -1;
94  }
95  G_debug(2, "Database opened");
96 
97  /* TODO: test if table exist first, but this should be tested by application befor
98  * F_generate() is called, because it may be correct (connection defined in DB
99  * but table does not exist) */
100 
101  sprintf(buf, "select * from %s where %s = %d", tblname, key, keyval);
102  G_debug(2, "%s", buf);
103  db_set_string(&sql, buf);
104  if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) != DB_OK) {
105  G_warning("Cannot open select cursor");
106  db_close_database(driver);
107  db_shutdown_driver(driver);
108  sprintf(buf,
109  "Cannot open select cursor:<BR>'%s'<BR>on database '%s' by driver '%s'<BR>",
111  escape_tcl_string(dbname), escape_tcl_string(drvname));
112  *form = G_store(buf);
113  return -1;
114  }
115  G_debug(2, "Select Cursor opened");
116 
117  table = db_get_cursor_table(&cursor);
118 
119  if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK) {
120  G_warning("Cannot fetch next record");
121  db_close_cursor(&cursor);
122  db_close_database(driver);
123  db_shutdown_driver(driver);
124  *form = G_store("Cannot fetch next record");
125  return -1;
126  }
127 
128  if (!more) {
129  G_warning("No database record");
130  if (format == F_HTML) {
131  *form = G_store("No record selected.<BR>");
132  }
133  else {
134  *form = G_store("No record selected.");
135  }
136  }
137  else {
138  ncols = db_get_table_number_of_columns(table);
139 
140  /* Start form */
141  if (format == F_HTML) {
142  if (edit_mode == F_EDIT) {
143  db_append_string(&html, "<FORM>");
144 
145  sprintf(buf, "<INPUT type=hidden name=%s value=\"%s\">",
146  escape_tcl_string(F_DRIVER_FNAME),
147  escape_tcl_string(drvname));
148  db_append_string(&html, buf);
149  /* Note: because html_library.tcl failes to parse
150  * <INPUT name=abc value='dbname=xxx'> and returnes
151  * name="xxx" value="dbname=xxx" order of value and name parameters is changed */
152  sprintf(buf, "<INPUT type=hidden value=\"%s\" name=%s>",
153  escape_tcl_string(dbname),
154  escape_tcl_string(F_DATABASE_FNAME));
155  db_append_string(&html, buf);
156  sprintf(buf, "<INPUT type=hidden name=%s value=\"%s\">",
157  escape_tcl_string(F_TABLE_FNAME),
158  escape_tcl_string(tblname));
159  db_append_string(&html, buf);
160  sprintf(buf, "<INPUT type=hidden name=%s value=\"%s\">",
161  escape_tcl_string(F_KEY_FNAME),
162  escape_tcl_string(key));
163  db_append_string(&html, buf);
164 
165  }
166 
167  for (col = 0; col < ncols; col++) {
168  column = db_get_table_column(table, col);
169  sqltype = db_get_column_sqltype(column);
170  ctype = db_sqltype_to_Ctype(sqltype);
171  value = db_get_column_value(column);
172  db_convert_value_to_string(value, sqltype, &str);
173  colname = db_get_column_name(column);
174 
175  G_debug(2, "%s: %s", colname, db_get_string(&str));
176 
177  if (edit_mode == F_VIEW) {
178  sprintf(buf, "<B>%s : </B> %s <BR>",
179  escape_tcl_string(G_strdup(colname)),
181  db_append_string(&html, buf);
182  }
183  else {
184  sprintf(buf, "<B>%s : </B>",
185  escape_tcl_string(G_strdup(colname)));
186  db_append_string(&html, buf);
187 
188  if (G_strcasecmp(colname, key) == 0) {
189  sprintf(buf,
190  "%s<BR> <INPUT type=hidden name=%s value=\"%s\">",
192  escape_tcl_string(G_strdup(colname)),
194  }
195  else {
196  switch (ctype) {
197  case DB_C_TYPE_INT:
198  sprintf(buf1, "20");
199  break;
200  case DB_C_TYPE_DOUBLE:
201  sprintf(buf1, "30");
202  break;
203  case DB_C_TYPE_STRING:
204  sprintf(buf1, "%d", db_get_column_length(column));
205  break;
206  case DB_C_TYPE_DATETIME:
207  sprintf(buf1, "20");
208  break;
209  }
210  sprintf(buf,
211  "<INPUT type=text size=%s name=%s value=\"%s\"><BR>",
212  escape_tcl_string(buf1),
213  escape_tcl_string(G_strdup(colname)),
215  }
216  db_append_string(&html, buf);
217  }
218  }
219 
220  if (edit_mode == F_EDIT) {
221  sprintf(buf,
222  "<HR> Assume data encoding as:<BR><BR><SELECT NAME=%s SIZE=4><HR><BR>",
223  F_ENCODING);
224  db_append_string(&html, buf);
225 
226  i = 0;
227  while (encoding_list[i] != NULL) {
228 
229  if (G_strcasecmp(encoding_list[i], enc_env) == 0)
230  sprintf(buf, "<OPTION VALUE=\"%s\" SELECTED>%s",
231  encoding_list[i], encoding_list[i]);
232  else
233  sprintf(buf, "<OPTION VALUE=\"%s\">%s",
234  encoding_list[i], encoding_list[i]);
235  ++i;
236  db_append_string(&html, buf);
237  }
238 
239  sprintf(buf, "</SELECT>");
240  db_append_string(&html, buf);
241  }
242 
243  /* Close form */
244  if (edit_mode == F_EDIT) {
245  db_append_string(&html, "</FORM>");
246  }
247  }
248  else { /* F_TXT */
249  for (col = 0; col < ncols; col++) {
250  column = db_get_table_column(table, col);
251  sqltype = db_get_column_sqltype(column);
252  ctype = db_sqltype_to_Ctype(sqltype);
253  value = db_get_column_value(column);
254  db_convert_value_to_string(value, sqltype, &str);
255  colname = db_get_column_name(column);
256 
257  G_debug(2, "%s: %s", colname, db_get_string(&str));
258 
259  sprintf(buf, "%s : %s\n", colname, db_get_string(&str));
260  db_append_string(&html, buf);
261  }
262  }
263  }
264  G_debug(2, "FORM STRING:\n%s\n", db_get_string(&html));
265 
266  db_close_cursor(&cursor);
267  db_close_database(driver);
268  db_shutdown_driver(driver);
269 
270  *form = G_store(db_get_string(&html));
271 
272  db_free_string(&sql);
273  db_free_string(&html);
274  db_free_string(&str);
275 
276  return 0;
277 }