source: trunk/gsdl/src/recpt/gtiaction.cpp@ 13692

Last change on this file since 13692 was 13692, checked in by mdewsnip, 17 years ago

Finished the Microsoft Excel spreadsheet generation page that I started ages ago.

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 32.6 KB
Line 
1/**********************************************************************
2 *
3 * gtiaction.cpp --
4 * Copyright (C) 2005 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 "gsdl_modules_cfg.h"
28#ifdef GSDL_USE_GTI_ACTION
29
30
31#include <expat.h>
32#include <stdio.h>
33#include <sys/utsname.h>
34#include "gtiaction.h"
35#include "cgiutils.h"
36#include "fileutil.h"
37#include "gsdlunicode.h"
38
39
40
41gtiaction::gtiaction()
42{
43 cgiarginfo arg_ainfo;
44
45 arg_ainfo.shortname = "tlc";
46 arg_ainfo.longname = "translation target language code";
47 arg_ainfo.multiplechar = true;
48 arg_ainfo.defaultstatus = cgiarginfo::weak;
49 arg_ainfo.savedarginfo = cgiarginfo::must;
50 argsinfo.addarginfo (&cerr, arg_ainfo);
51
52 arg_ainfo.shortname = "tfk";
53 arg_ainfo.longname = "translation file key";
54 arg_ainfo.multiplechar = true;
55 arg_ainfo.defaultstatus = cgiarginfo::weak;
56 arg_ainfo.savedarginfo = cgiarginfo::must;
57 argsinfo.addarginfo (&cerr, arg_ainfo);
58
59 arg_ainfo.shortname = "ncpp";
60 arg_ainfo.longname = "number of chunks per page";
61 arg_ainfo.multiplechar = true;
62 arg_ainfo.defaultstatus = cgiarginfo::weak;
63 arg_ainfo.argdefault = "1";
64 arg_ainfo.savedarginfo = cgiarginfo::must;
65 argsinfo.addarginfo (&cerr, arg_ainfo);
66}
67
68
69
70gtiaction::~gtiaction()
71{
72 delete[] set_gsdlhome_cstr;
73 delete[] set_gsdlos_cstr;
74}
75
76
77
78bool gtiaction::init (ostream& /*logout*/)
79{
80 // Set GSDLHOME and GSDLOS environment variables
81 text_t set_gsdlhome = "GSDLHOME=" + gsdlhome;
82 text_t set_gsdlos = "GSDLOS=";
83
84#if defined (__WIN32__)
85 set_gsdlos += "windows";
86#else
87 struct utsname *buf = new struct utsname();
88 if (uname(buf) == -1) {
89 // uname failed, so this must be linux
90 set_gsdlos += "linux";
91 }
92 else {
93 text_t gsdlos = buf->sysname;
94 lc(gsdlos);
95 set_gsdlos += gsdlos;
96 }
97 delete buf;
98#endif
99
100 // These will be cleaned up in the destructor
101 set_gsdlhome_cstr = set_gsdlhome.getcstr();
102 set_gsdlos_cstr = set_gsdlos.getcstr();
103 putenv(set_gsdlhome_cstr);
104 putenv(set_gsdlos_cstr);
105
106 return true;
107}
108
109
110
111bool gtiaction::check_cgiargs(cgiargsinfoclass& /*argsinfo*/, cgiargsclass& args,
112 recptprotolistclass* /*protos*/, ostream& logout)
113{
114 // Authenticate the user, except for the "home" and "lang" pages
115 if (args["p"] != "home" && args["p"] != "lang" && args["p"] != "status") {
116 args["uan"] = 1;
117 args["ug"] = "langadmin_" + args["tlc"];
118 }
119
120 return true;
121}
122
123
124
125bool gtiaction::do_action(cgiargsclass& args, recptprotolistclass* /*protos*/,
126 browsermapclass* /*browsers*/, displayclass& disp,
127 outconvertclass& outconvert, ostream& textout,
128 ostream& logout)
129{
130 // Special case for producing Excel spreadsheets, as these are downloaded
131 if (args["p"] == "excel") {
132 return produce_excel_spreadsheet(args, logout);
133 }
134
135 textout << outconvert << disp << ("_gti:header_\n") << ("_gti:content_\n") << ("_gti:footer_\n");
136 return true;
137}
138
139
140
141void gtiaction::get_cgihead_info(cgiargsclass& args, recptprotolistclass* /*protos*/,
142 response_t& response, text_t& response_data,
143 ostream& logout)
144{
145 // Special case for producing Excel spreadsheets, as these are downloaded
146 if (args["p"] == "excel") {
147 printf("Content-Disposition: attachment; filename=\"Greenstone-%s-%s.xml\"\n", args["tlc"].getcstr(), args["tfk"].getcstr());
148 response = content;
149 response_data = "text/xml";
150 return;
151 }
152
153 response = content;
154 response_data = "text/html";
155}
156
157
158
159void gtiaction::define_internal_macros(displayclass& disp, cgiargsclass& args,
160 recptprotolistclass* protos, ostream& logout)
161{
162 // logout << endl << "Arguments: " << args << endl;
163 logout << endl << "CGI arg p: " << args["p"] << endl;
164
165 // For some reason this must be done as well as setting the macro in gti.dm
166 // is that still true??
167 disp.setmacro("preflink", displayclass::defaultpackage, "_gti:preflink_");
168
169 // Define the page content for the GTI home page
170 if (args["p"] == "home") {
171 define_gti_home_page(disp, args, logout);
172 return;
173 }
174
175 // Define the page content for the GTI language page
176 if (args["p"] == "lang") {
177 define_gti_lang_page(disp, args, logout);
178 return;
179 }
180
181 // Define the page content for the GTI search page
182 if (args["p"] == "find") {
183 define_gti_find_page(disp, args, logout);
184 return;
185 }
186
187 // Define the page content for the GTI offline page
188 if (args["p"] == "offline") {
189 define_gti_offline_page(disp, args, logout);
190 return;
191 }
192
193 // Define the page content for the GTI view status page
194 if (args["p"] == "status") {
195 define_gti_status_page(disp, args, logout);
196 return;
197 }
198
199 // Process user translations
200 if (args["p"] == "submit") {
201 process_gti_submissions(disp, args, logout, true);
202 }
203
204 // Define the page content for the GTI core pages (containing the translation input forms)
205 define_gti_core_page(disp, args, logout);
206}
207
208
209
210void gtiaction::define_gti_home_page(displayclass& disp, cgiargsclass& args, ostream& logout)
211{
212 disp.setmacro("gtiformcontent", "gti", "_gti:gtihome_");
213
214 languageinfo_tmap loaded_languages = recpt->get_configinfo().languages;
215
216 // Get the languages specified in the main.cfg file, and put them into a map to sort by name
217 text_tmap gti_languages_name_code_mapping;
218 languageinfo_tmap::const_iterator loaded_language = loaded_languages.begin();
219 while (loaded_language != loaded_languages.end()) {
220 // English is not a valid GTI target language, since it is the source language
221 if (loaded_language->first != "en") {
222 gti_languages_name_code_mapping[loaded_language->second.longname] = loaded_language->first;
223 }
224 ++loaded_language;
225 }
226
227 // Set the gtitlcselection macro
228 text_t gti_tlc_selection = "<select name=\"tlc\">\n";
229 text_tmap::iterator gti_language = gti_languages_name_code_mapping.begin();
230 while (gti_language != gti_languages_name_code_mapping.end()) {
231 gti_tlc_selection += "<option value=\"" + gti_language->second + "\">" + gti_language->first + "</option>\n";
232 ++gti_language;
233 }
234 gti_tlc_selection += "</select>";
235 disp.setmacro("gtitlcselection", "gti", gti_tlc_selection);
236}
237
238
239
240void gtiaction::define_gti_lang_page(displayclass& disp, cgiargsclass& args, ostream& logout)
241{
242 // Get the target language code from the CGI arguments
243 text_t target_language_code = args["tlc"];
244
245 disp.setmacro("gtiformcontent", "gti", "_gti:gtilang_");
246
247 // Send a request to gti.pl to get the valid translation files
248 text_t gti_arguments = "get-language-status " + target_language_code;
249 GTI_Response gti_response = parse_gti_response(do_gti_request(gti_arguments, logout), logout);
250 if (gti_response.error_message != "") {
251 // An error has occurred
252 disp.setmacro("gtiformcontent", "gti", "_gti:gtierror_");
253 disp.setmacro("gtierrormessage", "gti", gti_response.error_message);
254 return;
255 }
256
257 languageinfo_tmap loaded_languages = recpt->get_configinfo().languages;
258 disp.setmacro("gtitargetlanguagename", "gti", loaded_languages[target_language_code].longname);
259
260 // Set the gtitfkselection macro
261 text_t gti_tfk_selection = "<table>";
262 text_tmap::iterator translation_file = gti_response.translation_files_index_to_key_mapping.begin();
263 while (translation_file != gti_response.translation_files_index_to_key_mapping.end()) {
264 text_t translation_file_key = translation_file->second;
265
266 gti_tfk_selection += "<tr><td>";
267 gti_tfk_selection += "<input type=\"radio\" name=\"tfk\" value=\"" + translation_file_key + "\"></td>\n";
268 gti_tfk_selection += "<td>_textgti" + translation_file_key + "_</td></tr>\n";
269
270 text_t num_chunks_translated = gti_response.translation_files_key_to_num_chunks_translated_mapping[translation_file_key];
271 text_t num_chunks_requiring_translation = gti_response.translation_files_key_to_num_chunks_requiring_translation_mapping[translation_file_key];
272 text_t num_chunks_requiring_updating = gti_response.translation_files_key_to_num_chunks_requiring_updating_mapping[translation_file_key];
273 gti_tfk_selection += "<tr><td></td><td>_gtitranslationfilestatus_(" + num_chunks_translated + "," + num_chunks_requiring_translation + "," + num_chunks_requiring_updating + ")</td></tr>\n";
274 ++translation_file;
275 }
276 gti_tfk_selection += "</table>";
277 disp.setmacro("gtitfkselection", "gti", gti_tfk_selection);
278}
279
280
281
282void gtiaction::define_gti_status_page(displayclass& disp, cgiargsclass& args, ostream& logout)
283{
284 disp.setmacro("gtiformcontent", "gti", "_gti:gtistatus_");
285
286 languageinfo_tmap loaded_languages = recpt->get_configinfo().languages;
287
288 // Get the languages specified in the main.cfg file, and put them into a map to sort by name
289 text_tmap gti_languages_name_code_mapping;
290 languageinfo_tmap::const_iterator loaded_language = loaded_languages.begin();
291 while (loaded_language != loaded_languages.end()) {
292 // English is not a valid GTI target language, since it is the source language
293 if (loaded_language->first != "en") {
294 gti_languages_name_code_mapping[loaded_language->second.longname] = loaded_language->first;
295 }
296 ++loaded_language;
297 }
298
299 // Get the languages, for each language, send a request to gti.pl to get the valid translation files and the current status for each file
300 text_t gti_status_table = "<table class=\"status\">\n";
301 text_tmap::iterator gti_language = gti_languages_name_code_mapping.begin();
302 bool first_lang = true;
303 while (gti_language != gti_languages_name_code_mapping.end()) {
304 // Send a request to gti.pl to get the valid translation files
305 text_t gti_arguments = "get-language-status " + gti_language->second;
306 GTI_Response gti_response = parse_gti_response(do_gti_request(gti_arguments, logout), logout);
307 if (gti_response.error_message != "") {
308 // An error has occurred
309 disp.setmacro("gtiformcontent", "gti", "_gti:gtierror_");
310 disp.setmacro("gtierrormessage", "gti", gti_response.error_message);
311 return;
312 }
313
314 text_tmap::iterator translation_file = gti_response.translation_files_index_to_key_mapping.begin();
315
316 text_t lang_status_temp = "<tr><td class=\"first\">" + gti_language->first + "</td>\n";
317 text_t files_temp = "<tr><th class=\"status\">_textgtilanguage_</th>\n";
318 text_t number_of_strings_temp = "<tr><td class=\"first\"><b>_textgtitotalnumberoftranslations_</b></td>\n";
319
320 while (translation_file != gti_response.translation_files_index_to_key_mapping.end()) {
321 text_t translation_file_key = translation_file->second;
322
323 text_t num_chunks_translated = gti_response.translation_files_key_to_num_chunks_translated_mapping[translation_file_key];
324 text_t num_chunks_requiring_translation = gti_response.translation_files_key_to_num_chunks_requiring_translation_mapping[translation_file_key];
325 text_t num_chunks_requiring_updating = gti_response.translation_files_key_to_num_chunks_requiring_updating_mapping[translation_file_key];
326
327 lang_status_temp += "<td class=\"status\">";
328 if(num_chunks_translated.getint() > 0){
329 lang_status_temp += "<div class=\"nowrap\"><div class=\"done\">";
330 lang_status_temp += num_chunks_translated+"</div><div class=\"plus\">+</div><div class=\"update\">";
331 lang_status_temp += num_chunks_requiring_updating+"</div><div class=\"plus\">+</div><div class=\"todo\">";
332 lang_status_temp += num_chunks_requiring_translation+"</div></div>";
333 }
334 lang_status_temp += "</td>\n";
335
336
337 //lang_status_temp += "<td valign=\"top\" nowrap>_gtitranslationfilestatus2_(" + num_chunks_translated + "," + num_chunks_requiring_translation + "," + num_chunks_requiring_updating + ")</td>";
338
339 // List the file names as the first row of the status table
340 // Add up number of strings need to be translate in each file, as the second line of the status table
341 if (first_lang) {
342 files_temp += "<th class=\"status\">_textgti" + translation_file_key + "_</th>\n";
343 int int_number_of_strings = num_chunks_translated.getint() + num_chunks_requiring_translation.getint();
344 number_of_strings_temp += "<td class=\"status\"><b>";
345 number_of_strings_temp.appendint(int_number_of_strings);
346 number_of_strings_temp += "</b></td>\n";
347 }
348 ++translation_file;
349 }
350
351 if(first_lang) {
352 gti_status_table += files_temp + "</tr>" + number_of_strings_temp + "</tr>";
353 first_lang = false;
354 }
355
356 gti_status_table += lang_status_temp + "</tr>";
357 ++gti_language;
358 }
359 gti_status_table += "\n</table>";
360 disp.setmacro("gtistatustable", "gti", gti_status_table);
361}
362
363
364
365void gtiaction::define_gti_find_page(displayclass& disp, cgiargsclass& args, ostream& logout)
366{
367 // Get the target language code and file to translate from the CGI arguments
368 text_t target_language_code = args["tlc"];
369 text_t translation_file_key = args["tfk"];
370 text_t query_string = to_utf8(args["q"]);
371
372 // Process user corrections
373 if (args["sp"] != "") {
374 process_gti_submissions(disp, args, logout, false);
375 }
376
377 disp.setmacro("gtiformcontent", "gti", "_gti:gtifind_");
378
379 languageinfo_tmap loaded_languages = recpt->get_configinfo().languages;
380 disp.setmacro("gtitargetlanguagename", "gti", loaded_languages[target_language_code].longname);
381 disp.setmacro("gtitranslationfiledesc", "gti", "_gti:textgti" + translation_file_key + "_");
382
383 if (query_string == "") {
384 // No query, so no search results
385 disp.setmacro("gtifindformcontent", "gti", "");
386 return;
387 }
388
389 // Display text right to left if target language is Arabic or Farsi or Urdu
390 if (target_language_code == "ar" || target_language_code == "fa" || target_language_code == "ur") {
391 disp.setmacro("gtitextdirection", "gti", "rtl");
392 }
393 else {
394 disp.setmacro("gtitextdirection", "gti", "ltr");
395 }
396
397 // Send a request to gti.pl to get the valid translation files
398 logout << "Query argument: " << query_string << endl;
399 text_t gti_arguments = "search-chunks " + target_language_code + " " + translation_file_key + " " + query_string;
400 GTI_Response gti_response = parse_gti_response(do_gti_request(gti_arguments, logout), logout);
401 if (gti_response.error_message != "") {
402 // An error has occurred
403 disp.setmacro("gtiformcontent", "gti", "_gti:gtierror_");
404 disp.setmacro("gtierrormessage", "gti", gti_response.error_message);
405 return;
406 }
407
408 disp.setmacro("gtinumchunksmatchingquery", "gti", gti_response.num_chunks_matching_query);
409
410 // Loop through the chunks returned, displaying them on the page
411 text_t gti_find_form_content = "_gtifindformheader_\n";
412 text_tmap::iterator chunk_key_iterator = gti_response.target_file_chunks_key_to_text_mapping.begin();
413 while (chunk_key_iterator != gti_response.target_file_chunks_key_to_text_mapping.end()) {
414 text_t chunk_key = chunk_key_iterator->first;
415
416 // Need to escape any underscores in the chunk key to show it correctly on the page
417 text_t chunk_key_escaped = escape_all(chunk_key, '_');
418
419 // Need to escape any backslashes, underscores, commas, parentheses, and single quotes in the chunk text
420 text_t target_file_chunk_text = gti_response.target_file_chunks_key_to_text_mapping[chunk_key];
421 text_t target_file_chunk_text_escaped = escape_all(target_file_chunk_text, '\\');
422 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, '_');
423 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, ',');
424 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, '(');
425 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, ')');
426 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, '"');
427 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, '\'');
428
429 // This chunk matches the query
430 gti_find_form_content += "_gtichunkmatchingquery_(" + chunk_key_escaped + "," + target_file_chunk_text_escaped + ")\n";
431
432 chunk_key_iterator++;
433 }
434 gti_find_form_content += "_gtifindformfooter_\n";
435
436 disp.setmacro("gtifindformcontent", "gti", gti_find_form_content);
437}
438
439
440
441void gtiaction::define_gti_offline_page(displayclass& disp, cgiargsclass& args, ostream& logout)
442{
443 // Get the target language code and file to translate from the CGI arguments
444 text_t target_language_code = args["tlc"];
445 text_t translation_file_key = args["tfk"];
446
447 disp.setmacro("gtiformcontent", "gti", "_gti:gtioffline_");
448
449 languageinfo_tmap loaded_languages = recpt->get_configinfo().languages;
450 disp.setmacro("gtitargetlanguagename", "gti", loaded_languages[target_language_code].longname);
451 disp.setmacro("gtitranslationfiledesc", "gti", "_gti:textgti" + translation_file_key + "_");
452}
453
454
455
456void gtiaction::define_gti_core_page(displayclass& disp, cgiargsclass& args, ostream& logout)
457{
458 // Get the target language code and file to translate from the CGI arguments
459 text_t target_language_code = args["tlc"];
460 text_t translation_file_key = args["tfk"];
461 text_t num_chunks_per_page = args["ncpp"];
462 logout << "Num chunks per page: " << num_chunks_per_page << endl;
463
464 disp.setmacro("gtiformcontent", "gti", "_gti:gticore_");
465
466 // Display text right to left if target language is Arabic or Farsi or Urdu
467 if (target_language_code == "ar" || target_language_code == "fa" || target_language_code == "ur") {
468 disp.setmacro("gtitextdirection", "gti", "rtl");
469 }
470 else {
471 disp.setmacro("gtitextdirection", "gti", "ltr");
472 }
473
474 // Send a request to gti.pl to get the first string to translate
475 text_t gti_arguments = "get-first-n-chunks-requiring-work " + target_language_code + " " + translation_file_key + " " + num_chunks_per_page;
476 GTI_Response gti_response = parse_gti_response(do_gti_request(gti_arguments, logout), logout);
477 if (gti_response.error_message != "") {
478 // An error has occurred
479 disp.setmacro("gtiformcontent", "gti", "_gti:gtierror_");
480 disp.setmacro("gtierrormessage", "gti", gti_response.error_message);
481 return;
482 }
483
484 languageinfo_tmap loaded_languages = recpt->get_configinfo().languages;
485 disp.setmacro("gtitargetlanguagename", "gti", loaded_languages[target_language_code].longname);
486 disp.setmacro("gtitargetfilepath", "gti", gti_response.translation_files_key_to_target_file_path_mapping[translation_file_key]);
487 disp.setmacro("gtitranslationfiledesc", "gti", "_gti:textgti" + translation_file_key + "_");
488 disp.setmacro("gtiviewtranslationfileinaction", "gti", "_gti:gtiview" + translation_file_key + "inaction_");
489
490 disp.setmacro("gtinumchunkstranslated", "gti", gti_response.translation_files_key_to_num_chunks_translated_mapping[translation_file_key]);
491 disp.setmacro("gtinumchunksrequiringtranslation", "gti", gti_response.translation_files_key_to_num_chunks_requiring_translation_mapping[translation_file_key]);
492 disp.setmacro("gtinumchunksrequiringupdating", "gti", gti_response.translation_files_key_to_num_chunks_requiring_updating_mapping[translation_file_key]);
493
494 // Check if the translation file is finished
495 if (gti_response.translation_files_key_to_num_chunks_requiring_translation_mapping[translation_file_key] == "0" && gti_response.translation_files_key_to_num_chunks_requiring_updating_mapping[translation_file_key] == "0") {
496 disp.setmacro("gtiformcontent", "gti", "_gti:gtidone_");
497 return;
498 }
499
500 // Loop through the chunks returned, displaying them on the page
501 text_t gti_core_form_content = "";
502 text_tmap::iterator chunk_key_iterator = gti_response.source_file_chunks_key_to_text_mapping.begin();
503 while (chunk_key_iterator != gti_response.source_file_chunks_key_to_text_mapping.end()) {
504 text_t chunk_key = chunk_key_iterator->first;
505
506 // Need to escape any underscores in the chunk key to show it correctly on the page
507 text_t chunk_key_escaped = escape_all(chunk_key, '_');
508
509 // Need to escape any backslashes, underscores, commas, parentheses, and single quotes in the chunk text
510 text_t source_file_chunk_text = gti_response.source_file_chunks_key_to_text_mapping[chunk_key];
511 text_t source_file_chunk_text_escaped = escape_all(source_file_chunk_text, '\\');
512 source_file_chunk_text_escaped = escape_all(source_file_chunk_text_escaped, '_');
513 source_file_chunk_text_escaped = escape_all(source_file_chunk_text_escaped, ',');
514 source_file_chunk_text_escaped = escape_all(source_file_chunk_text_escaped, '(');
515 source_file_chunk_text_escaped = escape_all(source_file_chunk_text_escaped, ')');
516 source_file_chunk_text_escaped = escape_all(source_file_chunk_text_escaped, '\'');
517 text_t target_file_chunk_text = gti_response.target_file_chunks_key_to_text_mapping[chunk_key];
518 text_t target_file_chunk_text_escaped = escape_all(target_file_chunk_text, '\\');
519 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, '_');
520 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, ',');
521 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, '(');
522 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, ')');
523 target_file_chunk_text_escaped = escape_all(target_file_chunk_text_escaped, '\'');
524
525 text_t source_file_chunk_date = gti_response.source_file_chunks_key_to_date_mapping[chunk_key];
526 text_t target_file_chunk_date = gti_response.target_file_chunks_key_to_date_mapping[chunk_key];
527
528 // This chunk requires translation
529 if (target_file_chunk_text == "") {
530 gti_core_form_content += "_gtichunkrequiringtranslation_(" + chunk_key_escaped + "," + source_file_chunk_text_escaped + "," + source_file_chunk_date + ")\n";
531 }
532 // This chunk requires updating
533 else {
534 gti_core_form_content += "_gtichunkrequiringupdating_(" + chunk_key_escaped + "," + source_file_chunk_text_escaped + "," + source_file_chunk_date + "," + target_file_chunk_text_escaped + "," + target_file_chunk_date + ")\n";
535 }
536
537 chunk_key_iterator++;
538 }
539
540 disp.setmacro("gticoreformcontent", "gti", gti_core_form_content);
541}
542
543
544
545void gtiaction::process_gti_submissions(displayclass& disp, cgiargsclass& args, ostream& logout, bool force_submission)
546{
547 // Get the target language code and file to translate from the CGI arguments
548 text_t target_language_code = args["tlc"];
549 text_t translation_file_key = args["tfk"];
550 text_t submitter_username = args["un"];
551
552 // Submitted chunk arguments contain the language code followed by "::"
553 char* source_chunk_key_start_cstr = ((text_t) "en" + "%3A%3A").getcstr();
554 char* target_chunk_key_start_cstr = (target_language_code + "%3A%3A").getcstr();
555
556 // Find the cgi arguments with submitted chunk information
557 text_t submission_text;
558 cgiargsclass::const_iterator cgi_argument = args.begin();
559 while (cgi_argument != args.end()) {
560 char* cgi_argument_name_cstr = cgi_argument->first.getcstr();
561
562 // Source file text
563 if (strncmp(cgi_argument_name_cstr, source_chunk_key_start_cstr, strlen(source_chunk_key_start_cstr)) == 0) {
564 submission_text += "<SourceFileText key=\"";
565 submission_text += &cgi_argument_name_cstr[strlen(source_chunk_key_start_cstr)];
566 submission_text += "\">\n";
567
568 text_t source_value = xml_safe(decode_commas(args[cgi_argument->first]));
569 // if (args["w"] != "utf-8") {
570 // source_value = to_utf8(source_value);
571 // }
572 submission_text += source_value + "\n";
573 submission_text += "</SourceFileText>\n";
574 }
575 // Target file text
576 if (strncmp(cgi_argument_name_cstr, target_chunk_key_start_cstr, strlen(target_chunk_key_start_cstr)) == 0) {
577 submission_text += "<TargetFileText key=\"";
578 submission_text += &cgi_argument_name_cstr[strlen(target_chunk_key_start_cstr)];
579 submission_text += "\">\n";
580
581 text_t target_value = xml_safe(decode_commas(args[cgi_argument->first]));
582 // if (args["w"] != "utf-8") {
583 // target_value = to_utf8(target_value);
584 // }
585 submission_text += target_value + "\n";
586 submission_text += "</TargetFileText>\n";
587 }
588
589 delete[] cgi_argument_name_cstr;
590 ++cgi_argument;
591 }
592
593 logout << "Submission text: " << submission_text << endl;
594
595 // Send the submission to gti.pl
596 text_t gti_arguments = "submit-translations " + target_language_code + " " + translation_file_key + " " + submitter_username;
597 if (force_submission) {
598 gti_arguments += " -force_submission";
599 }
600 do_gti_submission(gti_arguments, submission_text, logout);
601 logout << "Done." << endl;
602
603 delete[] source_chunk_key_start_cstr;
604 delete[] target_chunk_key_start_cstr;
605}
606
607
608
609bool gtiaction::produce_excel_spreadsheet(cgiargsclass& args, ostream& logout)
610{
611 // Get the target language code and file to translate from the CGI arguments
612 text_t target_language_code = args["tlc"];
613 text_t translation_file_key = args["tfk"];
614
615 // Send a request to gti.pl to get the Excel spreadsheet data
616 text_t gti_arguments = "get-first-n-chunks-requiring-work " + target_language_code + " " + translation_file_key + " " + "10000" + " | java -cp /home/nzdl/gti ApplyXSLT /home/nzdl/gti/gti-generate-excel-xml.xsl -";
617 text_t gti_response_xml_text = do_gti_request(gti_arguments, logout);
618 if (gti_response_xml_text == "") {
619 // An error has occurred
620 return false;
621 }
622
623 // Write the Excel spreadsheet data to the browser
624 char* gti_response_xml_text_cstr = gti_response_xml_text.getcstr();
625 printf(gti_response_xml_text_cstr);
626 delete[] gti_response_xml_text_cstr;
627
628 return true;
629}
630
631
632
633text_t gtiaction::escape_all(text_t text_string, char character_to_escape)
634{
635 text_t text_string_escaped = "";
636
637 text_t::iterator text_string_character = text_string.begin();
638 while (text_string_character != text_string.end()) {
639 if (*text_string_character == character_to_escape) {
640 text_string_escaped += "\\";
641 }
642 text_string_escaped.push_back(*text_string_character);
643 text_string_character++;
644 }
645
646 return text_string_escaped;
647}
648
649
650
651text_t gtiaction::xml_safe(const text_t &text_string)
652{
653 text_t text_string_safe;
654 text_t::const_iterator here = text_string.begin();
655 text_t::const_iterator end = text_string.end();
656 while (here != end) {
657 if (*here == '&') text_string_safe += "&amp;";
658 else if (*here == '<') text_string_safe += "&lt;";
659 else if (*here == '>') text_string_safe += "&gt;";
660 else text_string_safe.push_back(*here);
661 ++here;
662 }
663
664 return text_string_safe;
665}
666
667
668
669char* xml_get_attribute(const char** attributes, char* attribute_name)
670{
671 for (int i = 0; (attributes[i] != NULL); i += 2) {
672 if (strcmp(attribute_name, attributes[i]) == 0) {
673 return strdup(attributes[i+1]);
674 }
675 }
676
677 return NULL;
678}
679
680
681static void XMLCALL gti_response_xml_start_element(void* user_data, const char* element_name_cstr, const char** attributes)
682{
683 GTI_Response* gti_response = (GTI_Response*) user_data;
684 text_t element_name = element_name_cstr;
685 cerr << "In startElement() for " << element_name << endl;
686
687 if (element_name == "GTIError") {
688 gti_response->recorded_text = "";
689 gti_response->is_recording_text = true;
690 }
691
692 if (element_name == "TranslationFile") {
693 int translation_file_index = gti_response->translation_files_index_to_key_mapping.size();
694 gti_response->translation_file_key = xml_get_attribute(attributes, "key");
695 gti_response->translation_files_index_to_key_mapping[translation_file_index] = gti_response->translation_file_key;
696 gti_response->translation_files_key_to_target_file_path_mapping[gti_response->translation_file_key] = xml_get_attribute(attributes, "target_file_path");
697 gti_response->translation_files_key_to_num_chunks_translated_mapping[gti_response->translation_file_key] = xml_get_attribute(attributes, "num_chunks_translated");
698 gti_response->translation_files_key_to_num_chunks_requiring_translation_mapping[gti_response->translation_file_key] = xml_get_attribute(attributes, "num_chunks_requiring_translation");
699 gti_response->translation_files_key_to_num_chunks_requiring_updating_mapping[gti_response->translation_file_key] = xml_get_attribute(attributes, "num_chunks_requiring_updating");
700 }
701
702 if (element_name == "ChunksMatchingQuery") {
703 gti_response->num_chunks_matching_query = xml_get_attribute(attributes, "size");
704 }
705
706 if (element_name == "Chunk") {
707 gti_response->chunk_key = xml_get_attribute(attributes, "key");
708 }
709
710 if (element_name == "SourceFileText") {
711 gti_response->source_file_chunks_key_to_date_mapping[gti_response->chunk_key] = xml_get_attribute(attributes, "date");
712 gti_response->recorded_text = "";
713 gti_response->is_recording_text = true;
714 }
715
716 if (element_name == "TargetFileText") {
717 if (xml_get_attribute(attributes, "date") != NULL) {
718 gti_response->target_file_chunks_key_to_date_mapping[gti_response->chunk_key] = xml_get_attribute(attributes, "date");
719 }
720 gti_response->recorded_text = "";
721 gti_response->is_recording_text = true;
722 }
723}
724
725
726static void XMLCALL gti_response_xml_end_element(void* user_data, const char* element_name_cstr)
727{
728 GTI_Response* gti_response = (GTI_Response*) user_data;
729 text_t element_name = element_name_cstr;
730
731 if (element_name == "GTIError") {
732 gti_response->error_message = to_uni(gti_response->recorded_text);
733 gti_response->is_recording_text = false;
734 }
735
736 if (element_name == "SourceFileText") {
737 gti_response->source_file_chunks_key_to_text_mapping[gti_response->chunk_key] = to_uni(gti_response->recorded_text);
738 gti_response->is_recording_text = false;
739 }
740
741 if (element_name == "TargetFileText") {
742 gti_response->target_file_chunks_key_to_text_mapping[gti_response->chunk_key] = to_uni(gti_response->recorded_text);
743 gti_response->is_recording_text = false;
744 }
745}
746
747
748static void XMLCALL gti_response_xml_character_data(void *user_data, const char* text_cstr, int text_length)
749{
750 GTI_Response* gti_response = (GTI_Response*) user_data;
751 if (gti_response->is_recording_text) {
752 gti_response->recorded_text.appendcarr(text_cstr, text_length);
753 }
754}
755
756
757
758text_t gtiaction::do_gti_request(text_t gti_arguments, ostream& logout)
759{
760 // Send the request to gti.pl and read the XML output
761 text_t gti_command = "perl -S " + filename_cat(gsdlhome, "bin", "script", "gti.pl") + " " + gti_arguments;
762 char* gti_command_cstr = gti_command.getcstr();
763 FILE *gti_pipe = popen(gti_command_cstr, "r");
764 delete[] gti_command_cstr;
765 if (gti_pipe == NULL) {
766 logout << "Error: Could not open pipe for GTI command " << gti_command << endl;
767 return "";
768 }
769
770 // Read the gti.pl response
771 text_t gti_response_xml_text;
772 while (!feof(gti_pipe)) {
773 char buffer[1024];
774 gti_response_xml_text.appendcarr(buffer, fread(buffer, 1, 1024, gti_pipe));
775 }
776 pclose(gti_pipe);
777
778 return gti_response_xml_text;
779}
780
781
782
783GTI_Response gtiaction::parse_gti_response(text_t gti_response_xml_text, ostream& logout)
784{
785 GTI_Response gti_response;
786 gti_response.is_recording_text = false;
787
788 // Parse the gti.pl response (XML)
789 logout << "Parsing GTI command response: " << gti_response_xml_text << endl;
790 XML_Parser xml_parser = XML_ParserCreate(NULL);
791 XML_SetUserData(xml_parser, &gti_response);
792 XML_SetElementHandler(xml_parser, gti_response_xml_start_element, gti_response_xml_end_element);
793 XML_SetCharacterDataHandler(xml_parser, gti_response_xml_character_data);
794
795 char* gti_response_xml_text_cstr = gti_response_xml_text.getcstr();
796 int parse_status = XML_Parse(xml_parser, gti_response_xml_text_cstr, strlen(gti_response_xml_text_cstr), XML_TRUE);
797 delete[] gti_response_xml_text_cstr;
798 if (parse_status == XML_STATUS_ERROR) {
799 logout << "Parse error " << XML_ErrorString(XML_GetErrorCode(xml_parser)) << " at line " << XML_GetCurrentLineNumber(xml_parser) << endl;
800 return gti_response;
801 }
802
803 XML_ParserFree(xml_parser);
804
805 logout << "Finished parse." << endl;
806 return gti_response;
807}
808
809
810
811void gtiaction::do_gti_submission(text_t gti_arguments, text_t gti_submission, ostream& logout)
812{
813 // Send the submission to gti.pl
814 text_t gti_command = "perl -S " + filename_cat(gsdlhome, "bin", "script", "gti.pl") + " " + gti_arguments;
815 char* gti_command_cstr = gti_command.getcstr();
816 FILE *gti_pipe = popen(gti_command_cstr, "w");
817 delete[] gti_command_cstr;
818 if (gti_pipe == NULL) {
819 logout << "Error: Could not open pipe for GTI command " << gti_command << endl;
820 return;
821 }
822
823 // Write the gti.pl submission
824 char* gti_submission_cstr = gti_submission.getcstr();
825 fwrite(gti_submission_cstr, 1, strlen(gti_submission_cstr), gti_pipe);
826 delete[] gti_submission_cstr;
827
828 pclose(gti_pipe);
829}
830
831
832
833#endif // GSDL_USE_GTI_ACTION
Note: See TracBrowser for help on using the repository browser.