root/main/trunk/greenstone2/runtime-src/src/recpt/usersaction.cpp @ 28899

Revision 28899, 14.0 KB (checked in by ak19, 5 years ago)

Third commit for security, for ensuring cgiargs macros are websafe. This time all the changes to the runtime action classes.

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1/**********************************************************************
2 *
3 * usersaction.cpp -- managing users
4 * Copyright (C) 1999  DigiLib Systems Limited, New Zealand
5 *
6 * A component of the Greenstone digital library software
7 * from the New Zealand Digital Library Project at the
8 * University of Waikato, New Zealand.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 *********************************************************************/
25
26#include "gsdl_modules_cfg.h"
27#ifdef GSDL_USE_USERS_ACTION
28
29#include "usersaction.h"
30#include "fileutil.h"
31
32
33///////////////
34// usersaction
35///////////////
36
37usersaction::usersaction () {
38  // this action uses cgi variable "a"
39  cgiarginfo arg_ainfo;
40  arg_ainfo.shortname = "a";
41  arg_ainfo.longname = "action";
42  arg_ainfo.multiplechar = true;
43  arg_ainfo.multiplevalue = false;
44  arg_ainfo.defaultstatus = cgiarginfo::weak;
45  arg_ainfo.argdefault = "um"; // user management
46  arg_ainfo.savedarginfo = cgiarginfo::must;
47  argsinfo.addarginfo (NULL, arg_ainfo);
48
49  // "uma"
50  arg_ainfo.shortname = "uma";
51  arg_ainfo.longname = "user management action";
52  arg_ainfo.multiplechar = true;
53  arg_ainfo.multiplevalue = false;
54  arg_ainfo.defaultstatus = cgiarginfo::weak;
55  arg_ainfo.argdefault = "listusers";
56  arg_ainfo.savedarginfo = cgiarginfo::mustnot;
57  argsinfo.addarginfo (NULL, arg_ainfo);
58
59  // "umun"
60  arg_ainfo.shortname = "umun";
61  arg_ainfo.longname = "user management user name";
62  arg_ainfo.multiplechar = true;
63  arg_ainfo.multiplevalue = false;
64  arg_ainfo.defaultstatus = cgiarginfo::weak;
65  arg_ainfo.argdefault = g_EmptyText;
66  arg_ainfo.savedarginfo = cgiarginfo::mustnot;
67  argsinfo.addarginfo (NULL, arg_ainfo);
68
69  // "umpw"
70  arg_ainfo.shortname = "umpw";
71  arg_ainfo.longname = "user management password";
72  arg_ainfo.multiplechar = true;
73  arg_ainfo.multiplevalue = false;
74  arg_ainfo.defaultstatus = cgiarginfo::weak;
75  arg_ainfo.argdefault = g_EmptyText;
76  arg_ainfo.savedarginfo = cgiarginfo::mustnot;
77  argsinfo.addarginfo (NULL, arg_ainfo);
78
79  // "umnpw1"
80  arg_ainfo.shortname = "umnpw1";
81  arg_ainfo.longname = "user management new password 1";
82  arg_ainfo.multiplechar = true;
83  arg_ainfo.multiplevalue = false;
84  arg_ainfo.defaultstatus = cgiarginfo::weak;
85  arg_ainfo.argdefault = g_EmptyText;
86  arg_ainfo.savedarginfo = cgiarginfo::mustnot;
87  argsinfo.addarginfo (NULL, arg_ainfo);
88
89  // "umnpw2"
90  arg_ainfo.shortname = "umnpw2";
91  arg_ainfo.longname = "user management new password 2";
92  arg_ainfo.multiplechar = true;
93  arg_ainfo.multiplevalue = false;
94  arg_ainfo.defaultstatus = cgiarginfo::weak;
95  arg_ainfo.argdefault = g_EmptyText;
96  arg_ainfo.savedarginfo = cgiarginfo::mustnot;
97  argsinfo.addarginfo (NULL, arg_ainfo);
98
99  // "umus"
100  arg_ainfo.shortname = "umus";
101  arg_ainfo.longname = "user management account status";
102  arg_ainfo.multiplechar = true;
103  arg_ainfo.multiplevalue = false;
104  arg_ainfo.defaultstatus = cgiarginfo::weak;
105  arg_ainfo.argdefault = g_EmptyText;
106  arg_ainfo.savedarginfo = cgiarginfo::mustnot;
107  argsinfo.addarginfo (NULL, arg_ainfo);
108
109  // "umug"
110  arg_ainfo.shortname = "umug";
111  arg_ainfo.longname = "user management groups"; // comma seperated list
112  arg_ainfo.multiplechar = true;
113  arg_ainfo.multiplevalue = false;
114  arg_ainfo.defaultstatus = cgiarginfo::weak;
115  arg_ainfo.argdefault = g_EmptyText;
116  arg_ainfo.savedarginfo = cgiarginfo::mustnot;
117  argsinfo.addarginfo (NULL, arg_ainfo);
118
119  // "umc"
120  arg_ainfo.shortname = "umc";
121  arg_ainfo.longname = "user management comment";
122  arg_ainfo.multiplechar = true;
123  arg_ainfo.multiplevalue = false;
124  arg_ainfo.defaultstatus = cgiarginfo::weak;
125  arg_ainfo.argdefault = g_EmptyText;
126  arg_ainfo.savedarginfo = cgiarginfo::mustnot;
127  argsinfo.addarginfo (NULL, arg_ainfo);
128
129  // "bcp"
130  arg_ainfo.shortname = "bcp";
131  arg_ainfo.longname = "change password submit button";
132  arg_ainfo.multiplechar = true;
133  arg_ainfo.multiplevalue = false;
134  arg_ainfo.defaultstatus = cgiarginfo::weak;
135  arg_ainfo.argdefault = g_EmptyText;
136  arg_ainfo.savedarginfo = cgiarginfo::mustnot;
137  argsinfo.addarginfo (NULL, arg_ainfo);
138
139  // "beu"
140  arg_ainfo.shortname = "beu";
141  arg_ainfo.longname = "edit user submit button";
142  arg_ainfo.multiplechar = true;
143  arg_ainfo.multiplevalue = false;
144  arg_ainfo.defaultstatus = cgiarginfo::weak;
145  arg_ainfo.argdefault = g_EmptyText;
146  arg_ainfo.savedarginfo = cgiarginfo::mustnot;
147  argsinfo.addarginfo (NULL, arg_ainfo);
148
149  // "cm"
150  arg_ainfo.shortname = "cm";
151  arg_ainfo.longname = "confirm an action";
152  arg_ainfo.multiplechar = true;
153  arg_ainfo.multiplevalue = false;
154  arg_ainfo.defaultstatus = cgiarginfo::weak;
155  arg_ainfo.argdefault = g_EmptyText;
156  arg_ainfo.savedarginfo = cgiarginfo::mustnot;
157  argsinfo.addarginfo (NULL, arg_ainfo);
158}
159
160void usersaction::configure (const text_t &key, const text_tarray &cfgline) {
161  action::configure (key, cfgline);
162}
163
164bool usersaction::init (ostream &logout) {
165
166  if (dbhome.empty()) {
167    logout << "ERROR (usersaction::init) dbhome is not set\n";
168    return false;
169  }
170
171  return action::init (logout);
172}
173
174bool usersaction::check_cgiargs (cgiargsinfoclass &/*argsinfo*/, cgiargsclass &args,
175                 recptprotolistclass * /*protos*/, ostream &/*logout*/) {
176  args["uan"] = "1"; // user authentication is needed
177
178  if (args["uma"] == "changepasswd") {
179    // no particular group is needed to change a password
180    args["ug"].clear();
181  } else {
182    // administrator is needed for all other management tasks
183    args["ug"] = "administrator";
184  }
185 
186  return true;
187}
188
189void usersaction::get_cgihead_info (cgiargsclass &/*args*/, recptprotolistclass * /*protos*/,
190                    response_t &response, text_t &response_data,
191                    ostream &/*logout*/) {
192  response = content;
193  response_data = "text/html";
194}
195
196bool usersaction::do_action (cgiargsclass &args, recptprotolistclass * /*protos*/,
197                 browsermapclass * /*browsers*/, displayclass &disp,
198                 outconvertclass &outconvert, ostream &textout,
199                 ostream &logout) {
200
201  if (args["uma"] == "adduser" || args["uma"] == "edituser") {
202    // adduser is handled by edituser
203    return do_edituser (args, disp, outconvert, textout, logout);
204   
205  } else if (args["uma"] == "deleteuser") {
206    return do_deleteuser (args, disp, outconvert, textout, logout);
207   
208  } else if (args["uma"] == "changepasswd") {
209    return do_changepasswd (args, disp, outconvert, textout, logout); 
210  }
211
212  // default
213  return do_listusers (args, disp, outconvert, textout, logout);
214}
215
216bool usersaction::do_listusers (cgiargsclass &/*args*/, displayclass &disp,
217                outconvertclass &outconvert, ostream &textout,
218                ostream &/*logout*/) {
219
220  textout << outconvert << disp
221      << "_userslistusers:header_\n_userslistusers:contentstart_\n";
222
223  text_tarray userlist;
224  // get user list
225  user_database->get_user_list (userlist);
226
227  // sort the list
228  sort(userlist.begin(), userlist.end());
229 
230  // output the information for each user
231  userinfo_t userinfo;
232  text_tarray::iterator users_here = userlist.begin();
233  text_tarray::iterator users_end = userlist.end();
234  while (users_here != users_end) {
235    if (user_database->get_user_info(*users_here, userinfo) == ERRNO_SUCCEED) {
236      textout << outconvert << disp
237          << "<tr><td bgcolor=\"\\#eeeeee\">" << encodeForHTML(userinfo.username) << "</td>\n"
238              << "<td bgcolor=\"\\#eeeeee\">" << (char *) (userinfo.enabled ? "enabled" : "disabled") << "</td>\n"
239          << "<td bgcolor=\"\\#eeeeee\">" << encodeForHTML(userinfo.groups) << "&nbsp;</td>\n"
240          << "<td bgcolor=\"\\#eeeeee\">" << encodeForHTML(userinfo.comment) << "&nbsp;</td>\n"
241          << "<td><a href=\"_httpcurrentdocument_&a=um&uma=edituser&umun="
242          << encodeForHTML(userinfo.username) << "\">_userslistusers:textedituser_</a> "
243          << "<a href=\"_httpcurrentdocument_&a=um&uma=deleteuser&umun="
244          << encodeForHTML(userinfo.username) << "\">_userslistusers:textdeleteuser_</a>"
245          << "</td></tr>\n\n";
246
247    } else {
248      textout << outconvert << disp
249          << "<tr><td bgcolor=\"\\#eeeeee\">" << *users_here << "</td>\n"
250          << "<td bgcolor=\"\\#eeeeee\">&nbsp;</td>\n"
251          << "<td bgcolor=\"\\#eeeeee\">&nbsp;</td>\n"
252          << "<td bgcolor=\"\\#eeeeee\">&nbsp;</td>\n"
253          << "<td>&nbsp;</td></tr>\n\n";
254    }
255   
256    ++users_here;
257  }
258 
259  textout << outconvert << disp
260      << "_userslistusers:contentend_\n_userslistusers:footer_\n";
261  return true;
262}
263
264void usersaction::define_user_macros (cgiargsclass &args, displayclass &disp) {
265  disp.setmacro ("usersargun", "users", args["umun"]);
266  disp.setmacro ("usersargpw", "users", args["umpw"]);
267  disp.setmacro ("usersargus", "users", args["umus"]);
268  disp.setmacro ("usersargug", "users", args["umug"]);
269  disp.setmacro ("usersargc", "users", args["umc"]);
270}
271
272
273bool usersaction::do_edituser (cgiargsclass &args, displayclass &disp,
274                   outconvertclass &outconvert, ostream &textout,
275                   ostream &logout) {
276
277  userinfo_t userinfo;
278  text_t messagestatus;
279  bool noproblems = true;
280 
281  // fill in defaults from user database (if appropriate)
282  if (args["umun"].empty()) {
283    noproblems = false;
284   
285  } else if (!userdbclass::username_ok (args["umun"])) {
286    // problem with username
287    noproblems = false;
288    messagestatus += "_users:messageinvalidusername_";
289   
290  } else if (user_database->get_user_info (args["umun"], userinfo) == ERRNO_SUCCEED) {
291    if (args["uma"] == "adduser") {
292      // must not add a user that has the same name as another user
293      noproblems = false;
294      messagestatus += "_users:messageuserexists_";
295     
296    } else {
297      // only fill in the data if there is no user status defined
298      if (args["umus"].empty()) {
299    args["umus"] = userinfo.enabled ? "enabled" : "disabled";
300    if (args["umug"].empty()) args["umug"] = userinfo.groups;
301    if (args["umc"].empty()) args["umc"] = userinfo.comment;
302      }
303    }
304  }
305
306  // fill in the user status default
307  if (args["umus"].empty()) {
308    noproblems = false;
309    args["umus"] = "enabled";
310  }
311 
312  // make sure the password is ok
313  if (args["umpw"].empty()) {
314    // password must not be empty if none were supplied from database
315    // and we have had no other problems
316    if (userinfo.password.empty() && noproblems) {
317      noproblems = false;
318      messagestatus += "_users:messageemptypassword_";
319    }
320   
321  } else if (!userdbclass::password_ok(args["umpw"])) {
322    noproblems = false;
323    messagestatus += "_users:messageinvalidpassword_";
324  }
325
326  // set this info if no problems have been encounted
327  // and the submit button was pressed
328  if (noproblems && !args["beu"].empty()) {
329    userinfo.username = args["umun"];
330    if (!args["umpw"].empty()) {
331      // only set the password if it is not empty
332      userinfo.password = userdbclass::crypt_text(args["umpw"]);
333    }
334    userinfo.enabled = (args["umus"] == "enabled");   
335    userinfo.groups = userdbclass::format_user_groups(args["umug"]);
336    userinfo.comment = args["umc"];
337   
338    user_database->set_user_info (args["umun"], userinfo);
339   
340    // show list of users
341    return do_listusers (args, disp, outconvert, textout, logout);
342  }
343 
344  // define the macros for the user
345  define_user_macros (args, disp);
346  disp.setmacro ("messagestatus", "users", messagestatus);
347 
348  textout << outconvert << disp
349      << "_usersedituser:header_\n_usersedituser:content_\n_usersedituser:footer_\n";
350
351  return true;
352}
353
354bool usersaction::do_deleteuser (cgiargsclass &args, displayclass &disp,
355                 outconvertclass &outconvert, ostream &textout,
356                 ostream &logout) {
357  if (!args["cm"].empty()) {
358    if (args["cm"] == "yes" && !args["umun"].empty()) {
359      // user confirmed the deletion of the user
360      user_database->delete_user(args["umun"]);
361    }
362   
363    // redirect the user back to the listusers page
364    return do_listusers (args, disp, outconvert, textout, logout);
365  }
366
367  define_user_macros (args, disp);
368  textout << outconvert << disp
369      << "_usersdeleteuser:header_\n_usersdeleteuser:content_\n_usersdeleteuser:footer_\n";
370 
371  return true;
372}
373
374bool usersaction::do_changepasswd (cgiargsclass &args, displayclass &disp,
375                   outconvertclass &outconvert, ostream &textout,
376                   ostream &/*logout*/) {
377  text_t messagestatus;
378 
379  if (!args["bcp"].empty()) {
380    if (args["un"].empty()) {
381      messagestatus = "_users:messageusernameempty_";
382    } else if (args["umpw"].empty()) {
383      messagestatus = "_users:messagepasswordempty_";
384    } else if (args["umnpw1"].empty()) {
385      messagestatus = "_users:messagenewpass1empty_";
386    } else if (args["umnpw2"].empty()) {
387      messagestatus = "_users:messagenewpass2empty_";
388    } else if (args["umnpw1"] != args["umnpw2"]) {
389      messagestatus = "_users:messagenewpassmismatch_";
390    } else if (!userdbclass::password_ok(args["umnpw1"])) {
391      messagestatus = "_users:messageinvalidpassword_";
392    } else {
393      userinfo_t userinfo;
394      if (user_database->get_user_info (args["un"], userinfo) == ERRNO_SUCCEED) {
395    // check old password
396    if (userinfo.password != userdbclass::crypt_text(args["umpw"])) {
397      messagestatus = "_users:messagefailed_";
398     
399    } else {
400      userinfo.password = userdbclass::crypt_text(args["umnpw1"]);
401      if (user_database->set_user_info (args["un"], userinfo) == ERRNO_SUCCEED) {
402        // everything is ok
403        textout << outconvert << disp
404            << "_userschangepasswdok:header_\n"
405          "_userschangepasswdok:content_\n"
406          "_userschangepasswdok:footer_\n";
407        return true;
408      }
409    }
410      }
411    }
412  }
413
414  disp.setmacro ("messagestatus", "users", messagestatus);
415
416  textout << outconvert << disp
417      << "_userschangepasswd:header_\n"
418    "_userschangepasswd:content_\n"
419    "_userschangepasswd:footer_\n";
420
421  return true;
422}
423
424#endif //GSDL_USE_USERS_ACTION
Note: See TracBrowser for help on using the browser.