root/main/trunk/greenstone2/runtime-src/src/recpt/gtiaction.cpp @ 22984

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