account.module 15.3 KB
Newer Older
Dries's avatar
 
Dries committed
1
<?php
Dries's avatar
 
Dries committed
2

Dries's avatar
 
Dries committed
3
$module = array("help" => "account_help",
Dries's avatar
 
Dries committed
4
                "find" => "account_find",
Dries's avatar
 
Dries committed
5 6
                "admin" => "account_admin");

Dries's avatar
 
Dries committed
7 8
function account_help() {
 ?>
Dries's avatar
 
Dries committed
9
  <P>The account-module is responsible for maintaining the user database. It automatically handles tasks like registration, authentication, access control, password retrieval, user settings and much more.</P>
Dries's avatar
 
Dries committed
10 11
  <P>The required administration can be accomplished through the "account" interface of the administration section.  From here administrators can get a quick overview of all registered users and view/edit specific accounts using the links provided.  Some useful operations include blocking specific accounts (e.g. a troublesome user) and giving/taking administration permissions.  Note that you should only give these permissions to people you trust!</P>
  <P>Check the documentation page for detailed information about user management.</P>
Dries's avatar
 
Dries committed
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
  <H3>Regular expressions</H3>
  <P>A <I>regular expression</I> (or <I>regexp</I>, or <I>pattern</I>) is a text string that describes some (mathematical) set of strings.  A regexp <CODE>R</CODE> "matches" a string <CODE>S</CODE> if <CODE>S</CODE> is in the set of strings described by <CODE>R</CODE>.</P>
  <P>Regular expressions are very powerful but often get complicated and nothing in this write-up can change that.
  <P>A complete explanation of regular expressions is beyond the scope of this help system.  A regular expression may use any of the following special characters/constructs:</P>
  <TABLE BORDER="1">
   <TR><TD>^</TD><TD>Matches the beginning of a string.<TD></TR>
   <TR><TD>$</TD><TD>Matches the end of a string.<TD></TR>
   <TR><TD>.</TD><TD>Matches any character (including newline). For example the regular expression a.c would match the strings abc, adb, axb, but not axxc.<TD></TR>
   <TR><TD>a*</TD><TD>Matches any sequence of zero or more a characters.</TD></TR>
   <TR><TD>a+</TD><TD>Matches any sequence of one or more a characters.</TD></TR>
   <TR><TD>a?</TD><TD>Matches either zero or one a character.</TD></TR>
   <TR><TD>ab|cd</TD><TD>Matches either of the sequences "ab" or "cd".</TD></TR>
   <TR><TD>(abc)*</TD><TD>Matches zero or more instances of the sequence abc.</TD></TR>
   <TR><TD>[abc]</TD><TD>Matches any one of the characters between the brackets: a, b or c.  Ranges of characters can specified by using a hyphen. For example, the regular expression [0-9] means match any digit.  Multiple ranges can be specified as well. The regular expression [A-Za-z] means match any upper or lower case letter. To match any character except those in the range, the complement range, use the caret as the first character after the opening bracket.  For example, the expression [^269A-Z] will match any characters except 2, 6, 9, and upper case letters.</TD></TR>
   <TR><TD>{num}</TD><TD>Matches the preceding element num times.</TD></TR>
   <TR><TD>{min, max}</TD><TD>Matches the preceding element at least min times, but not more than max times.</TD></TR>
  </TABLE>
  <P><B>Examples:</B></P>
  <TABLE BORDER="1">
   <TR><TD>apple</TD><TD>Matches any string that has the text "apple" in it.<TD></TR>
   <TR><TD>^apple$</TD><TD>Matches the exact string "apple".<TD></TR>
   <TR><TD>^apple</TD><TD>Matches any string that starts with "apple".<TD></TR>
   <TR><TD>domain\.com$</TD><TD>Matches any string that ends with "@domain.com".  Note that you have to escape the dot in domain.com.</TD></TR>
  </TABLE>
Dries's avatar
 
Dries committed
36
 <?php
Dries's avatar
 
Dries committed
37 38
}

