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

Revision 28979, 35.5 KB (checked in by ak19, 6 years ago)

GTI on nzdl needs path to java executable. Since a custom javahome property can be set in gsdlsite.cfg, this is now read in if site from gsdlsite.cfg by common-src's gsdlsitecfg.cpp and set as an env var with putenv(), following Dr Bainbridge's idea. This env var is then read back in using getenv in gtiaction.cpp, so that it can run the appropriate java.

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