summaryrefslogtreecommitdiff
path: root/t/04-template-handling.t
blob: 1f05a2663859b4f055f735ddd47aec162ab493d8 (plain)
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. # Absolute directory name required to not trip up Template::Latex
  5. $ENV{TMPDIR} = "$ENV{PWD}/t/var";
  6. use Test::More 'no_plan';
  7. use Test::Trap qw(trap $trap);
  8. use Test::Exception;
  9. use Error qw(:try :warndie);
  10. use LedgerSMB::AM;
  11. use LedgerSMB::Form;
  12. use LedgerSMB::Sysconfig;
  13. use LedgerSMB::Locale;
  14. use LedgerSMB::Template;
  15. use LedgerSMB::Template::HTML;
  16. $LedgerSMB::Sysconfig::tempdir = 't/var';
  17. my @r;
  18. my $temp;
  19. my $form;
  20. my $myconfig;
  21. my $template;
  22. my $FH;
  23. my $locale;
  24. $locale = LedgerSMB::Locale->get_handle('fr');
  25. # AM->check_template_name checks
  26. # check_template operates by calling $form->error if the checks fail
  27. $form = new Form;
  28. $myconfig = {'templates' => 'test'};
  29. for my $ext ('css', 'tex', 'txt', 'html', 'xml') {
  30. $form->{file} = "test/apples.${ext}";
  31. @r = trap{AM->check_template_name($myconfig, $form)};
  32. ok(!defined $trap->die,
  33. "AM, check_template_name: Template directory, ${ext}");
  34. }
  35. $form->{file} = 'css/apples.txt';
  36. @r = trap{AM->check_template_name($myconfig, $form)};
  37. ok(!defined $trap->die,
  38. 'AM, check_template_name: CSS directory, txt');
  39. $form->{file} = 'test2/apples.txt';
  40. @r = trap{AM->check_template_name($myconfig, $form)};
  41. is($trap->die, "Error: Not in a whitelisted directory: test2/apples.txt\n",
  42. 'AM, check_template_name: Invalid directory, non-css denial');
  43. $form->{file} = 'test/apples.exe';
  44. @r = trap{AM->check_template_name($myconfig, $form)};
  45. is($trap->die, "Error: Error: File is of type that is not allowed.\n",
  46. 'AM, check_template_name: Disallowed type denial');
  47. # adjusting backuppath to avoid triggering directory traversal detection
  48. $temp = ${LedgerSMB::Sysconfig::backuppath};
  49. ${LedgerSMB::Sysconfig::backuppath} = "foo";
  50. $form->{file} = "${LedgerSMB::Sysconfig::backuppath}/apples.txt";
  51. @r = trap{AM->check_template_name($myconfig, $form)};
  52. is($trap->die, "Error: Not allowed to access foo/ with this method\n",
  53. 'AM, check_template_name: Backup path denial');
  54. ${LedgerSMB::Sysconfig::backuppath} = $temp;
  55. $form->{file} = "css/../apples.txt";
  56. @r = trap{AM->check_template_name($myconfig, $form)};
  57. is($trap->die, "Error: Directory transversal not allowed.\n",
  58. 'AM, check_template_name: Directory transversal denial 1');
  59. $form->{file} = "/tmp/apples.txt";
  60. @r = trap{AM->check_template_name($myconfig, $form)};
  61. is($trap->die, "Error: Directory transversal not allowed.\n",
  62. 'AM, check_template_name: Directory transversal denial 2');
  63. $form->{file} = "test/apples.txt:evil";
  64. @r = trap{AM->check_template_name($myconfig, $form)};
  65. is($trap->die, "Error: Directory transversal not allowed.\n",
  66. 'AM, check_template_name: Directory transversal denial 3');
  67. $form->{file} = "c:\\evil.txt";
  68. @r = trap{AM->check_template_name($myconfig, $form)};
  69. is($trap->die, "Error: Directory transversal not allowed.\n",
  70. 'AM, check_template_name: Directory transversal denial 4');
  71. # AM->load_template checks
  72. # load_template takes its file name from form
  73. $form = new Form;
  74. $myconfig = {'templates' => 't/data'};
  75. $form->{file} = 't/data/04-not-there.txt';
  76. @r = trap{AM->load_template($myconfig, $form)};
  77. is($trap->die, "Error: t/data/04-not-there.txt : No such file or directory\n",
  78. 'AM, load_template: Die on non-existent file');
  79. $form->{file} = 't/data/04-template.html';
  80. AM->load_template($myconfig, $form);
  81. is($form->{body}, "I am a template.\nLook at me <?lsmb login ?>.\n",
  82. 'AM, load_template: Read existing file');
  83. # AM->save_template checks
  84. $form = new Form;
  85. $myconfig = {'templates' => 't/var/not here'};
  86. $form->{body} = "I am a template.\nLook at me.\n";
  87. $form->{file} = "$myconfig->{templates}/test.txt";
  88. @r = trap{AM->save_template($myconfig, $form)};
  89. is($trap->die,
  90. "Error: t/var/not here/test.txt : No such file or directory\n",
  91. 'AM, save_template: Die on unwritable file');
  92. $myconfig = {'templates' => 't/var'};
  93. $form->{body} = "I am a template.\nLook at me.";
  94. $form->{file} = "$myconfig->{templates}/04-template-save-test-$$.txt";
  95. ok(!-e $form->{file}, 'AM, save_template: Environment clean');
  96. AM->save_template($myconfig, $form);
  97. ok(-e $form->{file}, 'AM, save_template: File created');
  98. open($FH, '<', $form->{file});
  99. @r = <$FH>;
  100. close($FH);
  101. chomp(@r);
  102. is(join("\n", @r), $form->{body}, 'AM, save_template: Good save');
  103. is(unlink($form->{file}), 1, 'AM, save_template: removing testfile');
  104. ok(!-e $form->{file}, 'AM, save_template: testfile removed');
  105. # LedgerSMB::Template::HTML checks
  106. is(LedgerSMB::Template::HTML::get_template('04-template'), '04-template.html',
  107. 'HTML, get_template: Returned correct template file name');
  108. is(LedgerSMB::Template::HTML::preprocess('04-template'), '04-template',
  109. 'HTML, preprocess: Returned simple string unchanged');
  110. is(LedgerSMB::Template::HTML::preprocess('14 > 12'), '14 &gt; 12',
  111. 'HTML, preprocess: Returned properly escaped string');
  112. is_deeply(LedgerSMB::Template::HTML::preprocess([0, 'apple', 'mango&durian']),
  113. [0, 'apple', 'mango&amp;durian'],
  114. 'HTML, preprocess: Returned properly escaped array ref contents');
  115. is_deeply(LedgerSMB::Template::HTML::preprocess({'fruit' => '&veggies',
  116. 'test' => 1}),
  117. {'fruit' => '&amp;veggies', 'test' => 1},
  118. 'HTML, preprocess: Returned properly escaped hash ref contents');
  119. is_deeply(LedgerSMB::Template::HTML::preprocess({'fruit' => '&veggies',
  120. 'test' => ['nest', 'bird', '0 < 15', 1]}),
  121. {'fruit' => '&amp;veggies', 'test' => ['nest', 'bird', '0 &lt; 15', 1]},
  122. 'HTML, preprocess: Returned properly escaped nested contents');
  123. is(LedgerSMB::Template::HTML::postprocess({outputfile => '04-template'}),
  124. '04-template.html', 'HTML, postprocess: Return output filename');
  125. # Template->new
  126. $myconfig = {'templates' => 't/data'};
  127. throws_ok{new LedgerSMB::Template('user' => $myconfig, 'language' => 'x/0')}
  128. qr/Invalid language/, 'Template, new: Invalid language caught 1';
  129. throws_ok{new LedgerSMB::Template('user' => $myconfig, 'language' => '1\\2')}
  130. qr/Invalid language/, 'Template, new: Invalid language caught 2';
  131. throws_ok{new LedgerSMB::Template('user' => $myconfig, 'language' => '1:2')}
  132. qr/Invalid language/, 'Template, new: Invalid language caught 3';
  133. throws_ok{new LedgerSMB::Template('user' => $myconfig, 'language' => '..')}
  134. qr/Invalid language/, 'Template, new: Invalid language caught 4';
  135. throws_ok{new LedgerSMB::Template('user' => $myconfig, 'language' => '.svn')}
  136. qr/Invalid language/,
  137. 'Template, new: Invalid language caught 5';
  138. $template = undef;
  139. $template = new LedgerSMB::Template('user' => $myconfig, 'language' => 'de');
  140. ok(defined $template, 'Template, new: Object creation with valid language');
  141. isa_ok($template, 'LedgerSMB::Template',
  142. 'Template, new: Object creation with valid language');
  143. is($template->{include_path}, 't/data/de;t/data',
  144. 'Template, new: Object creation with valid language has good include_path');
  145. $template = undef;
  146. $template = new LedgerSMB::Template('user' => $myconfig, 'language' => 'de',
  147. 'path' => 't/data');
  148. ok(defined $template,
  149. 'Template, new: Object creation with valid language and path');
  150. isa_ok($template, 'LedgerSMB::Template',
  151. 'Template, new: Object creation with valid language and path');
  152. is($template->{include_path}, 't/data',
  153. 'Template, new: Object creation with valid path overrides language');
  154. $template = undef;
  155. $template = new LedgerSMB::Template('user' => $myconfig, 'format' => 'HTML',
  156. 'template' => '04-template');
  157. ok(defined $template,
  158. 'Template, new: Object creation with format and template');
  159. isa_ok($template, 'LedgerSMB::Template',
  160. 'Template, new: Object creation with format and template');
  161. is($template->{include_path}, 't/data',
  162. 'Template, new: Object creation with format and template');
  163. is($template->render({'login' => 'foo&bar'}), 't/var/04-template-output.html',
  164. 'Template, render: Simple HTML template, default filename');
  165. ok(-e 't/var/04-template-output.html', 'Template, render (HTML): File created');
  166. open($FH, '<', 't/var/04-template-output.html');
  167. @r = <$FH>;
  168. close($FH);
  169. chomp(@r);
  170. is(join("\n", @r), "I am a template.\nLook at me foo&amp;bar.",
  171. 'Template, render (HTML): Simple HTML template, correct output');
  172. is(unlink('t/var/04-template-output.html'), 1,
  173. 'Template, render: removing testfile');
  174. ok(!-e 't/var/04-template-output.html',
  175. 'Template, render (HTML): testfile removed');
  176. $template = undef;
  177. $template = new LedgerSMB::Template('user' => $myconfig, 'format' => 'HTML',
  178. 'template' => '04-template', 'locale' => $locale);
  179. ok(defined $template,
  180. 'Template, new: Object creation with locale');
  181. isa_ok($template, 'LedgerSMB::Template',
  182. 'Template, new: Object creation with locale');
  183. $template = undef;
  184. $template = new LedgerSMB::Template('user' => $myconfig, 'format' => 'HTML',
  185. 'template' => '04-template-2');
  186. ok(defined $template,
  187. 'Template, new: Object creation with non-existent template');
  188. throws_ok{$template->render({'login' => 'foo'})} qr/not found/,
  189. 'Template, render: File not found caught';
  190. $template = undef;
  191. $template = new LedgerSMB::Template('user' => $myconfig, 'format' => 'TODO',
  192. 'template' => '04-template');
  193. ok(defined $template,
  194. 'Template, new: Object creation with non-existent format');
  195. throws_ok{$template->render({'login' => 'foo'})} qr/Can't locate/,
  196. 'Template, render: Invalid format caught';
  197. $template = undef;
  198. $template = new LedgerSMB::Template('user' => $myconfig, 'format' => 'PDF',
  199. 'template' => '04-template');
  200. ok(defined $template,
  201. 'Template, new: Object creation with format and template');
  202. isa_ok($template, 'LedgerSMB::Template',
  203. 'Template, new: Object creation with format and template');
  204. is($template->{include_path}, 't/data',
  205. 'Template, new: Object creation with format and template');
  206. is($template->render({'login' => 'foo\&bar'}), 't/var/04-template-output.pdf',
  207. 'Template, render: Simple PDF template, default filename');
  208. ok(-e 't/var/04-template-output.pdf', 'Template, render (PDF): File created');
  209. is(unlink('t/var/04-template-output.pdf'), 1,
  210. 'Template, render (PDF): removing testfile');
  211. ok(!-e 't/var/04-template-output.pdf',
  212. 'Template, render (PDF): testfile removed');
  213. $template = undef;
  214. $template = new LedgerSMB::Template('user' => $myconfig, 'format' => 'PS',
  215. 'template' => '04-template');
  216. ok(defined $template,
  217. 'Template, new: Object creation with format and template');
  218. isa_ok($template, 'LedgerSMB::Template',
  219. 'Template, new: Object creation with format and template');
  220. is($template->{include_path}, 't/data',
  221. 'Template, new: Object creation with format and template');
  222. is($template->render({'login' => 'foo\&bar'}), 't/var/04-template-output.ps',
  223. 'Template, render: Simple Postscript template, default filename');
  224. ok(-e 't/var/04-template-output.ps', 'Template, render (PS): File created');
  225. is(unlink('t/var/04-template-output.ps'), 1,
  226. 'Template, render (PS): removing testfile');
  227. ok(!-e 't/var/04-template-output.ps',
  228. 'Template, render (PS): testfile removed');
  229. ##open($FH, '<', 't/var/04-template-output.html');
  230. ##@r = <$FH>;
  231. ##close($FH);
  232. ##chomp(@r);
  233. ##is(join("\n", @r), "I am a template.\nLook at me foo&amp;bar.",
  234. ## 'Template, render (HTML): Simple HTML template, correct output');
  235. ##is(unlink('t/var/04-template-output.html'), 1,
  236. ## 'Template, render: removing testfile');
  237. ##ok(!-e 't/var/04-template-output.html',
  238. ## 'Template, render (HTML): testfile removed');