Dries's avatar
 
Dries committed
39
function account_find($keys) {
Dries's avatar
 
Dries committed
40
  global $user;
Dries's avatar
 
Dries committed
41
  $find = array();
Dries's avatar
 
Dries committed
42
  $result = db_query("SELECT * FROM users WHERE userid LIKE '%$keys%' LIMIT 20");
Dries's avatar
 
Dries committed
43
  while ($account = db_fetch_object($result)) {
Dries's avatar
 
Dries committed
44
    array_push($find, array("subject" => $account->userid, "link" => (user_access($user, "account") ? "admin.php?mod=account&op=view&name=$account->userid" : "account.php?op=view&name=$account->userid"), "user" => $account->userid));
Dries's avatar
 
Dries committed
45 46
  }
  return $find;
Dries's avatar
 
Dries committed
47
}
Dries's avatar
 
Dries committed
48

Dries's avatar
 
Dries committed
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
function account_ac_add($edit) {
  db_query("INSERT INTO access (mask, type, reason) VALUES ('". check_input($edit[mask]) ."', '". check_input($edit[type]) ."', '". check_input($edit[reason]) ."')", 1);
}

function account_ac_del($id) {
  db_query("DELETE FROM access WHERE id = '$id'");
}

function account_ac_check($edit) {
  return "\"$edit[text]\" ". (($rule = user_ban($edit[text], $edit[category])) ? "matched with access rule '$rule->mask'" : "did not match any of the existing access rules") .".";
}

function account_ac() {
  $access = array("e-mail address", "hostname", "username");

  $result = db_query("SELECT * FROM access");

  foreach ($access as $value) $type .= " <OPTION VALUE=\"$value\">$value</OPTION>\n";

  $output .= "<FORM ACTION=\"admin.php?mod=account&op=access\" METHOD=\"post\">\n";
  $output .= "<TABLE BORDER=\"1\" CELLPADDING=\"3\" CELLSPACING=\"0\">\n";
  $output .= " <TR><TH>mask</TH><TH>type</TH><TH>reason</TH><TH>oparations</TH></TR>\n";
  while ($rule = db_fetch_object($result)) {
    $output .= " <TR><TD>$rule->mask</TD><TD ALIGN=\"center\">$rule->type</TD><TD>". check_output($rule->reason) ."</TD><TD><A HREF=\"admin.php?mod=account&op=delete+rule&id=$rule->id\">delete rule</A></TD></TR>\n";
  }
  $output .= " <TR><TD><INPUT TYPE=\"text\" NAME=\"edit[mask]\"></TD><TD><SELECT NAME=\"edit[type]\">\n$type</SELECT></TD><TD><INPUT TYPE=\"text\" NAME=\"edit[reason]\"></TD><TD><INPUT NAME=\"op\" TYPE=\"submit\" VALUE=\"Add rule\"></TD></TR>\n";
  $output .= " <TR><TD COLSPAN=\"4\"><SMALL><I>Use <A HREF=\"admin.php?mod=account&op=help\">regular expressions</A> (regexs) to specify the mask pattern.</I></SMALL></TD></TR>\n";
  $output .= "</TABLE>\n";
  $output .= "<BR><BR>\n";
  $output .= "<TABLE BORDER=\"1\" CELLPADDING=\"3\" CELLSPACING=\"0\">\n";
  $output .= " <TR><TH COLSPAN=\"3\">check access rules</TH></TR>\n";
  $output .= " <TR><TD><INPUT TYPE=\"text\" NAME=\"edit[text]\"></TD><TD><SELECT NAME=\"edit[category]\">\n$type</SELECT></TD><TD><INPUT NAME=\"op\" TYPE=\"submit\" VALUE=\"Check\"></TD></TR>\n";
  $output .= "</TABLE>\n";
  $output .= "</FORM>\n";

  return $output;
}

