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
RevLine 
[3632]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
[4123]26
[4116]27#include <ctype.h>
[3632]28#include <stdio.h>
29#include <fstream.h>
[4123]30#include <unistd.h>
[3632]31#include "langaction.h"
32#include "fileutil.h"
[4123]33#include "gsdltimes.h"
[3632]34#include "gsdltools.h"
35#include "gsdlunicode.h"
36#include "langdb.h"
[3715]37#include "receptionist.h"
[3632]38#include "errno.h"
39#include <sys/utsname.h>
[4123]40
[3632]41
42/*====================*
43 * GLOBAL DEFINITIONS *
44 *====================*/
45
46// text file reading buffer
[4123]47const int LINESIZE = 1024;
[3632]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
[3715]75
[4123]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
[3715]117// set_navbarmacros sets _navigationbar_ and _httpbrowseXXX_ macros
118// reponse contains 1 metadata field (Title)
[4123]119bool langaction::init (ostream & /*logout*/)
120{
[3632]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
[4123]165bool langaction::check_cgiargs (cgiargsinfoclass &/*argsinfo*/, cgiargsclass &args,
166 recptprotolistclass* /*protos*/, ostream &logout)
167{
168 // Authenticate the user before allowing modifications
[4107]169 args["uan"] = 1;
170 args["ug"] = "langadmin";
[3632]171 return true;
172}
173
[4123]174
175void langaction::get_cgihead_info (cgiargsclass &/*args*/, recptprotolistclass* /*protos*/,
176 response_t &response, text_t &response_data,
177 ostream &logout)
178{
[3632]179 response = content;
180 response_data = "text/html";
181}
182
[4123]183
[3632]184void langaction::define_internal_macros (displayclass &disp, cgiargsclass &args,
[4123]185 recptprotolistclass *protos, ostream &logout)
186{
[3632]187 text_t text = "";
188 text_t cmd = "";
189 text_t dir = filename_cat(gsdlhome, "tmp", "lang");
[4123]190 text_t page = "";
191 text_t sourcelang = "";
192 text_t targetlang = "";
[3859]193
[4123]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
[3632]200 if (args["ownchoice"] != "") {
[4123]201 targetlang = args["ownchoice"];
[3632]202 }
[4068]203 else if (args["language"] != "") {
[4123]204 targetlang = args["language"];
[4068]205 }
[3723]206 else if (args["tlng"] != "") {
[4123]207 targetlang = args["tlng"];
[3632]208 }
[3723]209
[4123]210 // Case fold both languages
211 for (int i = 0; i < strlen(sourcelang.getcstr()); i++) {
212 sourcelang[i] = tolower(sourcelang[i]);
[3632]213 }
[4123]214 for (int i = 0; i < strlen(targetlang.getcstr()); i++) {
215 targetlang[i] = tolower(targetlang[i]);
[4116]216 }
217
[4233]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
[4116]222 // Make sure the source and target languages are different!
[4123]223 if (sourcelang == targetlang) {
[4116]224 logout << "Same language!" << endl;
225 args["p"] = "translang";
[4123]226 page = "picklanguage";
227 define_webpage(disp, sourcelang, targetlang, dir, page, -1, true, logout);
[4116]228 return;
229 }
230
[4123]231 // logout << "Source lang: " << sourcelang << " Target lang: " << targetlang << endl;
232 text_t translation = sourcelang + "-" + targetlang;
[4107]233 logout << "Translation: " << translation << endl;
234 text_t trans_dir = filename_cat(dir, translation);
[4068]235
[3715]236 // argument for page is of the form 'macrofile_pageno' so
237 // we need to split the argument to get the proper page content
[4123]238 text_t &arg_p = args["p"];
[3715]239 text_tarray splitarray;
240 splitchar(arg_p.begin(), arg_p.end(), '_', splitarray);
[4123]241
[3715]242 arg_p = splitarray[0];
243 if (splitarray.size() > 1)
[4123]244 page = splitarray[splitarray.size()-1];
[3632]245
[3723]246 //if are entering page from macro search
247 if (args["macroname"] != "") {
[3715]248 text_t macroname = args["macroname"];
[4123]249
250 // !! TO DO !!
251 cmd = "perl " + filename_cat(gsdlhome, "bin", "script", "fromsearch.pl") + " " + sourcelang + " " + targetlang + " " + macroname;
[3859]252 logout << "COMMAND: " << cmd <<endl;
[4123]253
[3715]254 if ((gsdl_system(cmd, true, logout)) != 0) {
[3859]255 logout << "Process " << cmd << " did not execute.../;-D\n";
[3715]256 return;
257 }
[4123]258
259 define_webpage(disp, sourcelang, targetlang, trans_dir, page, -1, false, logout);
[3632]260 return;
261 }
[4107]262
[4123]263 if (page == "fromsearch")
264 page = "thankyou";
[3715]265
[4123]266 if (page == "picklanguage") {
267 page = "1";
268
[3715]269 //calls the translator file to create HTML files
[4123]270 cmd = "perl " + filename_cat(gsdlhome, "bin", "script", "translator.pl") + " " + sourcelang + " " + targetlang;
[4233]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);
[3859]281 logout << "Process " << cmd << " did not execute.../;-D\n";
[3723]282 return;
283 }
[4123]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;
[3715]313 }
314
315 //generates the picklanguage page
[4123]316 if (page.empty()) {
317 page = "picklanguage";
[3715]318 cmd = "perl " + filename_cat(gsdlhome, "bin", "script", "picklanguage.pl");
[4116]319 logout << cmd << endl;
[4233]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
[3715]342 return;
[4233]343 }
[4123]344 define_webpage(disp, sourcelang, targetlang, dir, page, -1, false, logout);
[3715]345 return;
346 }
347
[4123]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) {
[4233]354 text_t errmsg="Error: File " + numpagesfilepath + " could not be opened.";
355 logout << errmsg << endl;
356 disp.setmacro("content", "translang", errmsg);
[4123]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];
[3715]373 text_t submit = "SUBMIT TRANSLATION";
[4123]374
[3632]375 //if the SUBMIT TRANSLATION >> button has been pushed
376 if (text_t_substring(submitargs,submit)) {
[4107]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
[3632]382 //create the command line for submitting the translation
383 cmd = "perl " + filename_cat(gsdlhome, "bin", "script", "submit_translation.pl") + " ";
[4123]384 cmd += (sourcelang + " " + targetlang + " " + "arguments.arg");
[4107]385
[3632]386 //give command to system to execute submission of translation
387 if((gsdl_system(cmd, true, logout)) != 0)
[3859]388 logout << "Process " << cmd << " did not execute\n";
[4107]389
[3632]390 //increments which page is displayed when translation is submitted
[4123]391 int pageno = atoi(page.getcstr());
392 if (pageno >= numpages)
393 page = "thankyou";
394 else
395 page = (pageno + 1);
[3632]396 }
[3715]397
[4123]398 define_webpage(disp, sourcelang, targetlang, trans_dir, page, numpages, false, logout);
[3632]399}
400
[4107]401
402void langaction::write_args_file (cgiargsclass &args, text_t argsfile, ostream &logout)
403{
404 ofstream argsout(argsfile.getcstr(), ios::out);
405
[4123]406 // Informs user and returns if output stream not opened
407 if (!argsout) {
408 logout << "Error: File " << argsfile << " could not be opened." << endl;
[4107]409 return;
410 }
411
[4123]412 // Make the file world writable
413 text_t changemode = "chmod a+w " + argsfile;
[4107]414 gsdl_system(changemode, false, logout);
415
[4123]416 // Write out the cgiargsclass variable to the argsout file
[4107]417 argsout << args;
418 argsout.close();
419}
420
421
[4123]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{
[3632]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
[4123]430 text_t formfile = filename_cat(dir, page + ".lang");
[3632]431 ifstream readfile(formfile.getcstr(), ios::in);
432 if (!readfile) {
[3859]433 logout << "File " << formfile << " could not be found.\n";
[3632]434 return;
435 }
[4107]436
437
[3632]438 /* ============================ START WEB-FORM HTML CODE ============================ */
[4123]439 text_t text = "";
440 text += "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"></head><body>\n";
[3715]441
[4123]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";
[3715]445
[4123]446 text += "_texttranshead_";
[4116]447
[4123]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>";
[4116]453
[4123]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";
[3632]464 }
[4123]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";
[3632]471 }
472 readfile.close();
[4123]473
474 if (page == "picklanguage" && error) {
475 text += "<center><strong>_textchoosedifferent_</strong></center>";
[4116]476 }
477
[4123]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>";
[3715]483
[4123]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";
[3723]494 }
[3715]495
[4123]496 if (page == "fromsearch")
[3723]497 text += "<center><strong> _textcurrpage_ 1 _textof_ 1</strong><br>\n";
[3715]498
[3723]499 text += "</body></html>\n";
500
501
[3715]502 /* ============================ END WEB-FORM HTML CODE ============================ */
[3632]503
504
505 // THE FOLLOWING MACROS ARE DEFINED IN translang.dm MACRO FILE
506 // set the formcontent as the content of the form-page
[4116]507
[3632]508 disp.setmacro("formcontent", "translang", text);
509
510 // set the action for the form
511 disp.setmacro("formaction", "translang", "_gwcgi_");
512
[3715]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>";
[3723]517
[4124]518 // if (page != "picklanguage") {
519 // navigationbar += "_imageserch_";
520 // }
[3723]521 navigationbar += "</td></tr></table>\n</nobr>\n";
[3715]522 navigationbar += "<!-- End of Navigation Bar -->\n";
523 disp.setmacro ("navigationbar", "translang", navigationbar);
[3632]524}
525
[4123]526
[3632]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"];
[4116]532 // logout << "Arg P: " << arg_p << endl;
533
[3723]534 outconvertclass text2utf8;
535
536 textout << text2utf8 << disp << ("_" + arg_p + ":header_\n")
[3632]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.