78c9971997-02-20Henrik Grubbström (Grubba) /*
3353441998-07-21Per Hedbor  * $Id: sqltag.pike,v 1.25 1998/07/21 15:28:09 per Exp $
78c9971997-02-20Henrik Grubbström (Grubba)  * * A module for Roxen Challenger, which gives the tags * <SQLQUERY> and <SQLOUTPUT>. * * Henrik Grubbström 1997-01-12 */
3353441998-07-21Per Hedbor constant cvs_version="$Id: sqltag.pike,v 1.25 1998/07/21 15:28:09 per Exp $";
07bf511997-08-31Peter Bortas constant thread_safe=1;
78c9971997-02-20Henrik Grubbström (Grubba) #include <module.h>
f5effc1997-10-15Henrik Grubbström (Grubba) /* Compatibility with old versions of the sqltag module. */ // #define SQL_TAG_COMPAT
78c9971997-02-20Henrik Grubbström (Grubba) inherit "module"; inherit "roxenlib";
0e05a31997-05-20Henrik Grubbström (Grubba) import Array; import Sql;
78c9971997-02-20Henrik Grubbström (Grubba) /* * Module interface functions */ array register_module() {
2a9ddf1998-07-15Johan Schön  return( ({ MODULE_PARSER|MODULE_PROVIDER,
f5effc1997-10-15Henrik Grubbström (Grubba)  "SQL-module", "This module gives the three tags &lt;SQLQUERY&gt;, " "&lt;SQLOUTPUT&gt;, and &lt;SQLTABLE&gt;.<br>\n" "Usage:<ul>\n" "<table border=0>\n" "<tr><td valign=top><b>&lt;sqloutput&gt;</b></td>" "<td>Executes an SQL-query, and " "replaces #-quoted fieldnames with the results. # is " "quoted as ##. The content inbetween &lt;sqloutput&gt; and " "&lt;/sqloutput&gt; is repeated once for every row in the " "result.</td></tr>\n" "<tr><td valign=top><b>&lt;sqlquery&gt;</b></td>\n" "<td>Executes an SQL-query, but " "doesn't do anything with the result. This is useful if " "you do queries like INSERT and CREATE.</td></tr>\n" "<tr><td valign=top><b>&lt;sqltable&gt;</td>" "<td>Executes an SQL-query, and makes " "an HTML-table from the result.</td></tr>\n" "</table></ul>\n" "The following attributes are used by the above tags:<ul>\n" "<table border=0>\n" "<tr><td valign=top><b>query</b></td>" "<td>The actual SQL-query. (<b>REQUIERED</b>)</td></tr>\n" "<tr><td valign=top><b>host<b></td>" "<td>The hostname of the machine the SQL-server runs on.<br>\n" "This argument can also be used to specify which SQL-server " "to use by specifying an \"SQL-URL\":<br><ul>\n" "<pre>[<i>sqlserver</i>://][[<i>user</i>][:<i>password</i>]@]" "[<i>host</i>[:<i>port</i>]]/<i>database</i></pre><br>\n" "</ul>Valid values for \"sqlserver\" depend on which " "sql-servers your pike has support for, but the following " "might exist: msql, mysql, odbc, oracle, postgres.</td></tr>\n" "<tr><td valign=top><b>database</b></td>" "<td>The name of the database to use.</td></tr>\n" "<tr><td valign=top><b>user</b></td>" "<td>The name of the user to access the database with.</td></tr>\n" "<tr><td valign=top><b>password</b></td>" "<td>The password to access the database.</td></tr>\n"
961fd31997-11-29Henrik Grubbström (Grubba)  "<tr><td valign=top><b>parse</b></td>" "<td>If specified, the query will be parsed by the "
2ca4ca1998-02-10Henrik Grubbström (Grubba)  "RXML-parser</td></tr>\n" "<tr><td valign=top><b>quiet</b></td>" "<td>If specified, SQL-errors will be kept quiet.</td></tr>\n"
f5effc1997-10-15Henrik Grubbström (Grubba)  "</table></ul><p>\n" "The &lt;sqltable&gt; tag has an additional attribute " "<b>ascii</b>, which generates a tab-separated table (usefull "
655b721997-10-15Henrik Grubbström (Grubba)  "with eg the &lt;diagram&gt; tag).<p>\n"
f5effc1997-10-15Henrik Grubbström (Grubba)  "\n" "<b>NOTE</b>: Specifying passwords in the documents may prove " "to be a security hole if the module is not loaded for some "
961fd31997-11-29Henrik Grubbström (Grubba)  "reason.<br>\n" "<b>SEE ALSO</b>: The &lt;FORMOUTPUT&gt; tag can be " "usefull to generate the queries.<br>\n",
f5effc1997-10-15Henrik Grubbström (Grubba)  0, 1 }) );
78c9971997-02-20Henrik Grubbström (Grubba) } /* * Tag handlers */ string sqloutput_tag(string tag_name, mapping args, string contents,
961fd31997-11-29Henrik Grubbström (Grubba)  object request_id, object f, mapping defines, object fd)
78c9971997-02-20Henrik Grubbström (Grubba) {
8756ae1998-03-08Per Hedbor  if(args->help) return register_module()[2]; // FIXME
78c9971997-02-20Henrik Grubbström (Grubba)  if (args->query) {
961fd31997-11-29Henrik Grubbström (Grubba)  if (args->parse) {
8ec5741997-12-04Henrik Grubbström (Grubba)  args->query = parse_rxml(args->query, request_id, f, defines);
961fd31997-11-29Henrik Grubbström (Grubba)  }
78c9971997-02-20Henrik Grubbström (Grubba)  string host = query("hostname");
f5effc1997-10-15Henrik Grubbström (Grubba) #ifdef SQL_TAG_COMPAT
78c9971997-02-20Henrik Grubbström (Grubba)  string database = query("database"); string user = query("user"); string password = query("password");
f5effc1997-10-15Henrik Grubbström (Grubba) #else /* SQL_TAG_COMPAT */ string database, user, password; #endif /* SQL_TAG_COMPAT */
0e05a31997-05-20Henrik Grubbström (Grubba)  object(sql) con;
78c9971997-02-20Henrik Grubbström (Grubba)  array(mapping(string:mixed)) result;
12ac991997-11-26Henrik Grubbström (Grubba)  function sql_connect = request_id->conf->sql_connect;
78c9971997-02-20Henrik Grubbström (Grubba)  mixed error; if (args->host) { host = args->host; user = ""; password = ""; } if (args->database) { database = args->database; user = ""; password = "";
12ac991997-11-26Henrik Grubbström (Grubba)  sql_connect = 0;
78c9971997-02-20Henrik Grubbström (Grubba)  } if (args->user) { user = args->user;
12ac991997-11-26Henrik Grubbström (Grubba)  sql_connect = 0;
78c9971997-02-20Henrik Grubbström (Grubba)  } if (args->password) { password = args->password;
12ac991997-11-26Henrik Grubbström (Grubba)  sql_connect = 0;
78c9971997-02-20Henrik Grubbström (Grubba)  }
12ac991997-11-26Henrik Grubbström (Grubba)  if (sql_connect) { error = catch(con = sql_connect(host)); } else { host = (lower_case(host) == "localhost")?"":host; error = catch(con = sql(host, database, user, password)); } if (error) {
2ca4ca1998-02-10Henrik Grubbström (Grubba)  if (!args->quiet) {
3353441998-07-21Per Hedbor  contents = ("<h3>Couldn't connect to SQL-server</h1><br>\n" + html_encode_string(error[0]) + "<false>");
2ca4ca1998-02-10Henrik Grubbström (Grubba)  } else { contents = "<false>"; }
0e05a31997-05-20Henrik Grubbström (Grubba)  } else if (error = catch(result = con->query(args->query))) {
2ca4ca1998-02-10Henrik Grubbström (Grubba)  if (!args->quiet) {
3353441998-07-21Per Hedbor  contents = ("<h3>Query \"" + html_encode_string(args->query) + "\" failed: " + html_encode_string(con->error()) + "</h1>\n<false>");
2ca4ca1998-02-10Henrik Grubbström (Grubba)  } else { contents = "<false>"; }
b2b1fb1998-02-02Mattias Wingstedt  } else if (result && sizeof(result)) { contents = do_output_tag( args, result, contents, request_id ) + "<true>";
07245f1997-09-28Henrik Grubbström (Grubba)  } else {
26b7da1997-09-30Henrik Grubbström (Grubba)  contents = "<false>";
78c9971997-02-20Henrik Grubbström (Grubba)  } } else {
26b7da1997-09-30Henrik Grubbström (Grubba)  contents = "<!-- No query! --><false>";
78c9971997-02-20Henrik Grubbström (Grubba)  } return(contents); } string sqlquery_tag(string tag_name, mapping args,
961fd31997-11-29Henrik Grubbström (Grubba)  object request_id, object f, mapping defines, object fd)
78c9971997-02-20Henrik Grubbström (Grubba) {
8756ae1998-03-08Per Hedbor  if(args->help) return register_module()[2]; // FIXME
78c9971997-02-20Henrik Grubbström (Grubba)  if (args->query) {
961fd31997-11-29Henrik Grubbström (Grubba)  if (args->parse) {
3aa2c81997-12-04Henrik Grubbström (Grubba)  args->query = parse_rxml(args->query, request_id, f, defines);
961fd31997-11-29Henrik Grubbström (Grubba)  }
78c9971997-02-20Henrik Grubbström (Grubba)  string host = query("hostname");
f5effc1997-10-15Henrik Grubbström (Grubba) #ifdef SQL_TAG_COMPAT
78c9971997-02-20Henrik Grubbström (Grubba)  string database = query("database"); string user = query("user"); string password = query("password");
f5effc1997-10-15Henrik Grubbström (Grubba) #else /* SQL_TAG_COMPAT */ string database, user, password; #endif /* SQL_TAG_COMPAT */
0e05a31997-05-20Henrik Grubbström (Grubba)  object(sql) con;
78c9971997-02-20Henrik Grubbström (Grubba)  mixed error;
12ac991997-11-26Henrik Grubbström (Grubba)  function sql_connect = request_id->conf->sql_connect;
07245f1997-09-28Henrik Grubbström (Grubba)  array(mapping(string:mixed)) res;
78c9971997-02-20Henrik Grubbström (Grubba)  if (args->host) { host = args->host; user = ""; password = ""; } if (args->database) { database = args->database; user = ""; password = "";
12ac991997-11-26Henrik Grubbström (Grubba)  sql_connect = 0;
78c9971997-02-20Henrik Grubbström (Grubba)  } if (args->user) { user = args->user;
12ac991997-11-26Henrik Grubbström (Grubba)  sql_connect = 0;
78c9971997-02-20Henrik Grubbström (Grubba)  } if (args->password) { password = args->password;
12ac991997-11-26Henrik Grubbström (Grubba)  sql_connect = 0;
78c9971997-02-20Henrik Grubbström (Grubba)  }
12ac991997-11-26Henrik Grubbström (Grubba)  if (sql_connect) { error = catch(con = sql_connect(host)); } else { host = (lower_case(host) == "localhost")?"":host; error = catch(con = sql(host, database, user, password)); } if (error) {
2ca4ca1998-02-10Henrik Grubbström (Grubba)  if (!args->quiet) {
3353441998-07-21Per Hedbor  return("<h3>Couldn't connect to SQL-server</h1><br>\n" + html_encode_string(error[0])+"<false>");
2ca4ca1998-02-10Henrik Grubbström (Grubba)  } else { return("<false>"); }
07245f1997-09-28Henrik Grubbström (Grubba)  } else if (error = catch(res = con->query(args->query))) {
2ca4ca1998-02-10Henrik Grubbström (Grubba)  if (!args->quiet) {
3353441998-07-21Per Hedbor  return("<h3>Query \"" + html_encode_string(args->query)+"\" failed: " + html_encode_string(con->error()) + "</h1>\n<false>");
2ca4ca1998-02-10Henrik Grubbström (Grubba)  } else { return("<false>"); }
78c9971997-02-20Henrik Grubbström (Grubba)  }
26b7da1997-09-30Henrik Grubbström (Grubba)  return(res?"<true>":"<false>");
78c9971997-02-20Henrik Grubbström (Grubba)  } else {
26b7da1997-09-30Henrik Grubbström (Grubba)  return("<!-- No query! --><false>");
78c9971997-02-20Henrik Grubbström (Grubba)  } } string sqltable_tag(string tag_name, mapping args,
961fd31997-11-29Henrik Grubbström (Grubba)  object request_id, object f, mapping defines, object fd)
78c9971997-02-20Henrik Grubbström (Grubba) {
c7f4e51997-10-15Henrik Grubbström (Grubba)  int ascii;
8756ae1998-03-08Per Hedbor  if(args->help) return register_module()[2]; // FIXME
c7f4e51997-10-15Henrik Grubbström (Grubba)  if (args->ascii) { // ASCII-mode ascii = 1; }
78c9971997-02-20Henrik Grubbström (Grubba)  if (args->query) {
961fd31997-11-29Henrik Grubbström (Grubba)  if (args->parse) {
3aa2c81997-12-04Henrik Grubbström (Grubba)  args->query = parse_rxml(args->query, request_id, f, defines);
961fd31997-11-29Henrik Grubbström (Grubba)  }
78c9971997-02-20Henrik Grubbström (Grubba)  string host = query("hostname");
f5effc1997-10-15Henrik Grubbström (Grubba) #ifdef SQL_TAG_COMPAT
78c9971997-02-20Henrik Grubbström (Grubba)  string database = query("database"); string user = query("user"); string password = query("password");
f5effc1997-10-15Henrik Grubbström (Grubba) #else /* SQL_TAG_COMPAT */ string database, user, password; #endif /* SQL_TAG_COMPAT */
0e05a31997-05-20Henrik Grubbström (Grubba)  object(sql) con;
78c9971997-02-20Henrik Grubbström (Grubba)  mixed error;
12ac991997-11-26Henrik Grubbström (Grubba)  function sql_connect = request_id->conf->sql_connect;
0e05a31997-05-20Henrik Grubbström (Grubba)  object(sql_result) result;
78c9971997-02-20Henrik Grubbström (Grubba)  string res; if (args->host) { host = args->host; user = ""; password = ""; } if (args->database) { database = args->database; user = ""; password = "";
12ac991997-11-26Henrik Grubbström (Grubba)  sql_connect = 0;
78c9971997-02-20Henrik Grubbström (Grubba)  } if (args->user) { user = args->user;
12ac991997-11-26Henrik Grubbström (Grubba)  sql_connect = 0;
78c9971997-02-20Henrik Grubbström (Grubba)  } if (args->password) { password = args->password;
12ac991997-11-26Henrik Grubbström (Grubba)  sql_connect = 0; } if (sql_connect) { error = catch(con = sql_connect(host)); } else { host = (lower_case(host) == "localhost")?"":host; error = catch(con = sql(host, database, user, password));
78c9971997-02-20Henrik Grubbström (Grubba)  }
12ac991997-11-26Henrik Grubbström (Grubba)  if (error) {
2ca4ca1998-02-10Henrik Grubbström (Grubba)  if (!args->quiet) {
3353441998-07-21Per Hedbor  return("<h3>Couldn't connect to SQL-server</h1><br>\n" + html_encode_string(error[0])+"<false>");
2ca4ca1998-02-10Henrik Grubbström (Grubba)  } else { return("<false>"); }
0e05a31997-05-20Henrik Grubbström (Grubba)  } else if (error = catch(result = con->big_query(args->query))) {
2ca4ca1998-02-10Henrik Grubbström (Grubba)  if (!args->quiet) {
3353441998-07-21Per Hedbor  return ("<h3>Query \"" + html_encode_string(args->query) + "\" failed: " + html_encode_string(con->error()) + "</h1>\n" + "<false>");
2ca4ca1998-02-10Henrik Grubbström (Grubba)  } else { return("<false>"); }
78c9971997-02-20Henrik Grubbström (Grubba)  }
0e05a31997-05-20Henrik Grubbström (Grubba)  if (result) {
78c9971997-02-20Henrik Grubbström (Grubba)  string nullvalue=""; array(mixed) row; if (args->nullvalue) { nullvalue=(string)args->nullvalue; }
f5effc1997-10-15Henrik Grubbström (Grubba)  if (ascii) { res = ""; } else { res = "<table"; foreach(indices(args) - ({ "host", "database", "user", "password",
78c9971997-02-20Henrik Grubbström (Grubba)  "query", "nullvalue" }),
f5effc1997-10-15Henrik Grubbström (Grubba)  string attr) { string val = args[attr]; if (val != attr) { res += " "+attr+"=\""+val+"\""; } else { res += " "+attr; }
78c9971997-02-20Henrik Grubbström (Grubba)  }
f5effc1997-10-15Henrik Grubbström (Grubba)  res += "><tr>"; foreach(map(result->fetch_fields(), lambda (mapping m) { return(m->name); } ), string name) { res += "<th>"+name+"</th>"; } res += "</tr>\n";
78c9971997-02-20Henrik Grubbström (Grubba)  }
07245f1997-09-28Henrik Grubbström (Grubba) 
0e05a31997-05-20Henrik Grubbström (Grubba)  while (row = result->fetch_row()) {
f5effc1997-10-15Henrik Grubbström (Grubba)  if (ascii) { res += (Array.map(row, lambda(mixed value) { return((string)value); }) * "\t") + "\n"; } else { res += "<tr>"; foreach(row, mixed value) { value = (string)value; res += "<td>"+(value==""?nullvalue:value)+"</td>"; } res += "</tr>\n";
78c9971997-02-20Henrik Grubbström (Grubba)  } }
a60c301997-10-15Henrik Grubbström (Grubba)  if (ascii) { res += "<true>"; } else {
f5effc1997-10-15Henrik Grubbström (Grubba)  res += "</table><true>"; }
78c9971997-02-20Henrik Grubbström (Grubba)  return(res); } else {
f5effc1997-10-15Henrik Grubbström (Grubba)  if (ascii) {
a60c301997-10-15Henrik Grubbström (Grubba)  return("<false>");
f5effc1997-10-15Henrik Grubbström (Grubba)  }
26b7da1997-09-30Henrik Grubbström (Grubba)  return("<!-- No result from query --><false>");
78c9971997-02-20Henrik Grubbström (Grubba)  } } else {
f5effc1997-10-15Henrik Grubbström (Grubba)  if (ascii) {
a60c301997-10-15Henrik Grubbström (Grubba)  return("<false>");
f5effc1997-10-15Henrik Grubbström (Grubba)  }
26b7da1997-09-30Henrik Grubbström (Grubba)  return("<!-- No query! --><false>");
78c9971997-02-20Henrik Grubbström (Grubba)  } }
07245f1997-09-28Henrik Grubbström (Grubba) string sqlelse_tag(string tag_name, mapping args, string contents, object request_id, mapping defines) {
26b7da1997-09-30Henrik Grubbström (Grubba)  return(make_container("else", args, contents));
07245f1997-09-28Henrik Grubbström (Grubba) }
0d90ed1998-01-17Henrik Grubbström (Grubba) #if 0
78c9971997-02-20Henrik Grubbström (Grubba) string dumpid_tag(string tag_name, mapping args, object request_id, mapping defines) { return(sprintf("<pre>ID:%O\n</pre>\n", mkmapping(indices(request_id), values(request_id)))); }
0d90ed1998-01-17Henrik Grubbström (Grubba) #endif /* 0 */
2a9ddf1998-07-15Johan Schön 
78c9971997-02-20Henrik Grubbström (Grubba) /* * Hook in the tags */ mapping query_tag_callers() { return( ([ "sql":sqlquery_tag, "sqlquery":sqlquery_tag,
0d90ed1998-01-17Henrik Grubbström (Grubba)  "sqltable":sqltable_tag, #if 0 "dumpid":dumpid_tag #endif /* 0 */ ]) );
78c9971997-02-20Henrik Grubbström (Grubba) } mapping query_container_callers() {
07245f1997-09-28Henrik Grubbström (Grubba)  return( ([ "sqloutput":sqloutput_tag, "sqlelse":sqlelse_tag ]) );
78c9971997-02-20Henrik Grubbström (Grubba) } /*
2a9ddf1998-07-15Johan Schön  * Callback functions */ object(sql) sql_object(object request_id) { string host = query("hostname"); object(sql) con; function sql_connect = request_id->conf->sql_connect; mixed error; error = catch(con = sql_connect(host)); if(error) return 0; return con; } string query_provides() { return "sql"; } /*
78c9971997-02-20Henrik Grubbström (Grubba)  * Setting the defaults */ void create() { defvar("hostname", "localhost", "Default SQL-database host",
47d81d1997-09-05Henrik Grubbström (Grubba)  TYPE_STRING, "Specifies the default host to use for SQL-queries.\n" "This argument can also be used to specify which SQL-server to " "use by specifying an \"SQL-URL\":<ul>\n" "<pre>[<i>sqlserver</i>://][[<i>user</i>][:<i>password</i>]@]" "[<i>host</i>[:<i>port</i>]]/<i>database</i></pre></ul><br>\n"
a2533f1997-09-23Henrik Grubbström (Grubba)  "Valid values for \"sqlserver\" depend on which "
47d81d1997-09-05Henrik Grubbström (Grubba)  "sql-servers your pike has support for, but the following " "might exist: msql, mysql, odbc, oracle, postgres.\n");
f5effc1997-10-15Henrik Grubbström (Grubba) #ifdef SQL_TAG_COMPAT
c7f4e51997-10-15Henrik Grubbström (Grubba)  defvar("database", "", "Default SQL-database (deprecated)", TYPE_STRING|VAR_MORE, "Specifies the name of the default SQL-database.\n"); defvar("user", "", "Default username (deprecated)", TYPE_STRING|VAR_MORE, "Specifies the default username to use for access.\n"); defvar("password", "", "Default password (deprecated)", TYPE_STRING|VAR_MORE, "Specifies the default password to use for access.\n");
f5effc1997-10-15Henrik Grubbström (Grubba) #endif /* SQL_TAG_COMPAT */
78c9971997-02-20Henrik Grubbström (Grubba) } /* * More interface functions */
12ac991997-11-26Henrik Grubbström (Grubba) object conf; void start(int level, object _conf)
78c9971997-02-20Henrik Grubbström (Grubba) {
12ac991997-11-26Henrik Grubbström (Grubba)  if (_conf) { conf = _conf; }
2a9ddf1998-07-15Johan Schön //add_api_function("sql_query", api_sql_query, ({ "string", 0,"int" }));
78c9971997-02-20Henrik Grubbström (Grubba) } void stop() { } string status() {
fa40051997-06-20Henrik Grubbström (Grubba)  if (catch {
12ac991997-11-26Henrik Grubbström (Grubba)  object o; if (conf->sql_connect) { o = conf->sql_connect(QUERY(hostname)); } else { o = Sql.sql(QUERY(hostname)
c7f4e51997-10-15Henrik Grubbström (Grubba) #ifdef SQL_TAG_COMPAT
12ac991997-11-26Henrik Grubbström (Grubba)  , QUERY(database), QUERY(user), QUERY(password)
c7f4e51997-10-15Henrik Grubbström (Grubba) #endif /* SQL_TAG_COMPAT */
12ac991997-11-26Henrik Grubbström (Grubba)  ); }
6ef16f1997-06-24Henrik Grubbström (Grubba)  return(sprintf("Connected to %s-server on %s<br>\n",
fa40051997-06-20Henrik Grubbström (Grubba)  o->server_info(), o->host_info())); }) { return("<font color=red>Not connected.</font><br>\n"); }
78c9971997-02-20Henrik Grubbström (Grubba) }