Dries's avatar
 
Dries committed
87
function account_overview($query = array()) {
Dries's avatar
 
Dries committed
88

Dries's avatar
 
Dries committed
89
  $result = db_query("SELECT id, userid, last_access FROM users $query[1] LIMIT 50");
Dries's avatar
 
Dries committed
90

Dries's avatar
 
Dries committed
91
  $output .= status($query[0]);
Dries's avatar
 
Dries committed
92
  $output .= "<TABLE BORDER=\"1\" CELLPADDING=\"2\" CELLSPACING=\"2\">\n";
Dries's avatar
 
Dries committed
93
  $output .= " <TR><TH>username</TH><TH>last access</TH><TH COLSPAN=\"2\">operations</TH></TR>\n";
Dries's avatar
 
Dries committed
94
  while ($account = db_fetch_object($result)) {
Dries's avatar
 
Dries committed
95
    $output .= " <TR><TD>". format_username($account->userid) ."</TD><TD>". format_date($account->last_access) ."</TD><TD ALIGN=\"center\"><A HREF=\"admin.php?mod=account&op=view&name=$account->userid\">view account</A></TD><TD ALIGN=\"center\"><A HREF=\"admin.php?mod=account&op=edit&name=$account->userid\">edit account</A></TD></TR>\n";
Dries's avatar
 
Dries committed
96 97 98
  }
  $output .= "</TABLE>\n";

Dries's avatar
 
Dries committed
99
  return $output;
Dries's avatar
 
Dries committed
100 101
}

Dries's avatar
 
Dries committed
102 103 104 105
function account_access($account) {
  $data = explode(";", $account->access);
  foreach ($data as $array) {
    $access = explode(":", $array);
Dries's avatar
 
Dries committed
106
    if ($access[0]) $output .= " $access[0]";
Dries's avatar
 
Dries committed
107 108 109 110
  }
  return $output;
}

Dries's avatar
 
Dries committed
111
function account_blocks($id) {
Dries's avatar
 
Dries committed
112
  $result = db_query("SELECT * FROM layout WHERE user = '$id'");
Dries's avatar
 
Dries committed
113
  while ($layout = db_fetch_object($result)) {
Dries's avatar
 
Dries committed
114
    $output .= "<LI>$layout->block</LI>\n";
Dries's avatar
 
Dries committed
115 116 117 118
  }
  return $output;
}

Dries's avatar
 
Dries committed
119
function account_nodes($id) {
Dries's avatar
 
Dries committed
120
  $result = db_query("SELECT * FROM node WHERE author = $id ORDER BY timestamp DESC");
Dries's avatar
 
Dries committed
121 122
  while ($node = db_fetch_object($result)) {
    $output .= "<LI><A HREF=\"node.php?id=$node->nid\">$node->title</A> ($node->type)</LI>\n";
Dries's avatar
 
Dries committed
123 124 125 126 127
  }
  return $output;
}

function account_comments($id) {
Dries's avatar
 
Dries committed
128
  $result = db_query("SELECT * FROM comments WHERE author = '$id' ORDER BY timestamp DESC");
Dries's avatar
 
Dries committed
129
  while ($comment = db_fetch_object($result)) {
Dries's avatar
 
Dries committed
130
    $output .= "<LI><A HREF=\"node.php?id=$comment->lid&cid=$comment->cid&pid=$comment->pid#$comment->cid\">$comment->subject</A></LI>\n";
Dries's avatar
 
Dries committed
131 132 133 134
  }
  return $output;
}

Dries's avatar
 
Dries committed
135 136 137
function account_delete($name) {
  $result = db_query("SELECT * FROM users WHERE userid = '$name' AND status = 0 AND id > 1");
  if ($account = db_fetch_object($result)) {
Dries's avatar
 
Dries committed
138
    db_query("DELETE FROM users WHERE id = '$account->id'");
Dries's avatar
 
Dries committed
139 140
  }
  else {
Dries's avatar
 
Dries committed
141
    return "failed to delete account '". format_username($name) ."': the account must be blocked first.";
Dries's avatar
 
Dries committed
142 143 144
  }
}

