source: trunk/gsdl/src/recpt/langaction.cpp@ 4290

Last change on this file since 4290 was 4233, checked in by jrm21, 21 years ago

print out better error messages when one of the perl scripts goes wrong,
rather than the default "oops..." message which is very uninformative

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 16.6 KB
Line 
1 /**********************************************************************
2 *
3 * langaction.cpp --
4 * Copyright (C) 1999 The New Zealand Digital Library Project
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
27#include <ctype.h>
28#include <stdio.h>
29#include <fstream.h>
30#include <unistd.h>
31#include "langaction.h"
32#include "fileutil.h"
33#include "gsdltimes.h"
34#include "gsdltools.h"
35#include "gsdlunicode.h"
36#include "langdb.h"
37#include "receptionist.h"
38#include "errno.h"
39#include <sys/utsname.h>
40
41
42/*====================*
43 * GLOBAL DEFINITIONS *
44 *====================*/
45
46// text file reading buffer
47const int LINESIZE = 1024;
48
49
50/*========================*
51 * LOCAL UTILITY ROUTINES *
52 *========================*/
53
54bool text_t_substring (text_t &text, text_t &substr)
55{
56 int SIZE = substr.size();
57
58 if (text.size() >= SIZE) {
59 if (substr <= text) {
60 if (text[0] == substr[0]) {
61 text_t temp = "";
62 // copy first SIZE elements of 'text' into 'temp'
63 for (int size = 0; size < SIZE; size++) {
64 temp.push_back(text[size]);
65 }
66 if (temp == substr)
67 return true;
68 }
69 }
70 }
71
72 return false;
73}
74
75
76/*====================*
77 * CLASS DEFINITIONS *
78 *====================*/
79
80langaction::langaction () {
81
82 package = "";
83
84 cgiarginfo arg_ainfo;
85
86 arg_ainfo.shortname = "l";
87 arg_ainfo.longname = "interface language";
88 arg_ainfo.multiplechar = true;
89 arg_ainfo.defaultstatus = cgiarginfo::weak;
90 arg_ainfo.argdefault = "en";
91 arg_ainfo.savedarginfo = cgiarginfo::must;
92 argsinfo.addarginfo (&cerr, arg_ainfo);
93
94 arg_ainfo.shortname = "bl";
95 arg_ainfo.longname = "base language";
96 arg_ainfo.multiplechar = true;
97 arg_ainfo.defaultstatus = cgiarginfo::weak;
98 arg_ainfo.argdefault = "english";
99 arg_ainfo.savedarginfo = cgiarginfo::must;
100 argsinfo.addarginfo (&cerr, arg_ainfo);
101
102 arg_ainfo.shortname = "tlng";
103 arg_ainfo.longname = "translation language";
104 arg_ainfo.multiplechar = true;
105 arg_ainfo.defaultstatus = cgiarginfo::weak;
106 arg_ainfo.argdefault = "french";
107 arg_ainfo.savedarginfo = cgiarginfo::must;
108 argsinfo.addarginfo (&cerr, arg_ainfo);
109}
110
111
112langaction::~langaction () {
113 // Nothing to do in destructor
114}
115
116
117// set_navbarmacros sets _navigationbar_ and _httpbrowseXXX_ macros
118// reponse contains 1 metadata field (Title)
119bool langaction::init (ostream & /*logout*/)
120{
121 // set up GSDLOS, GSDLHOME and PATH environment variables
122 text_t gsdlos, path;
123 unsigned int path_separator = ':';
124#if defined (__WIN32__)
125 gsdlos = "windows";
126 path_separator = ';';
127
128 path = filename_cat (gsdlhome, "bin", "windows", "perl", "bin;");
129
130#else
131 struct utsname *buf = new struct utsname();
132 int i = uname (buf);
133 if (i == -1) gsdlos = "linux"; // uname failed
134 else gsdlos.setcstr (buf->sysname);
135 delete buf;
136 lc (gsdlos);
137#endif
138
139 pathc = getenv ("PATH");
140 path += filename_cat (gsdlhome, "bin", gsdlos);
141 path.push_back (path_separator);
142 path += filename_cat (gsdlhome, "bin", "script");
143 if (pathc != NULL) {
144 path.push_back (path_separator);
145 path += pathc;
146 }
147 path = "PATH=" + path;
148
149 gsdlos = "GSDLOS=" + gsdlos;
150 text_t setgsdlhome = "GSDLHOME=" + gsdlhome;
151
152 // these will be cleaned up in the destructor
153 gsdlosc = gsdlos.getcstr();
154 gsdlhomec = setgsdlhome.getcstr();
155 pathc = path.getcstr();
156
157 putenv (gsdlosc);
158 putenv (gsdlhomec);
159 putenv (pathc);
160
161 return true;
162}
163
164
165bool langaction::check_cgiargs (cgiargsinfoclass &/*argsinfo*/, cgiargsclass &args,
166 recptprotolistclass* /*protos*/, ostream &logout)
167{
168 // Authenticate the user before allowing modifications
169 args["uan"] = 1;
170 args["ug"] = "langadmin";
171 return true;
172}
173
174
175void langaction::get_cgihead_info (cgiargsclass &/*args*/, recptprotolistclass* /*protos*/,
176 response_t &response, text_t &response_data,
177 ostream &logout)
178{
179 response = content;
180 response_data = "text/html";
181}
182
183
184void langaction::define_internal_macros (displayclass &disp, cgiargsclass &args,
185 recptprotolistclass *protos, ostream &logout)
186{
187 text_t text = "";
188 text_t cmd = "";
189 text_t dir = filename_cat(gsdlhome, "tmp", "lang");
190 text_t page = "";
191 text_t sourcelang = "";
192 text_t targetlang = "";
193
194 // Get the source language from the CGI arguments
195 if (args["bl"] != "") {
196 sourcelang = args["bl"];
197 }
198
199 // Get the target language from the CGI arguments
200 if (args["ownchoice"] != "") {
201 targetlang = args["ownchoice"];
202 }
203 else if (args["language"] != "") {
204 targetlang = args["language"];
205 }
206 else if (args["tlng"] != "") {
207 targetlang = args["tlng"];
208 }
209
210 // Case fold both languages
211 for (int i = 0; i < strlen(sourcelang.getcstr()); i++) {
212 sourcelang[i] = tolower(sourcelang[i]);
213 }
214 for (int i = 0; i < strlen(targetlang.getcstr()); i++) {
215 targetlang[i] = tolower(targetlang[i]);
216 }
217
218 // overwrite the global content (which should be overwritten by package)
219 // makes it obvious that package macros aren't defined, compared to "oops..."
220 disp.setmacro("content", "Global", "\\_translang:content\\_");
221
222 // Make sure the source and target languages are different!
223 if (sourcelang == targetlang) {
224 logout << "Same language!" << endl;
225 args["p"] = "translang";
226 page = "picklanguage";
227 define_webpage(disp, sourcelang, targetlang, dir, page, -1, true, logout);
228 return;
229 }
230
231 // logout << "Source lang: " << sourcelang << " Target lang: " << targetlang << endl;
232 text_t translation = sourcelang + "-" + targetlang;
233 logout << "Translation: " << translation << endl;
234 text_t trans_dir = filename_cat(dir, translation);
235
236 // argument for page is of the form 'macrofile_pageno' so
237 // we need to split the argument to get the proper page content
238 text_t &arg_p = args["p"];
239 text_tarray splitarray;
240 splitchar(arg_p.begin(), arg_p.end(), '_', splitarray);
241
242 arg_p = splitarray[0];
243 if (splitarray.size() > 1)
244 page = splitarray[splitarray.size()-1];
245
246 //if are entering page from macro search
247 if (args["macroname"] != "") {
248 text_t macroname = args["macroname"];
249
250 // !! TO DO !!
251 cmd = "perl " + filename_cat(gsdlhome, "bin", "script", "fromsearch.pl") + " " + sourcelang + " " + targetlang + " " + macroname;
252 logout << "COMMAND: " << cmd <<endl;
253
254 if ((gsdl_system(cmd, true, logout)) != 0) {
255 logout << "Process " << cmd << " did not execute.../;-D\n";
256 return;
257 }
258
259 define_webpage(disp, sourcelang, targetlang, trans_dir, page, -1, false, logout);
260 return;
261 }
262
263 if (page == "fromsearch")
264 page = "thankyou";
265
266 if (page == "picklanguage") {
267 page = "1";
268
269 //calls the translator file to create HTML files
270 cmd = "perl " + filename_cat(gsdlhome, "bin", "script", "translator.pl") + " " + sourcelang + " " + targetlang;
271 int ret=gsdl_system(cmd, true, logout);
272 if (ret != 0) {
273 ret = ret >> 8;
274 text_t errmsg="<H1>Error</H1>\nrunning translator.pl: ";
275 if (ret==1) errmsg += "GSDLHOME unset";
276 else if (ret==2) errmsg += "missing arguments";
277 else if (ret==3) errmsg += "translation not yet initialised";
278 else if (ret==4) errmsg += "no source macro found";
279 errmsg+= " (error " + text_t(ret) + ")\n";
280 disp.setmacro("content", "translang", errmsg);
281 logout << "Process " << cmd << " did not execute.../;-D\n";
282 return;
283 }
284
285 const recptconf &rcinfo = recpt->get_configinfo();
286
287 // Use sendmail.pl perl script to send email events
288 text_t tmpmailfile = filename_cat (gsdlhome, "tmp", "lang", "email.txt");
289 char *tmpmailfilec = tmpmailfile.getcstr();
290 ofstream tmpfile (tmpmailfilec);
291 if (tmpfile) {
292 tmpfile << "[Translator Event]\n"
293 << "Date: " << get_date (true) << "\n"
294 << "Greenstone Username: " << args["un"] << "\n";
295 tmpfile << "The " << targetlang << " language translation was entered.\n";
296 tmpfile.close();
297
298 text_t sendmail_cmd = "perl -S sendmail.pl";
299 sendmail_cmd += " -to \"" + rcinfo.maintainer + "\"";
300 sendmail_cmd += " -from \"[email protected]\"";
301 sendmail_cmd += " -smtp \"" + rcinfo.MailServer + "\"";
302 sendmail_cmd += " -subject \"Greenstone Translator Event\"";
303 sendmail_cmd += " -msgfile \"" + tmpmailfile + "\"";
304 // logout << "Sendmail command: " << sendmail_cmd << endl;
305 gsdl_system (sendmail_cmd, true, logout);
306 unlink(tmpmailfilec);
307 }
308 else {
309 logout << "translatoraction:: ERROR: Couldn't open "
310 << "temporary event log file " << tmpmailfile << " for email event.\n";
311 }
312 delete tmpmailfilec;
313 }
314
315 //generates the picklanguage page
316 if (page.empty()) {
317 page = "picklanguage";
318 cmd = "perl " + filename_cat(gsdlhome, "bin", "script", "picklanguage.pl");
319 logout << cmd << endl;
320 int ret=gsdl_system(cmd,true,logout);
321 if (ret != 0) { // determine error
322 /*
323 // ret=-1 => we couldn't run the script.
324 // ret=1 => GSDLHOME not set.
325 // >=2 implies some file IO error:
326 // ret=2 => can't read etc/main.cfg
327 // ret=3 => "can't create directory $GSDLHOME/tmp/lang/
328 // ret=4 => can't write $dir/picklanguage.lang
329 **/
330 // maybe this should be a "real" macro for translation?!
331 text_t errmsg="<H1>Error</H1>\nPermissions problem: picklanguage.pl failed ";
332
333 ret = ret >> 8; // man perlfunc for the reason for this
334 if (ret==255) errmsg+="running script";
335 else if (ret==1) errmsg+="GSDLHOME not set";
336 else if (ret==2) errmsg+="reading etc/main.cfg";
337 else if (ret==3) errmsg+="creating tmp/lang/";
338 else if (ret==4) errmsg+="writing picklanguage.lang";
339 errmsg += " (error="; errmsg += text_t(ret); errmsg += ")";
340 disp.setmacro("content", "translang", errmsg);
341
342 return;
343 }
344 define_webpage(disp, sourcelang, targetlang, dir, page, -1, false, logout);
345 return;
346 }
347
348 // Read the number of translation pages from numpages.log
349 text_t numpagesfilepath = filename_cat(trans_dir, "numpages.log");
350 ifstream numpagesfile(numpagesfilepath.getcstr(), ios::in);
351
352 // Check file opened OK
353 if (!numpagesfile) {
354 text_t errmsg="Error: File " + numpagesfilepath + " could not be opened.";
355 logout << errmsg << endl;
356 disp.setmacro("content", "translang", errmsg);
357 return;
358 }
359
360 // Read the number of pages from the file
361 int numpages;
362 char line[LINESIZE];
363 if (numpagesfile.getline(line, LINESIZE-1)) {
364 numpages = atoi(line);
365 }
366 numpagesfile.close();
367
368 // if (pagenos.empty() && pageno == "")
369 if (numpages == 0)
370 page = "thankyou";
371
372 text_t &submitargs = args[page];
373 text_t submit = "SUBMIT TRANSLATION";
374
375 //if the SUBMIT TRANSLATION >> button has been pushed
376 if (text_t_substring(submitargs,submit)) {
377 //creates output stream to argsfile
378 text_t argsfile = filename_cat(trans_dir, "arguments.arg");
379 logout << "Argsfile: " << argsfile << endl;
380 write_args_file(args, argsfile, logout);
381
382 //create the command line for submitting the translation
383 cmd = "perl " + filename_cat(gsdlhome, "bin", "script", "submit_translation.pl") + " ";
384 cmd += (sourcelang + " " + targetlang + " " + "arguments.arg");
385
386 //give command to system to execute submission of translation
387 if((gsdl_system(cmd, true, logout)) != 0)
388 logout << "Process " << cmd << " did not execute\n";
389
390 //increments which page is displayed when translation is submitted
391 int pageno = atoi(page.getcstr());
392 if (pageno >= numpages)
393 page = "thankyou";
394 else
395 page = (pageno + 1);
396 }
397
398 define_webpage(disp, sourcelang, targetlang, trans_dir, page, numpages, false, logout);
399}
400
401
402void langaction::write_args_file (cgiargsclass &args, text_t argsfile, ostream &logout)
403{
404 ofstream argsout(argsfile.getcstr(), ios::out);
405
406 // Informs user and returns if output stream not opened
407 if (!argsout) {
408 logout << "Error: File " << argsfile << " could not be opened." << endl;
409 return;
410 }
411
412 // Make the file world writable
413 text_t changemode = "chmod a+w " + argsfile;
414 gsdl_system(changemode, false, logout);
415
416 // Write out the cgiargsclass variable to the argsout file
417 argsout << args;
418 argsout.close();
419}
420
421
422void langaction::define_webpage (displayclass &disp, text_t sourcelang, text_t targetlang,
423 text_t dir, text_t page, int numpages, bool error,
424 ostream &logout)
425{
426 // produces HTML page with the current pages contents
427 // formfile is the file that contains web-form for the
428 // current package whose name is stored in 'package'
429
430 text_t formfile = filename_cat(dir, page + ".lang");
431 ifstream readfile(formfile.getcstr(), ios::in);
432 if (!readfile) {
433 logout << "File " << formfile << " could not be found.\n";
434 return;
435 }
436
437
438 /* ============================ START WEB-FORM HTML CODE ============================ */
439 text_t text = "";
440 text += "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"></head><body>\n";
441
442 text += "<input type=hidden name=\"a\" value=\"lang\">\n";
443 text += "<input type=hidden name=\"p\" value=\"translang_" + page + "\">\n";
444 text += "<input type=hidden name=\"e\" value=\"_decodedcompressedoptions_\">\n";
445
446 text += "_texttranshead_";
447
448 // If not a special case page display "Page x of y" and Next button
449 if ((page != "thankyou") && (page != "picklanguage") && (page != "fromsearch")) {
450 text += "<center><strong>";
451 text += " _textcurrpage_ " + page + " _textof_ " + numpages;
452 text += "</strong>";
453
454 int pageno = atoi(page.getcstr());
455 text += " <a href=\"_gwcgi_?e=_compressedoptions_&a=lang&p=translang_";
456 if (pageno >= numpages)
457 text += "thankyou";
458 else
459 text += (pageno + 1);
460 text += "&baselanguage=" + sourcelang;
461 text += "&language=" + targetlang;
462 text += "\">";
463 text += "<strong>NEXT>></strong></a></center>\n";
464 }
465
466 // Read in HTML from file
467 char line[LINESIZE];
468 while (readfile.getline(line, LINESIZE-1)) {
469 text_t temp = line;
470 text += temp + "\n";
471 }
472 readfile.close();
473
474 if (page == "picklanguage" && error) {
475 text += "<center><strong>_textchoosedifferent_</strong></center>";
476 }
477
478 // If not a special case page display "Page x of y" and Next button
479 if ((page != "thankyou") && (page != "picklanguage") && (page != "fromsearch")) {
480 text += "<center><strong>";
481 text += " _textcurrpage_ " + page + " _textof_ " + numpages;
482 text += "</strong>";
483
484 int pageno = atoi(page.getcstr());
485 text += " <a href=\"_gwcgi_?e=_compressedoptions_&a=lang&p=translang_";
486 if (pageno >= numpages)
487 text += "thankyou";
488 else
489 text += (pageno + 1);
490 text += "&baselanguage=" + sourcelang;
491 text += "&language=" + targetlang;
492 text += "\">";
493 text += "<strong>NEXT>></strong></a></center>\n";
494 }
495
496 if (page == "fromsearch")
497 text += "<center><strong> _textcurrpage_ 1 _textof_ 1</strong><br>\n";
498
499 text += "</body></html>\n";
500
501
502 /* ============================ END WEB-FORM HTML CODE ============================ */
503
504
505 // THE FOLLOWING MACROS ARE DEFINED IN translang.dm MACRO FILE
506 // set the formcontent as the content of the form-page
507
508 disp.setmacro("formcontent", "translang", text);
509
510 // set the action for the form
511 disp.setmacro("formaction", "translang", "_gwcgi_");
512
513 text_t navigationbar = "<!-- Navigation Bar -->\n";
514 navigationbar += "<table width=\"100%\" cellspacing=0 cellpadding=0>";
515 navigationbar += "<tr valign=top><td rowspan=2 align=left>_imagecollection_</td>";
516 navigationbar += "<td align=right>_javalinks_</td><td>";
517
518 // if (page != "picklanguage") {
519 // navigationbar += "_imageserch_";
520 // }
521 navigationbar += "</td></tr></table>\n</nobr>\n";
522 navigationbar += "<!-- End of Navigation Bar -->\n";
523 disp.setmacro ("navigationbar", "translang", navigationbar);
524}
525
526
527bool langaction::do_action (cgiargsclass &args, recptprotolistclass * /*protos*/,
528 browsermapclass * /*browsers*/, displayclass &disp,
529 outconvertclass &outconvert, ostream &textout,
530 ostream &logout) {
531 text_t &arg_p = args["p"];
532 // logout << "Arg P: " << arg_p << endl;
533
534 outconvertclass text2utf8;
535
536 textout << text2utf8 << disp << ("_" + arg_p + ":header_\n")
537 << ("_" + arg_p + ":content_\n")
538 << ("_" + arg_p + ":footer_\n");
539
540 return true;
541}
Note: See TracBrowser for help on using the repository browser.