source: main/trunk/greenstone2/runtime-src/src/recpt/usersaction.cpp@ 24306

Last change on this file since 24306 was 22984, checked in by ak19, 14 years ago
  1. Undoing commit of 22934 where decode_commas was called on stem and fold comma separated list: previously separated due to url-encoding of commas. Now that the problem has been fixed at the source, the decode_commas hack is no longer necessary. 2. Commas in stem and fold are no longer url-encoded because the multiple_value field of the continuously-reused struct arg_ainfo is always set back to the default false after ever being set to true. So it no longer subtly stays at true to affect Greenstone functioning in unforeseen ways (such as suddenly and unnecessarily URL-encoding commas where this is not wanted).
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 14.0 KB
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\">" << userinfo.username << "</td>\n"
238 << "<td bgcolor=\"\\#eeeeee\">" << (char *) (userinfo.enabled ? "enabled" : "disabled") << "</td>\n"
239 << "<td bgcolor=\"\\#eeeeee\">" << userinfo.groups << "&nbsp;</td>\n"
240 << "<td bgcolor=\"\\#eeeeee\">" << userinfo.comment << "&nbsp;</td>\n"
241 << "<td><a href=\"_httpcurrentdocument_&a=um&uma=edituser&umun="
242 << userinfo.username << "\">_userslistusers:textedituser_</a> "
243 << "<a href=\"_httpcurrentdocument_&a=um&uma=deleteuser&umun="
244 << 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 repository browser.