145
function account_edit_save($name, $edit) {
Dries's avatar
 
Dries committed
146
  foreach ($edit as $key=>$value) if ($key != "access") $query .= "$key = '". addslashes($value) ."', ";
Dries's avatar
 
Dries committed
147
  db_query("UPDATE users SET $query access = '' WHERE userid = '$name'");
Dries's avatar
 
Dries committed
148
  if ($edit[access]) foreach ($edit[access] as $key=>$value) user_set(user_load($name), "access", $value, 1);
Dries's avatar
 
Dries committed
149 150 151 152 153

  watchdog("message", "account: modified user '$name'");
}

function account_edit($name) {
Dries's avatar
 
Dries committed
154 155 156 157 158 159 160
  global $access, $account;

  function access($name, $module) {
    global $access, $account;
    $access .= "<OPTION VALUE=\"$name\"". (user_access($account, $name) ? " SELECTED" : "") .">$name</OPTION>";
  }

Dries's avatar
 
Dries committed
161 162 163 164 165 166
  $status = array(0 => "blocked", 1 => "not confirmed", 2 => "open");

  $result = db_query("SELECT * FROM users WHERE userid = '$name'");

  if ($account = db_fetch_object($result)) {
    foreach ($status as $key=>$value) {
Dries's avatar
 
Dries committed
167
      $stat .= " <OPTION VALUE=\"$key\"". (($account->status == $key) ? " SELECTED" : "") .">$value</OPTION>\n";
Dries's avatar
 
Dries committed
168 169
    }

Dries's avatar
 
Dries committed
170
    module_iterate("access");
Dries's avatar
 
Dries committed
171 172

    $output .= "<FORM ACTION=\"admin.php?mod=account\" METHOD=\"post\">\n";
Dries's avatar
 
Dries committed
173 174 175 176
    $output .= "<B>ID:</B><BR>$account->id<P>\n";
    $output .= "<B>Username:</B><BR>". check_output($account->userid) ."<P>\n";
    $output .= "<B>Status:</B><BR><SELECT NAME=\"edit[status]\">\n$stat</SELECT><P>\n";
    $output .= "<B>Administrator access:</B><BR><SELECT NAME=\"edit[access][]\" MULTIPLE=\"true\" SIZE=\"10\">$access</SELECT><P>\n";
Dries's avatar
 
Dries committed
177 178 179 180 181 182
    $output .= "<B>Real name:</B><BR><INPUT NAME=\"edit[name]\" SIZE=\"55\" VALUE=\"". check_textfield($account->name). "\"><P>\n";
    $output .= "<B>Real e-mail address:</B><BR><INPUT NAME=\"edit[real_email]\" SIZE=\"55\" VALUE=\"". check_textfield($account->real_email) ."\"><P>\n";
    $output .= "<B>Fake e-mail address:</B><BR><INPUT NAME=\"edit[fake_email]\" SIZE=\"55\" VALUE=\"". check_textfield($account->fake_email) ."\"><P>\n";
    $output .= "<B>URL of homepage:</B><BR><INPUT NAME=\"edit[url]\" SIZE=\"55\" VALUE=\"". check_textfield($account->url) ."\"><P>\n";
    $output .= "<B>Bio information:</B><BR><TEXTAREA NAME=\"edit[bio]\" COLS=\"35\" ROWS=\"5\" WRAP=\"virtual\">". check_textarea($account->bio) ."</TEXTAREA><P>\n";
    $output .= "<B>Signature:</B><BR><TEXTAREA NAME=\"edit[signature]\" COLS=\"35\" ROWS=\"5\" WRAP=\"virtual\">". check_textarea($account->signature) ."</TEXTAREA><P>\n";
Dries's avatar
 
Dries committed
183 184 185
    $output .= "<INPUT TYPE=\"hidden\" NAME=\"name\" VALUE=\"$account->userid\">\n";
    $output .= "<INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"View account\">\n";
    $output .= "<INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Save account\">\n";
Dries's avatar
 
Dries committed
186
    $output .= "</FORM>\n";
Dries's avatar
 
Dries committed
187
    return $output;
Dries's avatar
 
Dries committed
188 189 190
  }
}

