2f903e2001-03-04Per Hedbor #include <config_interface.h> #include <config.h> #include <roxen.h> //<locale-token project="roxen_config">_</locale-token>
2b73ed2017-05-29Pontus Östlund #define _(X,Y) _STR_LOCALE("roxen_config",X,Y)
2f903e2001-03-04Per Hedbor 
9570352001-08-09Per Hedbor mapping actions = ([
adcd212001-08-13Per Hedbor  // name title function must be internal
a74f072017-12-21Karl Gustav Sterneberg  "configure_ext_db_con": ({ _(1145,"Configure database connection"),
e2d8df2017-12-21Karl Gustav Sterneberg  configure_ext_db_con, 0 }),
9fa11d2001-08-24Martin Nilsson  "delete": ({ _(402,"Delete this database"), delete_db, 0 }),
1128652001-09-03Martin Nilsson  "group": ({ _(324,"Change group for this database"), change_group, 0 }),
9fa11d2001-08-24Martin Nilsson  "clear": ({ _(403,"Delete all tables"), clear_db, 0 }), "backup": ({ _(404,"Make a backup"), backup_db, 1 }),
fe07f52008-01-10Jonas Wallden  "charset":({ _(536, "Change default character set"), change_charset, 0 }), "repair": ({ _(537, "Repair all tables"), repair_db, 0 }), "optimize":({ _(538, "Optimize all tables"), optimize_db, 0 }),
0c7a1e2016-09-27Anders Johansson  "schedule":({ _(1109, "Change backup schedule"), change_schedule, 2 }),
9570352001-08-09Per Hedbor ]);
2f4c982001-09-03Per Hedbor 
a3b9102002-08-16Anders Johansson #define CU_AUTH id->misc->config_user->auth
c403b32015-04-02Jonas Walldén // Size limit for single field and aggregated fields (per column)
2b73ed2017-05-29Pontus Östlund #define MAX_FIELD_FORMATTED_SIZE (32 * 1024) // 32 K #define MAX_TOTAL_FORMATTED_SIZE (1024 * 1024) // 1 MB
c403b32015-04-02Jonas Walldén 
2b73ed2017-05-29Pontus Östlund #define VERIFY(X) do { \ if( !id->variables["yes.x"] ) \ { \ return \ ("<table><tr><td colspan='2'>\n"+ \ sprintf((string)(X), db)+ \
adcd212001-08-13Per Hedbor  "</td><tr><td><input type=hidden name=action value='&form.action;' />"\
ede9a22017-06-14Pontus Östlund  "<submit-gbutton2 name='yes' " \ " type='ok'>"+_(0,"Yes")+ \
2b73ed2017-05-29Pontus Östlund  "</submit-gbutton2></td>\n" \
e1fff72016-01-15Henrik Grubbström (Grubba)  "<td align=right><cf-no href='"+Roxen.html_encode_string(id->not_query)+\
2b73ed2017-05-29Pontus Östlund  "?db="+Roxen.html_encode_string(id->variables->db)+ \ "&amp;&usr.set-wiz-id;' />"+ \ "</td>\n</table>\n"); \ } \
9570352001-08-09Per Hedbor } while(0)
2f4c982001-09-03Per Hedbor mixed change_group( string db, RequestID id ) { if( !id->variables->group ) {
ede9a22017-06-14Pontus Östlund  string res =""
2f4c982001-09-03Per Hedbor  "<input type=hidden name=action value='&form.action;' />"
ede9a22017-06-14Pontus Östlund  "<cf-title>"+sprintf(_(423,"Changing group for %s"), db )+"</cf-title>" "<p><b>"+_(445,"Old group")+":</b> " + DBManager.get_group(DBManager.db_group(db))->lname+"</p>" "<p><b>"+_(504,"New group")+":</b> <select name='group'>";
2f4c982001-09-03Per Hedbor  foreach( DBManager.list_groups(), string g ) if( g == DBManager.db_group( db ) )
2b73ed2017-05-29Pontus Östlund  res += "<option selected value='"+g+"'>"+DBManager.get_group( g )->lname;
2f4c982001-09-03Per Hedbor  else
2b73ed2017-05-29Pontus Östlund  res += "<option value='"+g+"'>"+DBManager.get_group( g )->lname;
ede9a22017-06-14Pontus Östlund  return res + "</select><submit-gbutton2 name='ok' type='ok'>"+(201,"OK")+ "</submit-gbutton2></p>";
2f4c982001-09-03Per Hedbor  } DBManager.set_db_group( db, id->variables->group ); return 0; }
0d30602007-01-17Henrik Grubbström (Grubba) mixed change_charset( string db, RequestID id ) { if( !id->variables->default_charset ) { string old_charset = DBManager.get_db_default_charset(db);
ede9a22017-06-14Pontus Östlund  string res =""
0d30602007-01-17Henrik Grubbström (Grubba)  "<input type=hidden name=action value='&form.action;' />"
ede9a22017-06-14Pontus Östlund  "<cf-title>"+sprintf(_(539,"Changing default character set for %s"), db )+ "</cf-title>"+ (old_charset?("<p><b>"+_(540, "Old default character set")+":</b> " + old_charset+"</p>"):"")+ "<p><b>"+_(541,"New default character set")+":</b> "
0d30602007-01-17Henrik Grubbström (Grubba)  "<input type='string' name='default_charset' value='" + Roxen.html_encode_string(old_charset||"") +"' />"; return res + "</select><submit-gbutton2 name='ok'>"+(201,"OK")+
ede9a22017-06-14Pontus Östlund  "</submit-gbutton2></p>";
0d30602007-01-17Henrik Grubbström (Grubba)  } DBManager.set_db_default_charset( db, id->variables->default_charset ); return 0; }
c199a02015-10-21Henrik Grubbström (Grubba) mixed change_schedule( string db, RequestID id ) { Sql.Sql sql = connect_to_my_mysql(0, "roxen"); if( !id->variables->backup_schedule ) { string old_schedule, old_schedule_id; array q = sql->query("SELECT schedule_id, schedule FROM dbs, db_schedules "
2b73ed2017-05-29Pontus Östlund  " WHERE db_schedules.id = dbs.schedule_id " " AND dbs.name = %s", db);
c199a02015-10-21Henrik Grubbström (Grubba)  if (sizeof(q)) { old_schedule = q[0]->schedule; old_schedule_id = q[0]->schedule_id; } string res ="<br /><blockquote>" "<input type=hidden name=action value='&form.action;' />"
0c7a1e2016-09-27Anders Johansson  "<h2>"+sprintf(_(1110,"Changing backup schedule for %s"), db )+
c199a02015-10-21Henrik Grubbström (Grubba)  "</h2>"+
0c7a1e2016-09-27Anders Johansson  (old_schedule?("<b>"+_(1111, "Old backup schedule")+":</b> " +
2b73ed2017-05-29Pontus Östlund  Roxen.html_encode_string(old_schedule)+"<br />"):"")+
0c7a1e2016-09-27Anders Johansson  "<b>"+_(1112,"New backup schedule")+":</b> "
c199a02015-10-21Henrik Grubbström (Grubba)  "<default name='backup_schedule' value='" + old_schedule_id + "'>" "<select name='backup_schedule'>"; foreach(sql->query("SELECT schedule, id FROM db_schedules "
2b73ed2017-05-29Pontus Östlund  " ORDER BY schedule"), mapping(string:string) schedule) {
c199a02015-10-21Henrik Grubbström (Grubba)  res += sprintf("<option value='%s'>%s</option>",
2b73ed2017-05-29Pontus Östlund  schedule->id, Roxen.html_encode_string(schedule->schedule));
c199a02015-10-21Henrik Grubbström (Grubba)  } res += sprintf("<option value='0'>%s</option>",
2b73ed2017-05-29Pontus Östlund  Roxen.html_encode_string(_(1113, "None"))) +
c199a02015-10-21Henrik Grubbström (Grubba)  "</select></default>"; return res + "<submit-gbutton2 name='ok'>"+(201,"OK")+ "</submit-gbutton2>"; } if (id->variables->backup_schedule == "0") { sql->query("UPDATE dbs SET schedule_id = NULL "
2b73ed2017-05-29Pontus Östlund  " WHERE name = %s", db);
c199a02015-10-21Henrik Grubbström (Grubba)  } else { sql->query("UPDATE dbs SET schedule_id = %d "
2b73ed2017-05-29Pontus Östlund  " WHERE name = %s", (int)id->variables->backup_schedule, db);
c199a02015-10-21Henrik Grubbström (Grubba)  } return 0; }
e6f6392007-05-26Martin Stjernholm mixed repair_db( string db, RequestID id ) {
ede9a22017-06-14Pontus Östlund  string res = "<p><link-gbutton type='back' href='browser.pike?db=" + db + "&amp;&usr.set-wiz-id;'>Back</link-gbutton></p>" "<table id='tbl' class='nice tbl-details'>"
e6f6392007-05-26Martin Stjernholm  "<thead>" "<tr>" "<th>Target</th>" "<th>Result</th>" "<th>Time</th>" "</tr>" "</thead>" "<tbody>"; mixed m = query("SHOW TABLE STATUS IN " + db); float t3 = 0; if (sizeof(m)) { foreach (m,m) { string result = ""; mixed q; int t = time(); float t1 = time(t); float t2; if ( mixed e = catch { q = query( "REPAIR TABLE `" + db + "`.`" + m->Name + "`" ); } ) {
ede9a22017-06-14Pontus Östlund  result = "<span class='notify error inline'>Error: " + describe_error(e) + "</span>";
e6f6392007-05-26Martin Stjernholm  } else {
2b73ed2017-05-29Pontus Östlund  t2 = (time(t)-t1); t3 += t2;
e6f6392007-05-26Martin Stjernholm 
2b73ed2017-05-29Pontus Östlund  if (q->Msg_text = "OK")
ede9a22017-06-14Pontus Östlund  result = "<span class='notify ok inline'>Ok</span>";
2b73ed2017-05-29Pontus Östlund  else
ede9a22017-06-14Pontus Östlund  result = "<span class='notify error inline'>Failed: " + q->Msg_text + "</span>";
e6f6392007-05-26Martin Stjernholm  } res += "<tr>" +
2b73ed2017-05-29Pontus Östlund  "<td><a href='browser.pike?db=" + db + "&amp;&usr.set-wiz-id;'>" + db + "</a>.<a href='browser.pike?db=" + db + "&amp;table=" + m->Name + "&amp;&usr.set-wiz-id;'>" + m->Name + "</a></td>" +
ede9a22017-06-14Pontus Östlund  "<td>" + result + "</td>" +
2b73ed2017-05-29Pontus Östlund  "<td>" + t2 + " sec</td>" + "</tr>";
e6f6392007-05-26Martin Stjernholm  } }
ede9a22017-06-14Pontus Östlund  res += "</tbody>" "<tfoot><tr><td colspan='2'>Total:</td><td>" + t3 + " sec</td></tr></tfoot>" "</table>";
e6f6392007-05-26Martin Stjernholm  return res; } mixed optimize_db( string db, RequestID id ) { // CSS stylesheet
ede9a22017-06-14Pontus Östlund  string res = "<p><link-gbutton type='back' href='browser.pike?db=" + db + "&amp;&usr.set-wiz-id;'>Back</link-gbutton></p>" "<table id='tbl' class='nice db-list'>"
e6f6392007-05-26Martin Stjernholm  "<thead>" "<tr>" "<th>Target</th>" "<th>Result</th>" "<th>Time</th>" "</tr>" "</thead>" "<tbody>"; mixed m = query("SHOW TABLE STATUS IN " + db); float t3 = 0; if (sizeof(m)) { foreach (m,m) { string result = ""; mixed q; int t = time(); float t1 = time(t); float t2; if ( mixed e = catch { q = query( "OPTIMIZE TABLE `" + db + "`.`" + m->Name + "`" ); } ) {
ede9a22017-06-14Pontus Östlund  result = "<span class='notify error inline'>Error: " + describe_error(e) + "</span>";
e6f6392007-05-26Martin Stjernholm  } else {
2b73ed2017-05-29Pontus Östlund  t2 = (time(t)-t1); t3 += t2;
e6f6392007-05-26Martin Stjernholm 
2b73ed2017-05-29Pontus Östlund  if (q->Msg_text = "OK")
ede9a22017-06-14Pontus Östlund  result = "<span class='notify ok inline'>Ok</span>";
2b73ed2017-05-29Pontus Östlund  else
ede9a22017-06-14Pontus Östlund  result = "<span class='notify error inline'>Failed: " + q->Msg_text + "</span>";
e6f6392007-05-26Martin Stjernholm  } res += "<tr>" +
2b73ed2017-05-29Pontus Östlund  "<td><a href='browser.pike?db=" + db + "&amp;&usr.set-wiz-id;'>" + db + "</a>.<a href='browser.pike?db=" + db + "&amp;table=" + m->Name + "&amp;&usr.set-wiz-id;'>" + m->Name + "</a></td>" +
ede9a22017-06-14Pontus Östlund  "<td>" + result + "</td>" +
2b73ed2017-05-29Pontus Östlund  "<td>" + t2 + " sec</td>" + "</tr>";
e6f6392007-05-26Martin Stjernholm  } }
ede9a22017-06-14Pontus Östlund  res += "</tbody>" "<tfoot>" "<tr><td colspan='2'>Total:</td><td>" + t3 + " sec</td></tr>" "</tfoot></table>";
e6f6392007-05-26Martin Stjernholm  return res;} mixed query( mixed ... args ) {
2b73ed2017-05-29Pontus Östlund  return connect_to_my_mysql( 0, "roxen" )->query( @args );
e6f6392007-05-26Martin Stjernholm }
adcd212001-08-13Per Hedbor mixed backup_db( string db, RequestID id ) { if( id->variables["ok.x"] ) {
f770512010-11-25Henrik Grubbström (Grubba)  if (roxenloader->parse_mysql_location()->mysqldump) { DBManager.dump
2b73ed2017-05-29Pontus Östlund  (db, id->variables->dir == "auto" ? 0 : id->variables->dir);
f770512010-11-25Henrik Grubbström (Grubba)  } else { DBManager.backup
2b73ed2017-05-29Pontus Östlund  (db, id->variables->dir == "auto" ? 0 : id->variables->dir);
f770512010-11-25Henrik Grubbström (Grubba)  }
adcd212001-08-13Per Hedbor  return 0; } return
80cd682003-11-17Anders Johansson  "<b>"+_(405,"Directory")+":</b> <input name='dir' size='60' value='auto' /><br />"
6a32272011-12-21Jonas Wallden  "<i>" + sprintf (_(1061, #"\
9dd99a2010-01-28Martin Stjernholm The directory the backup will be saved in. If you chose auto, Roxen will generate a directory name that includes the database name and today's date in <tt>$VARDIR/backup</tt> (%s)."),
2b73ed2017-05-29Pontus Östlund  combine_path (getcwd(), roxen_path ("$VARDIR/backup"))) +
9dd99a2010-01-28Martin Stjernholm  "</i>"
adcd212001-08-13Per Hedbor  "<table width='100%'><tr><td valign=top>" "<input type=hidden name=action value='&form.action;' />"
34448c2015-04-09Henrik Grubbström (Grubba)  "<cf-cancel href='"+ Roxen.html_encode_string(id->not_query)+
e1fff72016-01-15Henrik Grubbström (Grubba)  "?db="+Roxen.html_encode_string(id->variables->db)+"&amp;&usr.set-wiz-id;'/>"
34448c2015-04-09Henrik Grubbström (Grubba)  "<td valign=top align=right><submit-gbutton2 name='ok'>"+_(201,"OK")+ "</submit-gbutton2></td>\n"
80cd682003-11-17Anders Johansson  "</td>\n</table>\n";
adcd212001-08-13Per Hedbor }
e2d8df2017-12-21Karl Gustav Sterneberg mixed configure_ext_db_con( string db, RequestID id )
9570352001-08-09Per Hedbor {
e2d8df2017-12-21Karl Gustav Sterneberg  if( DBManager.is_internal( db ) ) { error("Configure external database connection not possible for internal " "databases."); }
adcd212001-08-13Per Hedbor  string warning=""; if( id->variables["ok.x"] ) {
e2d8df2017-12-21Karl Gustav Sterneberg  if( !strlen(id->variables->url) ) {
bd4fb02018-01-17Pontus Östlund  warning= "<span class='notify warn inline'>"
e2d8df2017-12-21Karl Gustav Sterneberg  +_(406,"Please specify an URL to define an external database")+
bd4fb02018-01-17Pontus Östlund  "</span>";
e2d8df2017-12-21Karl Gustav Sterneberg  } else if( mixed err = catch( Sql.Sql( id->variables->url ) ) ) {
bd4fb02018-01-17Pontus Östlund  warning = sprintf("<span class='notify warn inline'>"+
e2d8df2017-12-21Karl Gustav Sterneberg  _(407,"It is not possible to connect to %s.")+ "<br /> (%s)"
bd4fb02018-01-17Pontus Östlund  "</span>",
e2d8df2017-12-21Karl Gustav Sterneberg  id->variables->url, describe_error(err));
adcd212001-08-13Per Hedbor  } if( !strlen( warning ) ) switch( id->variables->name ) { case "":
bd4fb02018-01-17Pontus Östlund  warning = "<span class='notify warn inline'>"+
a2548f2018-01-12Karl Gustav Sterneberg  _(1146,"Please specify a name for the database connection.")+
bd4fb02018-01-17Pontus Östlund  "</span>";
adcd212001-08-13Per Hedbor  break; case "mysql": case "roxen":
fe75642017-12-06Pontus Östlund  warning = sprintf("<span class='notify warn inline'>"+
32b1082018-01-02Henrik Grubbström (Grubba)  _(1147,"<tt>%s</tt> is an internal database, used by Roxen. "
a2548f2018-01-12Karl Gustav Sterneberg  "Please select another name.")+
fe75642017-12-06Pontus Östlund  "</span>", id->variables->name );
adcd212001-08-13Per Hedbor  break; default:
407e832001-08-17Per Hedbor  if( Roxen.is_mysql_keyword( id->variables->name ) )
bd4fb02018-01-17Pontus Östlund  warning = sprintf("<span class='notify warn inline'>"+
32b1082018-01-02Henrik Grubbström (Grubba)  _(1148,"<tt>%s</tt> is a MySQL keyword, used by MySQL. "
a2548f2018-01-12Karl Gustav Sterneberg  "Please select another name.")+
bd4fb02018-01-17Pontus Östlund  "</span>", id->variables->name );
c03fb22010-03-24Henrik Grubbström (Grubba)  catch {
2d981b2017-12-21Karl Gustav Sterneberg  // Check name first since DBManager.get_db_url_info() ignores // trailing spaces in db name. if( !(DBManager.valid_db_name( id->variables->name )) ) {
fe75642017-12-06Pontus Östlund  warning = sprintf("<span class='notify warn inline'>"+
bd4fb02018-01-17Pontus Östlund  _(1149,"<span class='prewrap'>"
2d981b2017-12-21Karl Gustav Sterneberg  "'<tt>%s</tt>'</span> "
a2548f2018-01-12Karl Gustav Sterneberg  "is not a valid database name. " "Please select another name.")+
4dcdea2018-05-18Pontus Östlund  "</span>",
2d080e2018-03-27Karl Gustav Sterneberg  Roxen.html_encode_string(id->variables->name));
2d981b2017-12-21Karl Gustav Sterneberg  } else if( db != id->variables->name && DBManager.get_db_url_info( id->variables->name ) ) {
bd4fb02018-01-17Pontus Östlund  warning = sprintf("<span class='notify warn inline'>"+
a2548f2018-01-12Karl Gustav Sterneberg  _(529,"A database with name <tt>%s</tt> " "already exists. Please select another name.")+
bd4fb02018-01-17Pontus Östlund  "</span>", id->variables->name );
2d981b2017-12-21Karl Gustav Sterneberg  }
c03fb22010-03-24Henrik Grubbström (Grubba)  };
407e832001-08-17Per Hedbor  break;
adcd212001-08-13Per Hedbor  } if( !strlen( warning ) ) {
2d981b2017-12-21Karl Gustav Sterneberg  if( db != id->variables->name )
adcd212001-08-13Per Hedbor  {
2d981b2017-12-21Karl Gustav Sterneberg  DBManager.create_db( id->variables->name, id->variables->url, 0, id->variables->group );
e2d8df2017-12-21Karl Gustav Sterneberg  DBManager.copy_db_md( db, id->variables->name ); DBManager.drop_db( db );
adcd212001-08-13Per Hedbor  }
e2d8df2017-12-21Karl Gustav Sterneberg  else if( id->variables->url != DBManager.db_url( db ) )
adcd212001-08-13Per Hedbor  {
e2d8df2017-12-21Karl Gustav Sterneberg  // Only url has changed.
2d981b2017-12-21Karl Gustav Sterneberg  DBManager.set_url( db, id->variables->url, 0 );
adcd212001-08-13Per Hedbor  }
e2d8df2017-12-21Karl Gustav Sterneberg  // else nothing has changed...
adcd212001-08-13Per Hedbor  return Roxen.http_redirect( "/dbs/", id ); } }
2d981b2017-12-21Karl Gustav Sterneberg  if( !id->variables->name )
adcd212001-08-13Per Hedbor  id->variables->name = db;
e0bd902001-10-01Per Hedbor 
adcd212001-08-13Per Hedbor  if( !id->variables->url ) id->variables->url = DBManager.db_url( db ) || ""; return
bd4fb02018-01-17Pontus Östlund  "<cf-title>"+_(414,"Configure external database connection")+"</cf-title>\n"
adcd212001-08-13Per Hedbor  +warning+
ede9a22017-06-14Pontus Östlund  "<table class='auto'>\n"
2b73ed2017-05-29Pontus Östlund 
adcd212001-08-13Per Hedbor  " <tr>\n"
a2548f2018-01-12Karl Gustav Sterneberg  " <td><b>"+_(418,"Name")+":</b></td>\n"
5054982005-04-15Marcus Wellhardh  " <td><input name='name' value='&form.name;'/></td>\n" " </tr>\n"
2b73ed2017-05-29Pontus Östlund 
5054982005-04-15Marcus Wellhardh  " <tr>\n" " <td valign=top colspan='2'>\n"
a2548f2018-01-12Karl Gustav Sterneberg  " <i>"+_(530,"The name for the database. It is recommended to "
2d981b2017-12-21Karl Gustav Sterneberg  "use only lowercase letters <tt>[a-z]</tt>, numbers " "and <tt>-</tt> (dash).")+"</i>\n"
5054982005-04-15Marcus Wellhardh  " </td>\n" " </tr>\n"+
2b73ed2017-05-29Pontus Östlund 
e2d8df2017-12-21Karl Gustav Sterneberg  " <tr>\n" " <td><nbsp><b>URL:</b></nbsp></td>\n" " <td colspan='3'><input name='url' size=50 value='&form.url;'/></td>\n" " </tr>\n"+
adcd212001-08-13Per Hedbor  "</table>\n"+
bd4fb02018-01-17Pontus Östlund  "<table class='auto'><tr><td>"
adcd212001-08-13Per Hedbor  "<input type=hidden name=action value='&form.action;' />"
34448c2015-04-09Henrik Grubbström (Grubba)  "<cf-cancel href='" + Roxen.html_encode_string(id->not_query) +
ce77982016-01-15Henrik Grubbström (Grubba)  "?db=" + Roxen.html_encode_string(id->variables->db) + "&amp;&usr.set-wiz-id;'/></td>\n"
80cd682003-11-17Anders Johansson  "<td align=right>"
ede9a22017-06-14Pontus Östlund  "<submit-gbutton2 name='ok' type='ok'>" + _(201,"OK") + "</submit-gbutton2>"
80cd682003-11-17Anders Johansson  "</td>\n</table>\n";
9570352001-08-09Per Hedbor } mixed delete_db( string db, RequestID id ) {
c6098c2001-09-03Per Hedbor  string msg; if( DBManager.is_internal( db ) )
a77be32001-09-03Henrik Grubbström (Grubba)  msg = (string)_(361, "Are you sure you want to delete the database %s "
2b73ed2017-05-29Pontus Östlund  "and the data?");
c6098c2001-09-03Per Hedbor  else
a77be32001-09-03Henrik Grubbström (Grubba)  msg = (string)_(362,"Are you sure you want to delete the database %s?"
2b73ed2017-05-29Pontus Östlund  " No data will be deleted from the remote database.");
c6098c2001-09-03Per Hedbor  VERIFY(msg);
13c6092001-12-10Anders Johansson  report_notice( _(424,"The database %s was deleted by %s")+"\n",
2b73ed2017-05-29Pontus Östlund  db, id->misc->authenticated_user->name() );
9570352001-08-09Per Hedbor  DBManager.drop_db( db );
adcd212001-08-13Per Hedbor  return Roxen.http_redirect( "/dbs/", id );
9570352001-08-09Per Hedbor } mixed clear_db( string db, RequestID id ) {
9fa11d2001-08-24Martin Nilsson  VERIFY(_(425,"Are you sure you want to delete all tables in %s?"));
e0bd902001-10-01Per Hedbor 
9570352001-08-09Per Hedbor  Sql.Sql sq = DBManager.get( db );
e0bd902001-10-01Per Hedbor 
0a416e2009-04-02Henrik Grubbström (Grubba)  // Note: Drop table may fail due to foreign key references // in some databases. Thus the outer loop and the catch.
017e292009-04-03Henrik Grubbström (Grubba)  int table_cnt;
0a416e2009-04-02Henrik Grubbström (Grubba)  array(string) remaining_tables = DBManager.db_tables( db ); do { foreach( remaining_tables, string r ) { catch { sq->query( "DROP TABLE "+r ); }; } table_cnt = sizeof(remaining_tables); remaining_tables = DBManager.db_tables( db ); } while (sizeof(remaining_tables) &&
2b73ed2017-05-29Pontus Östlund  (table_cnt > sizeof(remaining_tables)));
0a416e2009-04-02Henrik Grubbström (Grubba)  if (sizeof(remaining_tables)) { // We've failed to drop some tables, try forcing an error. sq->query( "DROP TABLE " + remaining_tables[0]); }
9570352001-08-09Per Hedbor  return 0; }
c488632001-03-04Per Hedbor int image_id = time() ^ gethrtime();
a32e962001-03-04Per Hedbor 
7042992001-03-04Per Hedbor string is_image( string x )
a32e962001-03-04Per Hedbor {
44d4172001-10-05Per Hedbor  if( !stringp(x) ) return 0;
8b89ed2001-07-24Johan Sundström  if( has_prefix( x, "GIF" ) )
7042992001-03-04Per Hedbor  return "gif"; if( has_value( x, "JFIF" ) ) return "jpeg";
8b89ed2001-07-24Johan Sundström  if( has_prefix( x, "\x89PNG" ) )
7042992001-03-04Per Hedbor  return "png"; }
a32e962001-03-04Per Hedbor 
b5a1522010-09-24Martin Jonsson int is_deflated (string what) { // This detection is an estimate - it may give false positives. if (!stringp (what) || sizeof (what) < 3) return 0; return ((what[0] & 0x0f) == 8) && !(((what[0] << 8) + what[1]) % 31); }
7ff5522001-03-05Per Hedbor  int is_encode_value( string what ) {
44d4172001-10-05Per Hedbor  if( !stringp(what) ) return 0;
d784262009-09-15Martin Stjernholm  return strlen(what) >= 5 && has_prefix (what, "¶ke");
7ff5522001-03-05Per Hedbor } string format_decode_value( string what ) {
e6f6392007-05-26Martin Stjernholm #if 0
7ff5522001-03-05Per Hedbor  string trim_comments( string what ) /* Needs work */ { string a, b; while( sscanf( what, "%s/*%*s*/%s", a, b ) ) what = a+b; return what; };
e6f6392007-05-26Martin Stjernholm #endif
7ff5522001-03-05Per Hedbor 
7bc5cc2001-09-03Per Hedbor  // Type is program or object? if( (what[4] & 15) == 5 || (what[4] & 15) == 3 ) return Roxen.html_encode_string( sprintf("<"+_(233,"bytecode data")+" ("+
2b73ed2017-05-29Pontus Östlund  _(505,"%d bytes")+")>", strlen(what)));
7ff5522001-03-05Per Hedbor  catch {
7bc5cc2001-09-03Per Hedbor  return "<pre>"+
e6f6392007-05-26Martin Stjernholm  Roxen.html_encode_string(
2b73ed2017-05-29Pontus Östlund  String.trim_all_whites(sprintf("%O",decode_value(what))))+
7bc5cc2001-09-03Per Hedbor  "</pre>";
7ff5522001-03-05Per Hedbor  };
c8516a2001-03-16Per Hedbor  return Roxen.html_encode_string( what );
7ff5522001-03-05Per Hedbor }
7042992001-03-04Per Hedbor string store_image( string x ) {
a32e962001-03-04Per Hedbor  string id = (string)image_id++;
7bc5cc2001-09-03Per Hedbor  .State->images[ id ] = ([
c488632001-03-04Per Hedbor  "type":"image/"+(is_image( x )||"unknown"),
a32e962001-03-04Per Hedbor  "data":x, "len":strlen(x), ]); return id; }
0d7d3a2007-01-18 Erik Dahl string db_switcher( RequestID id ) { mapping q = DBManager.get_permission_map( ); if ( !sizeof( q )) return ""; string res = #" <script type='text/javascript'> function switch_db( objSel ) { if( objSel.selectedIndex == 0) { return; } var selValue = objSel.options[objSel.selectedIndex].value; if(selValue != '&form.db:js;') {
5ad5db2016-02-10Henrik Grubbström (Grubba)  window.location.href = window.location.pathname + '?db=' + escape( selValue ) + '\x26&usr.set-wiz-id:js;';
0d7d3a2007-01-18 Erik Dahl  } } </script>
3133ff2018-01-16Pontus Östlund  <span class='select-wrapper'>
615dac2007-01-18 Erik Dahl  <select name='db' onchange='switch_db(this)'>
0d7d3a2007-01-18 Erik Dahl  <option value=''>Switch to other DB</option>\n"; foreach( sort(indices(q)), string d ) { res += sprintf( "<option value='%s'%s>%s</option>\n", d, (d == id->variables->db)? "selected='selected'": "", d); }
3133ff2018-01-16Pontus Östlund  return res + "</select></span><noscript><input type='submit' value='Switch db'/></noscript>\n";
0d7d3a2007-01-18 Erik Dahl }
e6f6392007-05-26Martin Stjernholm string format_table_owner (mapping(string:string) mod_info, void|int skip_conf) { // Note: Code duplication in db_list.pike. if ((<0, "">)[mod_info->conf]) return 0; Configuration c = roxen.find_configuration( mod_info->conf ); RoxenModule m = c && !(<0, "">)[mod_info->module] && c->find_module( mod_info->module ); ModuleInfo i = !(<0, "">)[mod_info->module] && roxen.find_module( (mod_info->module/"#")[0] ); string mn; if (!skip_conf) { if (c) { mn = "<a href='../sites/site.html/" +
2b73ed2017-05-29Pontus Östlund  Roxen.http_encode_url (mod_info->conf) + "/'>" + Roxen.html_encode_string (c->query_name()) + "</a>";
e6f6392007-05-26Martin Stjernholm  } else mn = Roxen.html_encode_string (
2b73ed2017-05-29Pontus Östlund  sprintf ((string) _(542, "the deleted site %O"), mod_info->conf));
e6f6392007-05-26Martin Stjernholm  } if( m ) { string module = "<a href='../sites/site.html/"+ Roxen.http_encode_url(mod_info->conf)+"/n!n/"+ replace(mod_info->module,"#","!")+"/"+ "'>"+ Roxen.html_encode_string (i->get_name())+"</a>"; if (mn)
fe07f52008-01-10Jonas Wallden  mn = sprintf ((string) _(543, "%s in %s"), module, mn);
e6f6392007-05-26Martin Stjernholm  else mn = module; } else if( i ) { if (mn) mn = sprintf (
2b73ed2017-05-29Pontus Östlund  (string) _(544, "the deleted module %s in %s"), Roxen.html_encode_string (sprintf ("%O", (string) i->get_name())), mn);
e6f6392007-05-26Martin Stjernholm  else mn = sprintf (
2b73ed2017-05-29Pontus Östlund  (string) _(545, "the deleted module %s"), Roxen.html_encode_string (sprintf ("%O", (string) i->get_name())));
e6f6392007-05-26Martin Stjernholm  } return mn; }
a32e962001-03-04Per Hedbor mapping|string parse( RequestID id )
b53a4a2001-01-09Per Hedbor {
7bc5cc2001-09-03Per Hedbor  if( id->variables->image ) return m_delete( .State->images, id->variables->image );
e0bd902001-10-01Per Hedbor 
a3b9102002-08-16Anders Johansson  if( !id->variables->db || !( CU_AUTH( "Edit Global Variables" ) ) )
7bc5cc2001-09-03Per Hedbor  return Roxen.http_redirect( "/dbs/", id );
9570352001-08-09Per Hedbor  string res =
719f172011-10-27Jonas Wallden  "<set variable='var.form-anchor' value='#dbquery'/>" "<use file='/template'/><tmpl>" "<topmenu base='../' selected='dbs'/>" "<content><cv-split><subtablist width='100%'><st-tabs>" "<insert file='subtabs.pike'/></st-tabs><st-page>"
2b73ed2017-05-29Pontus Östlund  "<input type='hidden' name='sort' value='&form.sort:http;' />\n";
9570352001-08-09Per Hedbor  if( id->variables->action && actions[ id->variables->action ]) {
615dac2007-01-18 Erik Dahl  res += "<input type='hidden' name='db' value='&form.db:http;' />\n";
9570352001-08-09Per Hedbor  mixed tmp = actions[ id->variables->action ][1]( id->variables->db, id ); if( stringp( tmp ) ) return res+tmp+"\n</st-page></content></tmpl>";
adcd212001-08-13Per Hedbor  if( tmp ) return tmp;
9570352001-08-09Per Hedbor  }
2f903e2001-03-04Per Hedbor  string url = DBManager.db_url( id->variables->db );
6852922001-07-31Per Hedbor 
e7588f2010-03-31Martin Stjernholm  string charset = "unicode"; #if !constant (Mysql.mysql.HAVE_MYSQL_FIELD_CHARSETNR)
4ac0932010-04-06Martin Jonsson  if (DBManager.is_mysql (url)) {
e7588f2010-03-31Martin Stjernholm  // Ugly kludge for broken mysql client lib. Works most of the // time, at least.. charset = "broken-unicode"; } #endif Sql.Sql db; mixed db_connect_error = catch (db = DBManager.get (id->variables->db, 0, 0, 0, charset)); if (db_connect_error) // Try again without charset. db_connect_error = catch (db = DBManager.get (id->variables->db));
f770512010-11-25Henrik Grubbström (Grubba)  if (!db && !db_connect_error) { db_connect_error = ({ "Failed to connect to database.\n", ({}) }); }
e7588f2010-03-31Martin Stjernholm 
6852922001-07-31Per Hedbor  string qres="";
2b73ed2017-05-29Pontus Östlund 
6852922001-07-31Per Hedbor  class QueryHistory { inherit Variable.Variable; constant type = "QueryHistory"; void create() { ::create( ([]), 65535 ); } }; object user = id->misc->config_user; QueryHistory hs; if( !(hs = user->settings->getvar( "db_history" ) ) ) { user->settings->defvar( "db_history", (hs = QueryHistory( )) ); user->settings->restore(); }
e6f6392007-05-26Martin Stjernholm  if( (!id->variables->query || id->variables["reset_q.x"]) )
6852922001-07-31Per Hedbor  {
e6f6392007-05-26Martin Stjernholm  array sel_t_columns = ({});
be89b22007-05-26Martin Stjernholm  if( !(<0, "">)[id->variables->table] ) {
e6f6392007-05-26Martin Stjernholm  if (mixed err = catch {
2b73ed2017-05-29Pontus Östlund  sel_t_columns = DBManager.db_table_fields( id->variables->db, id->variables->table ) ->name; }) { report_debug ("Error listing fields for table %s.%s: %s", id->variables->db, id->variables->table, describe_error (err));
e6f6392007-05-26Martin Stjernholm  } }
6852922001-07-31Per Hedbor  mapping h = hs->query();
e6f6392007-05-26Martin Stjernholm  function(string:string) quote_name = lambda (string s) {return s;}; if (DBManager.is_mysql (id->variables->db)) // FIXME: Ought to be generalized and put into Sql.pmod. quote_name = lambda (string s) {
2b73ed2017-05-29Pontus Östlund  if (db && db->master_sql->is_keyword (s)) return "`" + s + "`"; return s; };
e6f6392007-05-26Martin Stjernholm  if( !id->variables["reset_q.x"] &&
2b73ed2017-05-29Pontus Östlund  h[id->variables->db+"."+id->variables->table] )
e6f6392007-05-26Martin Stjernholm  id->variables->query = h[id->variables->db+"."+id->variables->table];
be89b22007-05-26Martin Stjernholm  else if( !(<0, "">)[id->variables->table] )
e6f6392007-05-26Martin Stjernholm  id->variables->query = "SELECT "+
2b73ed2017-05-29Pontus Östlund  (sizeof (sel_t_columns) ? map (sel_t_columns, quote_name) *", " : "*") + " FROM "+ quote_name (id->variables->table);
e6f6392007-05-26Martin Stjernholm  else if( DBManager.is_mysql( id->variables->db ) ) id->variables->query = "SHOW TABLES"; else id->variables->query = "";
e0bd902001-10-01Per Hedbor  }
6852922001-07-31Per Hedbor 
e6f6392007-05-26Martin Stjernholm  if (id->variables["run_q.x"] || id->variables["reset_q.x"])
6852922001-07-31Per Hedbor  hs->query()[ id->variables->db+"."+id->variables->table ] = id->variables->query-"\r";
e6f6392007-05-26Martin Stjernholm  if(db && id->variables["run_q.x"]) {
6852922001-07-31Per Hedbor  user->settings->save(); string query = "";
ce0aea2011-04-07Martin Stjernholm  // Normalize. foreach( (id->variables->query-"\r")/"\n", string q )
6852922001-07-31Per Hedbor  {
ce0aea2011-04-07Martin Stjernholm  //q = (q/" "-({""}))*" "; q = String.trim_all_whites (q);
626aec2011-04-07Martin Stjernholm  if (q == "--") break;
ce0aea2011-04-07Martin Stjernholm  if (q != "")
2b73ed2017-05-29Pontus Östlund  query = (query == "" ? q : query + "\n" + q);
6852922001-07-31Per Hedbor  }
ce0aea2011-04-07Martin Stjernholm 
6324f62011-04-07Martin Stjernholm  foreach( (query/";\n")-({""}); int i; string q )
6852922001-07-31Per Hedbor  {
6324f62011-04-07Martin Stjernholm  Sql.sql_result big_q; int h = gethrtime(); if (mixed err = catch (big_q = db->big_query( q ))) {
fe75642017-12-06Pontus Östlund  qres += "<p><span class='notify inline warn'>"+
2b73ed2017-05-29Pontus Östlund  sprintf((string)_(1062,"Error running query %d: %s"), i + 1, replace (Roxen.html_encode_string ( String.trim_all_whites (describe_error(err))), "\n", "<br/>\n"))+
fe75642017-12-06Pontus Östlund  "</span></p>\n";
2b73ed2017-05-29Pontus Östlund  continue;
6324f62011-04-07Martin Stjernholm  } float qtime = (gethrtime()-h)/1000000.0; if (!big_q)
2b73ed2017-05-29Pontus Östlund  // Query had no result or was empty/commented out. continue;
6324f62011-04-07Martin Stjernholm 
f3c2002015-04-14Henrik Grubbström (Grubba)  do {
2b73ed2017-05-29Pontus Östlund  int qrows; qres += "<p>\n" "<table id='res' class='nice valign-top'><thead><tr>"; // FIXME: Using id='res' above is wrong, as the tag // can be generated multiple times in the same // document. See also similar code further below. multiset right_columns = (<>); int column; array(string) col_types = ({}); array(string) col_names = ({}); foreach( big_q->fetch_fields(), mapping field ) { switch( field->type ) { case "char": // Actually a TINYINT. case "tiny integer": case "short": case "int": case "integer": case "long": case "long integer": case "int24": case "longlong": right_columns[column]=1; qres += "<th class='num'>"; col_types += ({"int"}); break; case "real": case "float": case "double": right_columns[column]=1; qres += "<th class='num'>"; col_types += ({"float"}); break; case "decimal": case "numeric": qres += "<th class='num'>"; col_types += ({"string"}); break; case "bit": default: qres += "<th>"; col_types += ({"string"}); } qres += Roxen.html_encode_string (field->name) + "</th>\n"; col_names += ({ field->name }); column++; } qres += "</tr></thead>"; mapping(string:string) mod_info = DBManager.module_table_info (id->variables->db, ""); Configuration c = !(<0, "">)[mod_info->conf] && roxen.find_configuration (mod_info->conf); RoxenModule m = c && !(<0, "">)[mod_info->module] && c->find_module (mod_info->module); // Find any column formatter callback in the DB's owner // module. See function prototype in base_server/module.pike. function(string,string,string,array(string),array(string),array(string), RequestID:string) format_col_cb = m && m->format_db_browser_value; array(int) formatted_total_size = allocate(sizeof(col_names), 0); if (id->variables->exp_fields == "disabled") format_col_cb = 0; while( array q = big_q->fetch_row() ) { qrows++; qres += "<tr>"; for( int i = 0; i<sizeof(q); i++ ) { qres += right_columns[i] ? "<td class='num'>" : "<td>"; if( !q[i] ) qres += "<i>NULL</i>"; else if( intp( q[i] ) || col_types[i] == "int" ) qres += (string) (int) q[i]; else if( floatp( q[i] ) || col_types[i] == "float" ) qres += (string) (float) q[i]; else if( is_image( q[i] ) ) qres += "<img src='browser.pike?image=" + store_image( q[i] ) + "&amp;&usr.set-wiz-id;' />"; else { mixed tmp = q[i]; int got_result; if (format_col_cb) { // Check for excessive amount of formatted data if (formatted_total_size[i] > MAX_TOTAL_FORMATTED_SIZE) { qres +=
fe75642017-12-06Pontus Östlund  "<span class='notify inline warn'>" +
2b73ed2017-05-29Pontus Östlund  "Total formatted data length exceeded &ndash; limit your query." "</span>"; got_result = 1; } else if (mixed formatted = format_col_cb (id->variables->db, id->variables->table, col_names[i], col_names, col_types, q, id)) { int formatted_len = sizeof(formatted); if ((formatted_len >= MAX_FIELD_FORMATTED_SIZE) && (id->variables->exp_fields == "auto")) { // This field alone is too big to display qres +=
fe75642017-12-06Pontus Östlund  "<span class='notify inline warn'>" +
2b73ed2017-05-29Pontus Östlund  "Skipping " + (formatted_len / 1024) + "K formatted data." "</span>"; got_result = 1; } else { formatted_total_size[i] += formatted_len; qres += formatted; got_result = 1; } } } if (!got_result) { if (is_deflated (tmp)) { // is_deflated _may_ give false positives, hence the catch. catch { tmp = Gz.inflate()->inflate (tmp); }; } if( is_encode_value( tmp ) ) qres += format_decode_value(tmp); else if (String.width (tmp) > 8) { // Let wide chars skip past the %q quoting, because // it'll quote them to \u escapes otherwise. string q = ""; int s; foreach (tmp; int i; int c) if (c >= 256) { if (s < i) q += sprintf ("%q", tmp[s..i - 1])[1..<1]; q += sprintf ("%c", c); s = i + 1; } q += sprintf ("%q", tmp[s..])[1..<1]; qres += Roxen.html_encode_string (q); } else qres += Roxen.html_encode_string(sprintf("%q", tmp)[1..<1]); } } qres += "</td>"; } qres += "</tr>\n"; } qres += "</table>"+ sprintf( _(426,"Query took %[0].3fs, %[1]d rows in the reply")+ "\n</p>\n", qtime, qrows); if (!big_q->next_result) break; h = gethrtime(); if (mixed err = catch (big_q = big_q->next_result())) { qres += "<p><font color='&usr.warncolor;'>"+ sprintf((string)_(1062,"Error running query %d: %s"), i + 1, replace (Roxen.html_encode_string ( String.trim_all_whites (describe_error(err))), "\n", "<br/>\n"))+ "</font></p>\n"; break; } qtime = (gethrtime()-h)/1000000.0; if (!big_q) break; // More results available.
f3c2002015-04-14Henrik Grubbström (Grubba)  } while(1);
6852922001-07-31Per Hedbor  } }
be89b22007-05-26Martin Stjernholm  if( !(<0, "">)[id->variables->table] )
e6f6392007-05-26Martin Stjernholm  res += "<input type=hidden name='table' value='&form.table:http;' />\n";
2f903e2001-03-04Per Hedbor 
e6f6392007-05-26Martin Stjernholm  // DB switcher and title.
fcd0c12001-08-14Per Hedbor 
2b73ed2017-05-29Pontus Östlund  res += "" "<table class='auto'><tr valign='center'>" "<td><span class='icon db x-large'></span></td>" +
e6f6392007-05-26Martin Stjernholm  "<td>" + db_switcher( id ) + "</td></tr></table>\n"
2b73ed2017-05-29Pontus Östlund  "<hr class='section'>" "<h3>Database <em>" + Roxen.html_encode_string (id->variables->db) + "</em></h3>\n";
fcd0c12001-08-14Per Hedbor 
e7588f2010-03-31Martin Stjernholm  if (db_connect_error)
2b73ed2017-05-29Pontus Östlund  res += "<div class='notify error'>" +
6a32272011-12-21Jonas Wallden  _(1063, "Error connecting to database: ") +
e7588f2010-03-31Martin Stjernholm  Roxen.html_encode_string (describe_error (db_connect_error)) +
2b73ed2017-05-29Pontus Östlund  "</div>\n";
e7588f2010-03-31Martin Stjernholm 
e6f6392007-05-26Martin Stjernholm  // Bullet list with generic database info.
fcd0c12001-08-14Per Hedbor 
2b73ed2017-05-29Pontus Östlund  res += "<ul>\n";
2f903e2001-03-04Per Hedbor 
2b73ed2017-05-29Pontus Östlund #define ADD_LI(X,Y) lis += ({ ([ "value" : (X), "bold" : Y ]) }) array(mapping) lis = ({});
1f9fb92017-10-18Henrik Grubbström (Grubba)  switch(id->variables->db) { case "local":
e6f6392007-05-26Martin Stjernholm  res += "<li>" +
fe07f52008-01-10Jonas Wallden  _(546, "Internal data that cannot be shared between servers.") + "</li>\n";
1f9fb92017-10-18Henrik Grubbström (Grubba)  break; case "shared":
e6f6392007-05-26Martin Stjernholm  res += "<li>" +
fe07f52008-01-10Jonas Wallden  _(547, "Internal data that may be shared between servers.") + "</li>\n";
1f9fb92017-10-18Henrik Grubbström (Grubba)  break; case "mysql": res += "<li>" +
bc131e2017-12-20Karl Gustav Sterneberg  _(1140, "MySQL/MariaDB-internal database.") + "</li>\n";
1f9fb92017-10-18Henrik Grubbström (Grubba)  break; case "roxen": res += "<li>" +
bc131e2017-12-20Karl Gustav Sterneberg  _(1141, "Roxen-internal database.") + "</li>\n";
1f9fb92017-10-18Henrik Grubbström (Grubba)  break; default: if( !url ) res += "<li>Internal database.</li>\n"; else res += "<li>Database URL: " + Roxen.html_encode_string(url)+"</li>\n"; break;
2b73ed2017-05-29Pontus Östlund  }
e6f6392007-05-26Martin Stjernholm  mapping(string:string) db_info = DBManager.module_table_info (id->variables->db, "");
2b73ed2017-05-29Pontus Östlund  if (string owner = format_table_owner (db_info)) { ADD_LI(sprintf((string)_(428,"Defined by %s."), owner), 0);
e6f6392007-05-26Martin Stjernholm  res += "<li>" + sprintf((string)_(428,"Defined by %s."), owner) + "</li>\n";
2b73ed2017-05-29Pontus Östlund  }
e6f6392007-05-26Martin Stjernholm  if (string c = db_info->comment) { c = String.trim_all_whites (c);
2b73ed2017-05-29Pontus Östlund  if (c != "") {
b1e4d72017-12-01Pontus Östlund  // ADD_LI(c, 0);
e6f6392007-05-26Martin Stjernholm  res += "<li>" + Roxen.html_encode_string (c) + "</li>\n";
2b73ed2017-05-29Pontus Östlund  }
e6f6392007-05-26Martin Stjernholm  }
0d30602007-01-17Henrik Grubbström (Grubba)  string default_charset = DBManager.get_db_default_charset(id->variables->db); if (default_charset) {
b1e4d72017-12-01Pontus Östlund  // ADD_LI(_(548,"Default charset:") + default_charset, 0);
fe07f52008-01-10Jonas Wallden  res += "<li>" + _(548,"Default charset:") +
e6f6392007-05-26Martin Stjernholm  Roxen.html_encode_string(default_charset) + "</li>";
0d30602007-01-17Henrik Grubbström (Grubba)  }
b1e4d72017-12-01Pontus Östlund  // ADD_LI(sprintf( // (string) // _(506,"Member of the %s database group."), // "<a href='edit_group.pike?group="+ // Roxen.http_encode_url(DBManager.db_group( id->variables->db ))+ // "&amp;&usr.set-wiz-id;'>" + // DBManager.get_group( DBManager.db_group( id->variables->db ) ) // ->lname + // "</a>" // ), 0);
2b73ed2017-05-29Pontus Östlund 
e6f6392007-05-26Martin Stjernholm  res +="<li>" +
2f4c982001-09-03Per Hedbor  sprintf( (string)
2b73ed2017-05-29Pontus Östlund  _(506,"Member of the %s database group."), "<a href='edit_group.pike?group="+ Roxen.http_encode_url(DBManager.db_group( id->variables->db ))+ "&amp;&usr.set-wiz-id;'>" + DBManager.get_group( DBManager.db_group( id->variables->db ) ) ->lname + "</a>")
e6f6392007-05-26Martin Stjernholm  + "</li>";
2f4c982001-09-03Per Hedbor 
c199a02015-10-21Henrik Grubbström (Grubba)  string schedule = DBManager.db_schedule(id->variables->db); if (schedule) {
b1e4d72017-12-01Pontus Östlund  // ADD_LI(sprintf( // (string)_(1114, "Backuped via the %s backup schedule."), // "<a href='schedules.html'>" + (schedule) +"</a>" // ), 0);
c199a02015-10-21Henrik Grubbström (Grubba)  res += "<li>" +
0c7a1e2016-09-27Anders Johansson  sprintf( (string)_(1114, "Backuped via the %s backup schedule."),
2b73ed2017-05-29Pontus Östlund  "<a href='schedules.html'>" + Roxen.html_encode_string(schedule) + "</a>") +
c199a02015-10-21Henrik Grubbström (Grubba)  "</li>"; } else {
b1e4d72017-12-01Pontus Östlund  // ADD_LI(_(1115, "Not a member of any backup schedule."), 1);
c199a02015-10-21Henrik Grubbström (Grubba)  res += "<li><b>" +
0c7a1e2016-09-27Anders Johansson  _(1115, "Not a member of any backup schedule.") +
c199a02015-10-21Henrik Grubbström (Grubba)  "</b></li>"; }
2b73ed2017-05-29Pontus Östlund  res += "</ul>\n"; // TRACE("lis: %O\n", lis);
2f903e2001-03-04Per Hedbor 
e6f6392007-05-26Martin Stjernholm  if (db) { // The database table list.
e0bd902001-10-01Per Hedbor 
2b73ed2017-05-29Pontus Östlund  res += "<p><table id='tbls' class='nice db-list'>";
2f903e2001-03-04Per Hedbor 
e6f6392007-05-26Martin Stjernholm  array table_data = ({});
52c2792007-05-26Martin Stjernholm  int sort_ok, got_owner_column;
2f903e2001-03-04Per Hedbor 
e6f6392007-05-26Martin Stjernholm  string deep_table_info( string table ) { array(mapping(string:mixed)) data =
2b73ed2017-05-29Pontus Östlund  DBManager.db_table_fields( id->variables->db, table );
e6f6392007-05-26Martin Stjernholm  if( !data )
2b73ed2017-05-29Pontus Östlund  return sprintf((string)_(507,"Cannot list fields in %s databases"), DBManager.db_driver(id->variables->db) );
e6f6392007-05-26Martin Stjernholm  multiset(string) props = (<>); foreach (data, mapping(string:mixed) r)
2b73ed2017-05-29Pontus Östlund  foreach (r; string prop;) props[prop] = 1; props->name = 0; // Always listed first. props->type = 0; // Always listed second. props->table = 0; // Just our own table - ignored.
e6f6392007-05-26Martin Stjernholm  array(string) sort_props = sort (indices (props));
2b73ed2017-05-29Pontus Östlund  string res = "<table id='tbl-details' class='tbl-details'>" "<thead>" "<tr>" "<th>Column</th>" "<th>Type</th>" + map (sort_props, lambda (string prop) { return "<th>" + Roxen.html_encode_string ( String.capitalize (prop)) + "</th>"; }) * "" + "</tr>\n" "</thead>" "<tbody>";
e6f6392007-05-26Martin Stjernholm  foreach( data, mapping(string:mixed) r ) {
2b73ed2017-05-29Pontus Östlund  res += "<tr>" "<td>" + Roxen.html_encode_string (r->name) + "</td>" "<td>" + Roxen.html_encode_string (r->type) + "</td>"; foreach (sort_props, string prop) { mixed val = r[prop]; if (zero_type (val)) res += "<td></td>"; else if (intp (val) || floatp (val)) res += "<td class='num'>" + val + "</td>"; else if (stringp (val)) res += "<td>" + Roxen.html_encode_string (val) + "</td>"; else if (arrayp (val) && !catch (val = (array(string)) val)) res += "<td>" + Roxen.html_encode_string (val * ", ") + "</td>"; else if (multisetp (val) && !catch (val = (array(string)) indices (val))) res += "<td>" + Roxen.html_encode_string (val * ", ") + "</td>"; else if (objectp (val)) res += "<td>" + Roxen.html_encode_string (sprintf ("%O", val)) + "</td>"; else res += "<td>" + Roxen.html_encode_string (sprintf ("<%t>", val)) + "</td>"; } res += "</tr>\n";
e6f6392007-05-26Martin Stjernholm  }
e0bd902001-10-01Per Hedbor 
2b73ed2017-05-29Pontus Östlund  return res+ "</tbody></table>";
e6f6392007-05-26Martin Stjernholm  };
e0bd902001-10-01Per Hedbor 
e6f6392007-05-26Martin Stjernholm  void add_table_info( string table, mapping tbi ) { mapping(string:string) tbl_info =
2b73ed2017-05-29Pontus Östlund  DBManager.module_table_info (id->variables->db, table);
e6f6392007-05-26Martin Stjernholm  int deep_info = id->variables->table == table;
b1e4d72017-12-01Pontus Östlund  array(string) extra_css = ({}); if (deep_info) { extra_css += ({ "tbl-open" }); } if (tbl_info->inhibit_backups) { extra_css += ({ "inhibit-backups" }); }
2b73ed2017-05-29Pontus Östlund  string res = "<tr id='tbl-" + Roxen.http_encode_url(table) + "'" +
b1e4d72017-12-01Pontus Östlund  (sizeof(extra_css) ? sprintf(" class='%s'", extra_css*" ") : "") +
2b73ed2017-05-29Pontus Östlund  ">" "<td class='nowrap'>" "<a href='browser.pike?sort=&form.sort:http;&amp;" "db=&form.db:http;&amp;&usr.set-wiz-id;" + (deep_info ? "" : "&amp;table="+Roxen.http_encode_url(table)) + "#tbl-" + Roxen.http_encode_url(table) + "'" " class='icon table no-decoration'>"+ table+"</a></td>" "<td class='num'>"+ (!tbi || zero_type (tbi->rows) ? "" : tbi->rows) + "</td>" "<td class='num'>" + (!tbi || zero_type (tbi->data_length) ? "" : sprintf ("%d KiB", ((int)tbi->data_length+(int)tbi->index_length) / 1024)) + "</td>";
fe75642017-12-06Pontus Östlund 
e6f6392007-05-26Martin Stjernholm 
52c2792007-05-26Martin Stjernholm  string owner; if ((db_info->conf || "") != (tbl_info->conf || ""))
2b73ed2017-05-29Pontus Östlund  owner = format_table_owner (tbl_info, 0);
52c2792007-05-26Martin Stjernholm  else if ((db_info->module || "") != (tbl_info->module || ""))
2b73ed2017-05-29Pontus Östlund  owner = format_table_owner (tbl_info, 1);
fe75642017-12-06Pontus Östlund  res += "<td>";
52c2792007-05-26Martin Stjernholm  if (owner) {
fe75642017-12-06Pontus Östlund  res += String.capitalize (owner);
2b73ed2017-05-29Pontus Östlund  got_owner_column = 1;
fe75642017-12-06Pontus Östlund  } else { res += "&nbsp;";
52c2792007-05-26Martin Stjernholm  }
b19f302017-10-18Henrik Grubbström (Grubba)  res += "</td>";
52c2792007-05-26Martin Stjernholm 
e6f6392007-05-26Martin Stjernholm  if (deep_info) {
bd4fb02018-01-17Pontus Östlund  res += "</tr>\n<tr class='tbl-details'><td colspan='4'>";
2b73ed2017-05-29Pontus Östlund 
e6f6392007-05-26Martin Stjernholm  if (tbl_info->comment) sscanf( tbl_info->comment, "%s\0%s", tbl_info->tbl, tbl_info->comment );
2b73ed2017-05-29Pontus Östlund 
e6f6392007-05-26Martin Stjernholm  if( tbl_info->tbl && tbl_info->tbl != table)
bd4fb02018-01-17Pontus Östlund  if( tbl_info->tbl != (string)0 ) {
e6f6392007-05-26Martin Stjernholm  res +=
fe75642017-12-06Pontus Östlund  "<div class='description'><div class='notify warn inline'>" +
e6f6392007-05-26Martin Stjernholm  sprintf((string) _(429,"The table is known as %O "
bd4fb02018-01-17Pontus Östlund  "in the module."), tbl_info->tbl ) +
fe75642017-12-06Pontus Östlund  "</div></div>\n";
2b73ed2017-05-29Pontus Östlund  }
bd4fb02018-01-17Pontus Östlund  else {
e6f6392007-05-26Martin Stjernholm  res +=
bd4fb02018-01-17Pontus Östlund  "<div class='description'><div class='notify warn inline'>" +
e6f6392007-05-26Martin Stjernholm  sprintf((string) _(430,"The table is an anonymous table defined "
bd4fb02018-01-17Pontus Östlund  "by the module."), tbl_info->tbl ) +
fe75642017-12-06Pontus Östlund  "</div></div>\n";
2b73ed2017-05-29Pontus Östlund  }
e6f6392007-05-26Martin Stjernholm  if (string c = tbl_info->comment) { c = String.trim_all_whites (c);
bd4fb02018-01-17Pontus Östlund  if (c != "" && c != "0") { res +=
2b73ed2017-05-29Pontus Östlund  "<div class='description'>" + Roxen.html_encode_string (c) +
bd4fb02018-01-17Pontus Östlund  "</div>";
2b73ed2017-05-29Pontus Östlund  }
e6f6392007-05-26Martin Stjernholm  }
2b73ed2017-05-29Pontus Östlund 
8a890d2017-10-18Henrik Grubbström (Grubba)  if (tbl_info->inhibit_backups == "yes") {
bd4fb02018-01-17Pontus Östlund  res +=
fe75642017-12-06Pontus Östlund  "<div class='description'><div class='notify inline warn'>" +
bd4fb02018-01-17Pontus Östlund  _(1142, "The table is not included in backups of this database.") + "</div></div>";
8a890d2017-10-18Henrik Grubbström (Grubba)  }
b1e4d72017-12-01Pontus Östlund 
e6f6392007-05-26Martin Stjernholm  res += deep_table_info (table) + "</td></tr>\n"; } else
2b73ed2017-05-29Pontus Östlund  res += "</tr>\n";
e0bd902001-10-01Per Hedbor 
e6f6392007-05-26Martin Stjernholm  if( tbi )
2b73ed2017-05-29Pontus Östlund  sort_ok = 1;
e0bd902001-10-01Per Hedbor 
e6f6392007-05-26Martin Stjernholm  table_data += ({({
2b73ed2017-05-29Pontus Östlund  table, (tbi ?(int)tbi->data_length+ (int)tbi->index_length:0), (tbi ?(int)tbi->rows:0), res })});
e6f6392007-05-26Martin Stjernholm  };
e0bd902001-10-01Per Hedbor 
e6f6392007-05-26Martin Stjernholm  foreach( DBManager.db_tables( id->variables->db )-({0}), string tb ) add_table_info(tb,
2b73ed2017-05-29Pontus Östlund  DBManager.db_table_information(id->variables->db, tb));
e0bd902001-10-01Per Hedbor 
e6f6392007-05-26Martin Stjernholm  switch( id->variables->sort ) { default:
2b73ed2017-05-29Pontus Östlund  sort( column( table_data, 0 ), table_data ); break;
e6f6392007-05-26Martin Stjernholm  case "rows":
2b73ed2017-05-29Pontus Östlund  sort( column( table_data, 2 ), table_data ); table_data = reverse( table_data ); break;
e6f6392007-05-26Martin Stjernholm  case "size":
2b73ed2017-05-29Pontus Östlund  sort( column( table_data, 1 ), table_data ); table_data = reverse( table_data ); break;
e6f6392007-05-26Martin Stjernholm  }
2b73ed2017-05-29Pontus Östlund #define SEL(X,Y) \ ((id->variables->sort == X || (Y && !id->variables->sort)) ? \ "<span class='icon sort-desc'></span>" : \ "<span class='icon sort'></span>")
2f903e2001-03-04Per Hedbor 
e6f6392007-05-26Martin Stjernholm  if( sort_ok ) {
52c2792007-05-26Martin Stjernholm  if (!got_owner_column)
2b73ed2017-05-29Pontus Östlund  // Try to hide the owner column when it's empty. Doesn't work // in firefox 2.0, though. res += "<col span='3'/><col style='visiblity: collapse'/>\n";
e6f6392007-05-26Martin Stjernholm  res +=
2b73ed2017-05-29Pontus Östlund  "<thead><tr>" "<th><a href='browser.pike?db=&form.db:http;&amp;table=&form.table:http;&amp;sort=name&amp;&usr.set-wiz-id;'>"+ SEL("name", 1) + _(376,"Name")+ "</a></th>\n" "<th class='num'><a href='browser.pike?db=&form.db:http;&amp;table=&form.table:http;&amp;sort=rows&amp;&usr.set-wiz-id;'>"+ SEL("rows",0)+String.capitalize(_(374,"rows"))+ "</a></th>\n" "<th class='num'><a href='browser.pike?db=&form.db:http;&amp;table=&form.table:http;&amp;sort=size&amp;&usr.set-wiz-id;'>"+ SEL("size",0)+_(377,"Size")+ "</a></th>\n" "<th>Owner</th>\n" "</tr></thead>\n";
e6f6392007-05-26Martin Stjernholm  }
2f903e2001-03-04Per Hedbor 
e6f6392007-05-26Martin Stjernholm  res += "<tbody>" + column( table_data, 3 )*"\n" + "</tbody></table></p>\n";
2f903e2001-03-04Per Hedbor 
e6f6392007-05-26Martin Stjernholm  // Query widget.
2f903e2001-03-04Per Hedbor 
c403b32015-04-02Jonas Walldén  string formatter_options = "<span style='font-size: smaller;'>Smart field formatters: </span>" "<default variable='form.exp_fields'>" "<select name='exp_fields'>" " <option value='auto'>Enabled for data &lt; " + (MAX_FIELD_FORMATTED_SIZE / 1024) + "K</option>" " <option value='disabled'>Disabled</option>" " <option value='force'>Force expansion of long fields</option>" "</select>" "</default>" "<br />";
2b73ed2017-05-29Pontus Östlund 
c403b32015-04-02Jonas Walldén  int db_has_formatters = 0; if (id->variables->db) { mapping(string:string) mod_info =
2b73ed2017-05-29Pontus Östlund  DBManager.module_table_info (id->variables->db, "");
c403b32015-04-02Jonas Walldén  Configuration c = !(<0, "">)[mod_info->conf] &&
2b73ed2017-05-29Pontus Östlund  roxen.find_configuration (mod_info->conf);
c403b32015-04-02Jonas Walldén  RoxenModule m = c && !(<0, "">)[mod_info->module] &&
2b73ed2017-05-29Pontus Östlund  c->find_module (mod_info->module);
c403b32015-04-02Jonas Walldén  db_has_formatters = m && m->format_db_browser_value; }
2b73ed2017-05-29Pontus Östlund 
e6f6392007-05-26Martin Stjernholm  res +=
f4b1c32011-10-25 Erik Dahl  "<a name='dbquery'></a><p>"
3a29632008-11-27Martin Stjernholm  "<textarea rows='12' cols='90' wrap='soft' name='query' "
de32f72008-11-18Jonas Wallden  " style='font-size: 90%'>" +
c403b32015-04-02Jonas Walldén  Roxen.html_encode_string (id->variables->query) + "</textarea><br />" + (db_has_formatters ? formatter_options : "") +
2b73ed2017-05-29Pontus Östlund  "<table class='auto'><tr><td>" "<submit-gbutton2 name=reset_q>"+_(378,"Reset query")+"</submit-gbutton2>"
626aec2011-04-07Martin Stjernholm  "</td><td>"
2b73ed2017-05-29Pontus Östlund  "<submit-gbutton2 name=run_q>"+_(379,"Run query")+"</submit-gbutton2>"
626aec2011-04-07Martin Stjernholm  "</td><td style='font-size: smaller; padding-left: 10px'>" +
6a32272011-12-21Jonas Wallden  _(1064, "Tip: Put '--' on a line to ignore everything below it.") +
626aec2011-04-07Martin Stjernholm  "</td></tr></table></p>";
e6f6392007-05-26Martin Stjernholm  // Query result. res += qres; }
8b89ed2001-07-24Johan Sundström 
e6f6392007-05-26Martin Stjernholm  // Actions.
9570352001-08-09Per Hedbor 
e6f6392007-05-26Martin Stjernholm  res += "<p>";
e0bd902001-10-01Per Hedbor 
c199a02015-10-21Henrik Grubbström (Grubba)  int flags = DBManager.is_internal(id->variables->db)*3; if (!flags) { mapping(string:mixed) url_info = DBManager.get_db_url_info(id->variables->db); if (url_info && has_prefix(url_info->path, "mysql://")) { // Is external mysql. flags = 2; } }
2b73ed2017-05-29Pontus Östlund #define ADD_ACTION(X) if(!actions[X][2] || (actions[X][2] & flags) ) \ res += sprintf("<link-gbutton href='%s?db=%s&amp;action=%s&amp;&usr.set-wiz-id;'>%s</link-gbutton>\n",\ id->not_query, id->variables->db, X, actions[X][0] ) #define ADD_ACTION2(X) \ do { \ res += sprintf( \ "<option value='%s?db=%s&amp;action=%s&amp;&usr.set-wiz-id;'>%s</option>", \ id->not_query, id->variables->db, X, actions[X][0]); \ } while (0)
9570352001-08-09Per Hedbor  switch( id->variables->db ) { case "local":
3133ff2018-01-16Pontus Östlund  res += "<hr><span class='select-wrapper'>" "<select data-goto=''><option>Select action...</option>";
2b73ed2017-05-29Pontus Östlund 
bd4fb02018-01-17Pontus Östlund  foreach( ({ "backup","optimize","repair","schedule" }), string x ) {
2b73ed2017-05-29Pontus Östlund  ADD_ACTION2( x ); } res += "</select>"
3133ff2018-01-16Pontus Östlund  "</span>"
2b73ed2017-05-29Pontus Östlund  "<link-gbutton href='./' type='cancel'>Cancel</link-gbutton>";
9570352001-08-09Per Hedbor  break;
2b73ed2017-05-29Pontus Östlund 
9570352001-08-09Per Hedbor  default:
3133ff2018-01-16Pontus Östlund  res += "<hr><span class='select-wrapper'>" "<select data-goto=''><option>Select action...</option>";
2b73ed2017-05-29Pontus Östlund 
e2d8df2017-12-21Karl Gustav Sterneberg  array(string) action_ids = sort( indices( actions ) ); if (DBManager.is_internal( id->variables->db )) { action_ids -= ({ "configure_ext_db_con" }); }
bd4fb02018-01-17Pontus Östlund  foreach( action_ids, string x ) {
2b73ed2017-05-29Pontus Östlund  ADD_ACTION2( x ); } res += "</select>"
3133ff2018-01-16Pontus Östlund  "</span>"
2b73ed2017-05-29Pontus Östlund  "<link-gbutton href='./' type='cancel'>Cancel</link-gbutton>";
9570352001-08-09Per Hedbor  break;
e0bd902001-10-01Per Hedbor  }
e6f6392007-05-26Martin Stjernholm  return res+"</p></st-page></subtablist></cv-split></content></tmpl>";
b53a4a2001-01-09Per Hedbor }