Annotation of loncom/publisher/loncleanup.pm, revision 1.17
1.1 www 1: # The LearningOnline Network with CAPA
2: # Handler to cleanup XML files
3: #
1.17 ! raeburn 4: # $Id: loncleanup.pm,v 1.16 2011/11/14 00:20:31 raeburn Exp $
1.1 www 5: #
6: # Copyright Michigan State University Board of Trustees
7: #
8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
9: #
10: # LON-CAPA 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: # LON-CAPA 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 LON-CAPA; if not, write to the Free Software
22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23: #
24: # /home/httpd/html/adm/gpl.txt
25: #
26: # http://www.lon-capa.org/
27: #
28: #
29: ###
30:
31: package Apache::loncleanup;
32:
33: use strict;
34: use Apache::File;
35: use File::Copy;
36: use Apache::Constants qw(:common :http :methods);
37: use Apache::loncommon();
1.11 bisitz 38: use Apache::lonhtmlcommon();
1.1 www 39: use Apache::lonlocal;
40: use Apache::lonnet;
1.8 www 41: use lib '/home/httpd/lib/perl/';
42: use LONCAPA;
43:
1.1 www 44:
45: sub latextrans {
46: my $symbolfont=shift;
47: my %latexsymb=(
48: '±' => '\pm',
49: '´' => '\times',
50: '¸' => '\div',
51: 'Ò' => '(R)',
52: 'Ó' => '\copy',
53: 'Ø' => '\neg',
54: 'â' => '(R)',
55: 'ã' => '\copy',
56: '¦' => 'f',
57: 'A' => '\Alpha',
58: 'B' => '\Beta',
59: 'G' => '\Gamma',
60: 'D' => '\Delta',
61: 'E' => '\Epsilon',
62: 'Z' => '\Zeta',
63: 'H' => '\Eta',
64: 'Q' => '\Theta',
65: 'I' => '\Iota',
66: 'K' => '\Kappa',
67: 'L' => '\Lambda',
68: 'M' => '\Mu',
69: 'N' => '\Nu',
70: 'X' => '\Xi',
71: 'O' => '\Omicron',
72: 'P' => '\Pi',
73: 'R' => '\Rho',
74: 'S' => '\Sigma',
75: 'T' => '\Tau',
76: 'U' => 'Y',
77: 'F' => '\Phi',
78: 'C' => '\Chi',
79: 'Y' => '\Psi',
80: 'W' => '\Omega',
81: 'a' => '\alpha',
82: 'b' => '\beta',
83: 'g' => '\gamma',
84: 'd' => '\delta',
85: 'e' => '\epsilon',
86: 'z' => '\zeta',
87: 'h' => '\eta',
88: 'q' => '\theta',
89: 'i' => '\iota',
90: 'k' => '\kappa',
91: 'l' => '\lambda',
92: 'm' => '\mu',
93: 'n' => '\nu',
94: 'x' => '\xi',
95: 'o' => '\omicron',
96: 'p' => '\pi',
97: 'r' => '\rho',
98: 'V' => '\sigmaf',
99: 's' => '\sigma',
100: 't' => '\tau',
101: 'u' => '\upsilon',
102: 'f' => '\phi',
103: 'c' => '\chi',
104: 'y' => '\psi',
105: 'w' => '\omega',
106: 'J' => '\vartheta',
107: 'j' => '\varphi',
108: 'v' => '\varpi',
109: '¡' => '\Upsilon',
110: '¢' => "'",
111: '¤' => '/',
112: '²' => '"',
113: '¼' => '\ldots',
114: 'À' => '\aleph',
115: 'Á' => '\Im',
116: 'Â' => '\Re',
117: 'Ã' => '\wp',
118: 'Ô' => '^{TM}',
119: 'ä' => '^{TM}',
120: 'ð' => 'EUR',
121: '«' => '\leftrightarrow',
122: '¬' => '\leftarrow',
123: '­' => '\uparrow',
124: '®' => '\rightarrow',
125: '¯' => '\downarraw',
126: '¿' => '\hookleftarrow',
127: 'Û' => '\Leftrightarrow',
128: 'Ü' => '\Leftarrow',
129: 'Ý' => '\Uparrow',
130: 'Þ' => '\Rightarrow',
131: 'ß' => '\Downarrow',
132: '"' => '\forall',
133: '$' => '\exists',
134: ''' => '\ni',
135: '*' => '\ast',
136: '-' => '-',
137: '@' => '\cong',
138: '\' => '\therefore',
139: '^' => '\perp',
140: '~' => '\sim',
141: '£' => '\leq',
142: '¥' => '\infty',
143: '³' => '\geq',
144: 'µ' => '\propto',
145: '¶' => '\partial',
146: '·' => '\cdot',
147: '¹' => '\not=',
148: 'º' => '\equiv',
149: '»' => '\approx',
150: 'Ä' => '\otimes',
151: 'Å' => '\oplus',
152: 'Æ' => '\emptyset',
153: 'Ç' => '\cap',
154: 'È' => '\cup',
155: 'É' => '\supset',
156: 'Ê' => '\supseteq',
157: 'Ë' => '\not\subset',
158: 'Ì' => '\subset',
159: 'Í' => '\subseteq',
160: 'Î' => '\in',
161: 'Ï' => '\not\in',
162: 'Ð' => '\angle',
163: 'Ñ' => '\nabla',
164: 'Õ' => '\prod',
165: 'Ö' => '\surd',
166: '×' => '\cdot',
167: 'Ù' => '\wedge',
168: 'Ú' => '\wee',
169: 'å' => '\sum',
170: 'ò' => '\int',
171: 'á' => '\langle',
172: 'ñ' => '\rangle',
173: 'à' => '\diamondsuit',
174: '§' => '\clubsuit',
175: '¨' => '\diamondsuit',
176: '©' => '\heartsuit',
177: 'ª' => '\spadesuit'
178: );
179: my $output='';
180: my $char='';
181: my $entitymode=0;
182: for (my $i=0; $i<length($symbolfont); $i++) {
183: my $newchar=substr($symbolfont,$i,1);
184: $char.=$newchar;
185: if ($newchar eq '&') { $entitymode=1; }
186: if (($entitymode) && ($newchar ne ';')) { next; }
187: my $latex=$latexsymb{$char};
188: if ($latex) {
189: $output.=$latex;
190: } else {
191: $output.=$char;
192: }
193: $char='';
194: $entitymode=0;
195: }
196: return $output;
197: }
198:
199: sub insidetrans {
200: my @args=@_;
201: return '<font'.$args[0].$args[1].'><m>$'.&latextrans($args[2]).'$</m>';
202: }
203:
204: sub symbolfontreplace {
205: my $text=shift;
206: my @fragments=split(/\<\/font\>/si,$text);
207: for (my $i=0; $i<=$#fragments;$i++) {
208: $fragments[$i]=~s/\<font([^\>]*)\s+face=[\"\']*symbol[\"\']*([^\>]*)\>(.*)$/&insidetrans($1,$2,$3)/gsie;
209: }
210: return join('</font>',@fragments);
211: }
212:
213: sub htmlclean {
1.2 www 214: my ($raw,$full,$blocklinefeed,$blockemptytags,$blocklowercasing,$blockdesymboling)=@_;
1.1 www 215: # Take care of CRLF etc
1.2 www 216: unless ($blocklinefeed) {
217: $raw=~s/\r\f/\n/gs; $raw=~s/\f\r/\n/gs;
218: $raw=~s/\r\n/\n/gs; $raw=~s/\n\r/\n/gs;
219: $raw=~s/\f/\n/gs; $raw=~s/\r/\n/gs;
220: $raw=~s/\&\#10\;/\n/gs; $raw=~s/\&\#13\;/\n/gs;
221: }
1.1 www 222: # Generate empty tags, remove wrong end tags
1.2 www 223: unless ($blockemptytags) {
1.6 www 224: $raw=~s/\<(br|hr|img|meta|embed|allow|basefont)([^\>]*?)\>/\<$1$2 \/\>/gis;
225: $raw=~s/\<\/(br|hr|img|meta|embed|allow|basefont)\>//gis;
226: $raw=~s/\/ \/\>/\/\>/gs;
1.2 www 227: unless ($full) {
228: $raw=~s/\<[\/]*(body|head|html)\>//gis;
229: }
1.1 www 230: }
231: # Make standard tags lowercase
1.2 www 232: unless ($blocklowercasing) {
233: foreach ('html','body','head','meta','h1','h2','h3','h4','b','i','m',
234: 'table','tr','td','th','p','br','hr','img','embed','font',
235: 'a','strong','center','title','basefont','li','ol','ul',
236: 'input','select','form','option','script','pre') {
237: $raw=~s/\<$_\s*\>/\<$_\>/gis;
238: $raw=~s/\<\/$_\s*\>/<\/$_\>/gis;
239: $raw=~s/\<$_\s([^\>]*)\>/<$_ $1\>/gis;
240: }
241: }
242: # Replace <font face="symbol">
243: unless ($blockdesymboling) {
244: $raw=&symbolfontreplace($raw);
1.1 www 245: }
246: return $raw;
247: }
248:
249: sub phaseone {
1.2 www 250: my ($r,$fn,$uname,$udom)=@_;
1.11 bisitz 251: $r->print(
252: &Apache::lonhtmlcommon::start_pick_box()
253: .&Apache::lonhtmlcommon::row_title(&mt('Select actions to attempt'))
254: .'<input type="checkbox" name="linefeed" checked="checked" /> '
255: .&mt('Linefeeds, formfeeds, and carriage returns')
256: .'<br />'
257: .'<input type="checkbox" name="empty" checked="checked" /> '
258: .&mt('Empty tags')
259: .'<br />'
260: .'<input type="checkbox" name="lower" checked="checked" /> '
261: .&mt('Lower casing')
262: .'<br />'
263: .'<input type="checkbox" name="symbol" checked="checked" /> '
264: .&mt('Symbol font')
265: .&Apache::lonhtmlcommon::row_closure(1)
266: .&Apache::lonhtmlcommon::end_pick_box()
267: );
268:
269: $r->print(
270: '<input type="hidden" name="phase" value="two" />'
271: .'<p>'
272: .'<input type="submit" value="'.&mt('Next').'" />'
273: .'</p>'
274: );
1.1 www 275: }
276:
277: sub phasetwo {
1.11 bisitz 278: # Check original file
1.2 www 279: my ($r,$fn,$uname,$udom)=@_;
1.4 www 280: my $text='';
1.14 raeburn 281: my $londocroot = $r->dir_config('lonDocRoot');
282: if (open(IN,"<$londocroot/priv/$udom/$uname".$fn)) {
283: while (my $line=<IN>) {
284: $text.=$line;
285: }
286: close(IN);
1.4 www 287: }
1.14 raeburn 288: my $uri="/priv/$udom/$uname".$fn;
1.4 www 289: my $result=&Apache::lonnet::ssi_body($uri,
290: ('grade_target'=>'web',
291: 'return_only_error_and_warning_counts' => 1));
292: my ($errorcount,$warningcount)=split(':',$result);
1.11 bisitz 293:
294: # Display results for original file
295: $r->print(
296: &Apache::lonhtmlcommon::start_pick_box()
297: .&Apache::lonhtmlcommon::row_title(&mt('Original file'))
298: .&Apache::lonhtmlcommon::confirm_success(
299: &mt('[quant,_1,error]',$errorcount), $errorcount)
300: .'<br />'
301: .&Apache::lonhtmlcommon::confirm_success(
302: &mt('[quant,_1,warning]',$warningcount), $warningcount)
303: .&Apache::lonhtmlcommon::row_closure()
304: );
305:
306: # Clean up file
1.4 www 307: $text=&htmlclean($text,1,
308: ($env{'form.linefeed'} ne 'on'),
309: ($env{'form.empty'} ne 'on'),
310: ($env{'form.lower'} ne 'on'),
311: ($env{'form.symbol'} ne 'on'));
312: my ($main,$ext)=($fn=~/^(.*)\.(\w+)/);
313: my $newfn=$main.'_Auto_Cleaned_Up.'.$ext;
1.14 raeburn 314: if (open(OUT,">$londocroot/priv/$udom/$uname".$newfn)) {
315: print OUT $text;
316: close(OUT);
317: }
318: my $newuri="/priv/$udom/$uname".$newfn;
1.4 www 319: $result=&Apache::lonnet::ssi_body($newuri,
1.11 bisitz 320: ('grade_target'=>'web',
321: 'return_only_error_and_warning_counts' => 1));
1.4 www 322: ($errorcount,$warningcount)=split(':',$result);
1.11 bisitz 323:
324: # Display results for cleaned up file
325: $r->print(
326: &Apache::lonhtmlcommon::row_title(&mt('Cleaned up file'))
327: .&Apache::lonhtmlcommon::confirm_success(
328: &mt('[quant,_1,error]',$errorcount), $errorcount)
329: .'<br />'
330: .&Apache::lonhtmlcommon::confirm_success(
331: &mt('[quant,_1,warning]',$warningcount), $warningcount)
332: .&Apache::lonhtmlcommon::row_closure()
333: );
334:
335: # Display actions
336: $r->print(
337: &Apache::lonhtmlcommon::row_title(&mt('Actions'))
338: .'<ul>'
339: .'<li><a href="'.$newuri.'" target="prev">'
340: .&mt('Open (and edit) cleaned up file in new window')
341: .'</a></li>'
342: .'<li><a href="/adm/diff?filename='.&escape($uri)
343: .'&versionone=priv&filetwo='.&escape($newuri).'" target="prev">'
344: .&mt('Show diffs in new window')
345: .'</a></li>'
346: .'</ul>'
347: .&Apache::lonhtmlcommon::row_closure(1)
348: .&Apache::lonhtmlcommon::end_pick_box()
349: .'<p>'
350: .'<input type="hidden" name="phase" value="three" />'
351: .'<input type="submit" name="accept" value="'
352: .&mt('Clean Up').'" />'
353: .' <input type="submit" name="reject" value="'
354: .&mt('Cancel').'" />'
355: .'</p>'
356: );
1.2 www 357: }
358:
359: sub phasethree {
360: my ($r,$fn,$uname,$udom)=@_;
1.14 raeburn 361: my $old=$r->dir_config('lonDocRoot')."/priv/$udom/$uname".$fn;
1.4 www 362: my ($main,$ext)=($fn=~/^(.*)\.(\w+)/);
363: my $newfn=$main.'_Auto_Cleaned_Up.'.$ext;
1.14 raeburn 364: my $new=$r->dir_config('lonDocRoot')."/priv/$udom/$uname".$newfn;
1.4 www 365: if ($env{'form.accept'}) {
1.11 bisitz 366: $r->print(
367: '<p class="LC_info">'
368: .&mt('Accepting changes')
369: .'</p>'
370: );
1.4 www 371: move($new,$old);
372: } else {
1.11 bisitz 373: $r->print(
374: '<p class="LC_info">'
375: .&mt('Rejecting changes')
376: .'</p>'
377: );
1.4 www 378: unlink($new);
379: }
1.1 www 380: }
381:
382: # ---------------------------------------------------------------- Main Handler
383: sub handler {
384:
1.3 albertel 385: my $r=shift;
1.4 www 386: my $fn='';
1.1 www 387:
388: # Get query string for limited number of parameters
389:
1.3 albertel 390: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
391: ['filename']);
1.1 www 392:
1.3 albertel 393: if ($env{'form.filename'}) {
394: $fn=$env{'form.filename'};
1.15 raeburn 395: $fn=~s{^https?\://[^/]+}{};
1.3 albertel 396: } else {
397: $r->log_reason($env{'user.name'}.' at '.$env{'user.domain'}.
398: ' unspecified filename for cleanup', $r->filename);
399: return HTTP_NOT_FOUND;
400: }
401:
402: unless ($fn) {
403: $r->log_reason($env{'user.name'}.' at '.$env{'user.domain'}.
404: ' trying to cleanup non-existing file', $r->filename);
405: return HTTP_NOT_FOUND;
406: }
1.1 www 407:
408: # ----------------------------------------------------------- Start page output
1.3 albertel 409: my $uname;
410: my $udom;
411:
1.17 ! raeburn 412: ($uname,$udom)=&Apache::lonnet::constructaccess($fn);
1.3 albertel 413: unless (($uname) && ($udom)) {
414: $r->log_reason($uname.' at '.$udom.
415: ' trying to cleanup file '.$env{'form.filename'}.
416: ' ('.$fn.') - not authorized',
417: $r->filename);
418: return HTTP_NOT_ACCEPTABLE;
419: }
420:
421: &Apache::loncommon::content_type($r,'text/html');
422: $r->send_http_header;
423:
1.11 bisitz 424: # Breadcrumbs
1.16 raeburn 425: my $brcrum = [{'href' => &Apache::loncommon::authorspace($fn),
1.11 bisitz 426: 'text' => 'Construction Space'},
427: {'href' => '',
428: 'text' => 'Cleanup XML Document'}];
429:
1.16 raeburn 430: $fn=~s{^/priv/$LONCAPA::domain_re/$LONCAPA::username_re}{};
431:
1.11 bisitz 432: $r->print(&Apache::loncommon::start_page('Cleanup XML Document',
433: undef,
434: {'bread_crumbs' => $brcrum,}));
1.4 www 435: $r->print('<h2>'.$fn.'</h2>'.
436: '<form action="/adm/cleanup" method="post">'.
437: '<input type="hidden" name="filename" value="'.$env{'form.filename'}.'" />');
438: unless ($fn=~/\.(problem|exam|quiz|assess|survey|form|library|xml|html|htm|xhtml|xhtm|sty)$/) {
439: $r->print(&mt('Cannot cleanup this filetype'));
1.3 albertel 440: } else {
1.4 www 441: if ($env{'form.phase'} eq 'three') {
442: &phasethree($r,$fn,$uname,$udom);
443: } elsif ($env{'form.phase'} eq 'two') {
444: &phasetwo($r,$fn,$uname,$udom);
445: } else {
446: &phaseone($r,$fn,$uname,$udom);
447: }
1.3 albertel 448: }
1.4 www 449: my $dir=$fn;
1.14 raeburn 450: $dir=~s{[^/]+$}{};
1.11 bisitz 451: $r->print(
452: '</form>'
453: .&Apache::lonhtmlcommon::start_funclist()
454: .&Apache::lonhtmlcommon::add_item_funclist(
1.14 raeburn 455: '<a href="/priv/'.$udom.'/'.$uname.$fn.'">'.&mt('Back to Source File').'</a>')
1.11 bisitz 456: .&Apache::lonhtmlcommon::add_item_funclist(
1.14 raeburn 457: '<a href="/priv/'.$udom.'/'.$uname.$dir.'">'.&mt('Back to Source Directory').'</a>')
1.11 bisitz 458: .&Apache::lonhtmlcommon::end_funclist()
459: .&Apache::loncommon::end_page()
460: );
461:
1.3 albertel 462: return OK;
1.1 www 463: }
464:
465: 1;
466: __END__
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>