Dries's avatar
 
Dries committed
191 192 193 194 195 196
function account_view($name) {
  $status = array(0 => "blocked", 1 => "not confirmed", 2 => "open");

  $result = db_query("SELECT * FROM users WHERE userid = '$name'");

  if ($account = db_fetch_object($result)) {
Dries's avatar
 
Dries committed
197
    $output .= "<FORM ACTION=\"admin.php?mod=account\" METHOD=\"post\">\n";
Dries's avatar
 
Dries committed
198
    $output .= "<TABLE BORDER=\"1\" CELLPADDING=\"3\" CELLSPACING=\"0\">\n";
Dries's avatar
 
Dries committed
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
    $output .= " <TR><TH>ID:</TH><TD>$account->id</TD></TR>\n";
    $output .= " <TR><TH>Username:</TH><TD>$account->userid</TD></TR>\n";
    $output .= " <TR><TH>Status:</TH><TD>". $status[$account->status] ."</TD></TR>\n";
    $output .= " <TR><TH>Access:</TH><TD>". check_output(account_access($account)) ."</TD></TR>\n";
    $output .= " <TR><TH>Real name:</TH><TD>". check_output($account->name) ."</TD></TR>\n";
    $output .= " <TR><TH>Real e-mail address:</TH><TD>". format_email($account->real_email) ."</TD></TR>\n";
    $output .= " <TR><TH>Fake e-mail address:</TH><TD>". check_output($account->fake_email) ."</TD></TR>\n";
    $output .= " <TR><TH>URL of homepage:</TH><TD>". format_url($account->url) ."</TD></TR>\n";
    $output .= " <TR><TH>Last access:</TH><TD>". format_date($account->last_access) ." from ". check_output($account->last_host) ."</TD></TR>\n";
    $output .= " <TR><TH>User rating:</TH><TD>". check_output($account->rating) ."</TD></TR>\n";
    $output .= " <TR><TH>Bio information:</TH><TD>". check_output($account->bio) ."</TD></TR>\n";
    $output .= " <TR><TH><B>Signature:</TH><TD>". check_output($account->signature) ."</TD></TR>\n";
    $output .= " <TR><TH>Theme:</TH><TD>". check_output($account->theme) ."</TD></TR>\n";
    $output .= " <TR><TH>Timezone:</TH><TD>". check_output($account->timezone / 3600) ."</TD></TR>\n";
    $output .= " <TR><TH>Selected blocks:</TH><TD>". check_output(account_blocks($account->id)) ."</TD></TR>\n";
Dries's avatar
 
Dries committed
214
    $output .= " <TR><TH>Submitted nodes:</TH><TD>". check_output(account_nodes($account->id)) ."</TD></TR>\n";
Dries's avatar
 
Dries committed
215 216
    $output .= " <TR><TH>Submitted comments:</TH><TD>". check_output(account_comments($account->id)) ."</TD></TR>\n";
    $output .= " <TR><TD ALIGN=\"center\" COLSPAN=\"2\"><INPUT TYPE=\"hidden\" NAME=\"name\" VALUE=\"$account->userid\"><INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Edit account\"><INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Delete account\"></TD></TR>\n";
Dries's avatar
 
Dries committed
217
    $output .= "</TABLE>\n";
Dries's avatar
 
Dries committed
218
    $output .= "</FORM>\n";
Dries's avatar
 
Dries committed
219
    return $output;
Dries's avatar
 
Dries committed
220 221 222
  }
}

Dries's avatar
 
Dries committed
223 224 225 226 227 228 229 230
function account_query($type = "") {
  $queries = array(0 => array("users recently visiting", "ORDER BY last_access DESC"), 1 => array("users recently joining", "ORDER BY id DESC"), 2 => array("users with access rights", "WHERE access != '' ORDER BY last_access DESC"), 3 => array("users with pending accounts", "WHERE status = 1 ORDER BY last_access DESC"), 4 => array("users with blocked accounts", "WHERE status = 0 ORDER BY last_access DESC"));
  return ($queries[$type] ? $queries[$type] : $queries);
}

function account_listing() {
  foreach (account_query() as $key=>$array) {
    $output .= "<LI><A HREF=\"admin.php?mod=account&type=$key\">$array[0]</A></LI>\n";
Dries's avatar
 
Dries committed
231 232 233 234
  }
  return "<OL>$output</OL>\n";
}

Dries's avatar
 
Dries committed
235
function account_admin() {
Dries's avatar
 
Dries committed
236
  global $op, $edit, $id, $mod, $keys, $order, $name, $type;
Dries's avatar
 
Dries committed
237

Dries's avatar
 
Dries committed
238 239 240
  print "<SMALL><A HREF=\"admin.php?mod=account&op=access\">access control</A> | <A HREF=\"admin.php?mod=account&op=listing\">account listings</A> | <A HREF=\"admin.php?mod=account&op=search\">search account</A> | <A HREF=\"admin.php?mod=account\">overview</A> | <A HREF=\"admin.php?mod=account&op=help\">help</A></SMALL><HR>";

  $type = ($type ? $type : 1);
Dries's avatar
 
Dries committed
241

Dries's avatar
 
Dries committed
242
  switch ($op) {
Dries's avatar
 
Dries committed
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
    case "access":
      print account_ac();
      break;
    case "Add rule":
      print status(account_ac_add($edit));
      print account_ac();
      break;
    case "Check":
      print status(account_ac_check($edit));
      print account_ac();
      break;
    case "delete rule":
      print status(account_ac_del($id));
      print account_ac();
      break;
Dries's avatar
 
Dries committed
258 259
    case "Delete account":
    case "delete":
Dries's avatar
 
Dries committed
260
      print status(account_delete(check_input($name)));
Dries's avatar
 
Dries committed
261
      print account_overview(account_query($type));
Dries's avatar
 
Dries committed
262 263
      break;
    case "Edit account":
Dries's avatar
 
Dries committed
264
    case "edit":
Dries's avatar
 
Dries committed
265
      print account_edit(check_input($name));
Dries's avatar
 
Dries committed
266
      break;
Dries's avatar
 
Dries committed
267
    case "help":
Dries's avatar
 
Dries committed
268
      print account_help();
Dries's avatar
 
Dries committed
269
      break;
Dries's avatar
 
Dries committed
270 271 272
    case "listing":
      print account_listing();
      break;
Dries's avatar
 
Dries committed
273
    case "search":
Dries's avatar
 
Dries committed
274 275
      print search_form($keys);
      print search_data($keys, $mod);
Dries's avatar
 
Dries committed
276
      break;
Dries's avatar
 
Dries committed
277 278 279 280
    case "Save account":
      print status(account_edit_save(check_input($name), $edit));
      print account_view(check_input($name));
      break;
Dries's avatar
 
Dries committed
281
    case "View account":
Dries's avatar
 
Dries committed
282
    case "view":
Dries's avatar
 
Dries committed
283
      print account_view($name);
Dries's avatar
 
Dries committed
284 285
      break;
    default:
Dries's avatar
 
Dries committed
286
      print account_overview(account_query($type));
Dries's avatar
 
Dries committed
287 288 289
  }
}

Dries's avatar
 
Dries committed
290
?>