File:
[LON-CAPA] /
loncom /
interface /
londocs.pm
Revision
1.489:
download - view:
text,
annotated -
select for diffs
Thu Jul 5 21:33:39 2012 UTC (12 years, 1 month ago) by
raeburn
Branches:
MAIN
CVS tags:
HEAD
- Pasting from paste buffer.
- When pasting content in /uploaded from a different course to current course, require 'mdc' priv in original course.
- Parse file for dependencies in HTML file being pasted from docs/supplemental to
different type, or different course, and copy any dependencies which
exist in the source.
- Fix active tab when viewing History for Supplemental Content.
1: # The LearningOnline Network
2: # Documents
3: #
4: # $Id: londocs.pm,v 1.489 2012/07/05 21:33:39 raeburn Exp $
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: package Apache::londocs;
30:
31: use strict;
32: use Apache::Constants qw(:common :http);
33: use Apache::imsexport;
34: use Apache::lonnet;
35: use Apache::loncommon;
36: use Apache::lonhtmlcommon;
37: use LONCAPA::map();
38: use Apache::lonratedt();
39: use Apache::lonxml;
40: use Apache::lonclonecourse;
41: use Apache::lonnavmaps;
42: use Apache::lonnavdisplay();
43: use Apache::lonuserstate();
44: use HTML::Entities;
45: use HTML::TokeParser;
46: use GDBM_File;
47: use Apache::lonlocal;
48: use Cwd;
49: use LONCAPA qw(:DEFAULT :match);
50:
51: my $iconpath;
52:
53: my %hash;
54:
55: my $hashtied;
56: my %alreadyseen=();
57:
58: my $hadchanges;
59:
60:
61: my %help=();
62:
63:
64: sub mapread {
65: my ($coursenum,$coursedom,$map)=@_;
66: return
67: &LONCAPA::map::mapread('/uploaded/'.$coursedom.'/'.$coursenum.'/'.
68: $map);
69: }
70:
71: sub storemap {
72: my ($coursenum,$coursedom,$map)=@_;
73: my ($outtext,$errtext)=
74: &LONCAPA::map::storemap('/uploaded/'.$coursedom.'/'.$coursenum.'/'.
75: $map,1);
76: if ($errtext) { return ($errtext,2); }
77:
78: $hadchanges=1;
79: return ($errtext,0);
80: }
81:
82:
83:
84: sub authorhosts {
85: my %outhash=();
86: my $home=0;
87: my $other=0;
88: foreach my $key (keys(%env)) {
89: if ($key=~/^user\.role\.(au|ca)\.(.+)$/) {
90: my $role=$1;
91: my $realm=$2;
92: my ($start,$end)=split(/\./,$env{$key});
93: if (($start) && ($start>time)) { next; }
94: if (($end) && (time>$end)) { next; }
95: my ($ca,$cd);
96: if ($1 eq 'au') {
97: $ca=$env{'user.name'};
98: $cd=$env{'user.domain'};
99: } else {
100: ($cd,$ca)=($realm=~/^\/($match_domain)\/($match_username)$/);
101: }
102: my $allowed=0;
103: my $myhome=&Apache::lonnet::homeserver($ca,$cd);
104: my @ids=&Apache::lonnet::current_machine_ids();
105: foreach my $id (@ids) {
106: if ($id eq $myhome) {
107: $allowed=1;
108: last;
109: }
110: }
111: if ($allowed) {
112: $home++;
113: $outhash{'home_'.$ca.':'.$cd}=1;
114: } else {
115: $outhash{'otherhome_'.$ca.':'.$cd}=$myhome;
116: $other++;
117: }
118: }
119: }
120: return ($home,$other,%outhash);
121: }
122:
123:
124: sub clean {
125: my ($title)=@_;
126: $title=~s/[^\w\/\!\$\%\^\*\-\_\=\+\;\:\,\\\|\`\~]+/\_/gs;
127: return $title;
128: }
129:
130:
131:
132: sub dumpcourse {
133: my ($r) = @_;
134: my $crstype = &Apache::loncommon::course_type();
135: $r->print(&Apache::loncommon::start_page('Dump '.$crstype.' Content to Authoring Space')."\n".
136: &Apache::lonhtmlcommon::breadcrumbs('Dump '.$crstype.' Content to Authoring Space')."\n");
137: $r->print(&startContentScreen('tools'));
138: my ($home,$other,%outhash)=&authorhosts();
139: unless ($home) {
140: $r->print(&endContentScreen());
141: return '';
142: }
143: my $origcrsid=$env{'request.course.id'};
144: my %origcrsdata=&Apache::lonnet::coursedescription($origcrsid);
145: if (($env{'form.authorspace'}) && ($env{'form.authorfolder'}=~/\w/)) {
146: # Do the dumping
147: unless ($outhash{'home_'.$env{'form.authorspace'}}) {
148: $r->print(&endContentScreen());
149: return '';
150: }
151: my ($ca,$cd)=split(/\@/,$env{'form.authorspace'});
152: $r->print('<h3>'.&mt('Copying Files').'</h3>');
153: my $title=$env{'form.authorfolder'};
154: $title=&clean($title);
155: my %replacehash=();
156: foreach my $key (keys(%env)) {
157: if ($key=~/^form\.namefor\_(.+)/) {
158: $replacehash{$1}=$env{$key};
159: }
160: }
161: my $crs='/uploaded/'.$env{'request.course.id'}.'/';
162: $crs=~s/\_/\//g;
163: foreach my $item (keys(%replacehash)) {
164: my $newfilename=$title.'/'.$replacehash{$item};
165: $newfilename=~s/\.(\w+)$//;
166: my $ext=$1;
167: $newfilename=&clean($newfilename);
168: $newfilename.='.'.$ext;
169: my @dirs=split(/\//,$newfilename);
170: my $path=$r->dir_config('lonDocRoot')."/priv/$cd/$ca";
171: my $makepath=$path;
172: my $fail=0;
173: for (my $i=0;$i<$#dirs;$i++) {
174: $makepath.='/'.$dirs[$i];
175: unless (-e $makepath) {
176: unless(mkdir($makepath,0777)) { $fail=1; }
177: }
178: }
179: $r->print('<br /><tt>'.$item.'</tt> => <tt>'.$newfilename.'</tt>: ');
180: if (my $fh=Apache::File->new('>'.$path.'/'.$newfilename)) {
181: if ($item=~/\.(sequence|page|html|htm|xml|xhtml)$/) {
182: print $fh &Apache::lonclonecourse::rewritefile(
183: &Apache::lonclonecourse::readfile($env{'request.course.id'},$item),
184: (%replacehash,$crs => '')
185: );
186: } else {
187: print $fh
188: &Apache::lonclonecourse::readfile($env{'request.course.id'},$item);
189: }
190: $fh->close();
191: } else {
192: $fail=1;
193: }
194: if ($fail) {
195: $r->print('<span class="LC_error">'.&mt('fail').'</span>');
196: } else {
197: $r->print('<span class="LC_success">'.&mt('ok').'</span>');
198: }
199: }
200: } else {
201: $r->print(&mt('Searching ...').'<br />');
202: $r->rflush();
203: # Input form
204: $r->print('<form name="dumpdoc" action="" method="post">'."\n");
205: unless ($home==1) {
206: $r->print('<div class="LC_left_float">'.
207: '<fieldset><legend>'.
208: &mt('Select the Authoring Space').
209: '</legend><select name="authorspace">');
210: }
211: foreach my $key (sort(keys(%outhash))) {
212: if ($key=~/^home_(.+)$/) {
213: if ($home==1) {
214: $r->print(
215: '<input type="hidden" name="authorspace" value="'.$1.'" />');
216: } else {
217: $r->print('<option value="'.$1.'">'.$1.' - '.
218: &Apache::loncommon::plainname(split(/\:/,$1)).'</option>');
219: }
220: }
221: }
222: unless ($home==1) {
223: $r->print('</select></fieldset></div>'."\n");
224: }
225: my $title=$origcrsdata{'description'};
226: $title=~s/[\/\s]+/\_/gs;
227: $title=&clean($title);
228: $r->print('<div class="LC_left_float">'.
229: '<fieldset><legend>'.&mt('Folder in Authoring Space').'</legend>'.
230: '<input type="text" size="50" name="authorfolder" value="'.
231: $title.'" />'.
232: '</fieldset></div><br clear="all" />'."\n");
233: &tiehash();
234: $r->print('<h4>'.&mt('Filenames in Authoring Space').'</h4>'
235: .&Apache::loncommon::start_data_table()
236: .&Apache::loncommon::start_data_table_header_row()
237: .'<th>'.&mt('Internal Filename').'</th>'
238: .'<th>'.&mt('Title').'</th>'
239: .'<th>'.&mt('Save as ...').'</th>'
240: .&Apache::loncommon::end_data_table_header_row());
241: foreach my $file (&Apache::lonclonecourse::crsdirlist($origcrsid,'userfiles')) {
242: $r->print(&Apache::loncommon::start_data_table_row()
243: .'<td>'.$file.'</td>');
244: my ($ext)=($file=~/\.(\w+)$/);
245: my $title=$hash{'title_'.$hash{
246: 'ids_/uploaded/'.$origcrsdata{'domain'}.'/'.$origcrsdata{'num'}.'/'.$file}};
247: $r->print('<td>'.($title?$title:' ').'</td>');
248: if (!$title) {
249: $title=$file;
250: } else {
251: $title=~s|/|_|g;
252: }
253: $title=~s/\.(\w+)$//;
254: $title=&clean($title);
255: $title.='.'.$ext;
256: $r->print("\n<td><input type='text' size='60' name='namefor_".$file."' value='".$title."' /></td>"
257: .&Apache::loncommon::end_data_table_row());
258: }
259: $r->print(&Apache::loncommon::end_data_table());
260: &untiehash();
261: $r->print(
262: '<p><input type="submit" name="dumpcourse" value="'.&mt("Dump $crstype Content").'" /></p></form>');
263: }
264: $r->print(&endContentScreen());
265: }
266:
267: sub group_import {
268: my ($coursenum, $coursedom, $folder, $container, $caller, @files) = @_;
269:
270: while (@files) {
271: my ($name, $url, $residx) = @{ shift(@files) };
272: if (($url =~ m{^/uploaded/\Q$coursedom\E/\Q$coursenum\E/(default_\d+\.)(page|sequence)$})
273: && ($caller eq 'londocs')
274: && (!&Apache::lonnet::stat_file($url))) {
275:
276: my $errtext = '';
277: my $fatal = 0;
278: my $newmapstr = '<map>'."\n".
279: '<resource id="1" src="" type="start"></resource>'."\n".
280: '<link from="1" to="2" index="1"></link>'."\n".
281: '<resource id="2" src="" type="finish"></resource>'."\n".
282: '</map>';
283: $env{'form.output'}=$newmapstr;
284: my $result=&Apache::lonnet::finishuserfileupload($coursenum,$coursedom,
285: 'output',$1.$2);
286: if ($result != m|^/uploaded/|) {
287: $errtext.='Map not saved: A network error occurred when trying to save the new map. ';
288: $fatal = 2;
289: }
290: if ($fatal) {
291: return ($errtext,$fatal);
292: }
293: }
294: if ($url) {
295: if (!$residx
296: || defined($LONCAPA::map::zombies[$residx])) {
297: $residx = &LONCAPA::map::getresidx($url,$residx);
298: push(@LONCAPA::map::order, $residx);
299: }
300: my $ext = 'false';
301: if ($url=~m{^http://} || $url=~m{^https://}) { $ext = 'true'; }
302: $url = &LONCAPA::map::qtunescape($url);
303: $name = &LONCAPA::map::qtunescape($name);
304: $LONCAPA::map::resources[$residx] =
305: join(':', ($name, $url, $ext, 'normal', 'res'));
306: }
307: }
308: return &storemap($coursenum, $coursedom, $folder.'.'.$container);
309: }
310:
311: sub breadcrumbs {
312: my ($allowed,$crstype)=@_;
313: &Apache::lonhtmlcommon::clear_breadcrumbs();
314: my (@folders);
315: if ($env{'form.pagepath'}) {
316: @folders = split('&',$env{'form.pagepath'});
317: } else {
318: @folders=split('&',$env{'form.folderpath'});
319: }
320: my $folderpath;
321: my $cpinfo='';
322: my $plain='';
323: my $randompick=-1;
324: my $isencrypted=0;
325: my $ishidden=0;
326: my $is_random_order=0;
327: while (@folders) {
328: my $folder=shift(@folders);
329: my $foldername=shift(@folders);
330: if ($folderpath) {$folderpath.='&';}
331: $folderpath.=$folder.'&'.$foldername;
332: my $url;
333: if ($allowed) {
334: $url = '/adm/coursedocs?folderpath=';
335: } else {
336: $url = '/adm/supplemental?folderpath=';
337: }
338: $url .= &escape($folderpath);
339: my $name=&unescape($foldername);
340: # randompick number, hidden, encrypted, random order, is appended with ":"s to the foldername
341: $name=~s/\:(\d*)\:(\w*)\:(\w*):(\d*)$//;
342: if ($1 ne '') {
343: $randompick=$1;
344: } else {
345: $randompick=-1;
346: }
347: if ($2) { $ishidden=1; }
348: if ($3) { $isencrypted=1; }
349: if ($4 ne '') { $is_random_order = 1; }
350: if ($folder eq 'supplemental') {
351: $name = &mt('Supplemental '.$crstype.' Content');
352: }
353: &Apache::lonhtmlcommon::add_breadcrumb(
354: {'href'=>$url.$cpinfo,
355: 'title'=>$name,
356: 'text'=>$name,
357: 'no_mt'=>1,
358: });
359: $plain.=$name.' > ';
360: }
361: $plain=~s/\>\;\s*$//;
362: return (&Apache::lonhtmlcommon::breadcrumbs(undef,undef,0,'nohelp',
363: undef, undef, 1 ),$randompick,$ishidden,
364: $isencrypted,$plain,$is_random_order);
365: }
366:
367: sub log_docs {
368: return &Apache::lonnet::instructor_log('docslog',@_);
369: }
370:
371: {
372: my @oldresources=();
373: my @oldorder=();
374: my $parmidx;
375: my %parmaction=();
376: my %parmvalue=();
377: my $changedflag;
378:
379: sub snapshotbefore {
380: @oldresources=@LONCAPA::map::resources;
381: @oldorder=@LONCAPA::map::order;
382: $parmidx=undef;
383: %parmaction=();
384: %parmvalue=();
385: $changedflag=0;
386: }
387:
388: sub remember_parms {
389: my ($idx,$parameter,$action,$value)=@_;
390: $parmidx=$idx;
391: $parmaction{$parameter}=$action;
392: $parmvalue{$parameter}=$value;
393: $changedflag=1;
394: }
395:
396: sub log_differences {
397: my ($plain)=@_;
398: my %storehash=('folder' => $plain,
399: 'currentfolder' => $env{'form.folder'});
400: if ($parmidx) {
401: $storehash{'parameter_res'}=$oldresources[$parmidx];
402: foreach my $parm (keys(%parmaction)) {
403: $storehash{'parameter_action_'.$parm}=$parmaction{$parm};
404: $storehash{'parameter_value_'.$parm}=$parmvalue{$parm};
405: }
406: }
407: my $maxidx=$#oldresources;
408: if ($#LONCAPA::map::resources>$#oldresources) {
409: $maxidx=$#LONCAPA::map::resources;
410: }
411: for (my $idx=0; $idx<=$maxidx; $idx++) {
412: if ($LONCAPA::map::resources[$idx] ne $oldresources[$idx]) {
413: $storehash{'before_resources_'.$idx}=$oldresources[$idx];
414: $storehash{'after_resources_'.$idx}=$LONCAPA::map::resources[$idx];
415: $changedflag=1;
416: }
417: if ($LONCAPA::map::order[$idx] ne $oldorder[$idx]) {
418: $storehash{'before_order_res_'.$idx}=$oldresources[$oldorder[$idx]];
419: $storehash{'after_order_res_'.$idx}=$LONCAPA::map::resources[$LONCAPA::map::order[$idx]];
420: $changedflag=1;
421: }
422: }
423: $storehash{'maxidx'}=$maxidx;
424: if ($changedflag) { &log_docs(\%storehash); }
425: }
426: }
427:
428: sub docs_change_log {
429: my ($r,$coursenum,$coursedom,$folder,$allowed,$crstype,$iconpath)=@_;
430: my $supplementalflag=($env{'form.folderpath'}=~/^supplemental/);
431: my $js = '<script type="text/javascript">'."\n".
432: '// <![CDATA['."\n".
433: &Apache::loncommon::display_filter_js('docslog')."\n".
434: &editing_js($env{'user.domain'},$env{'user.name'},$supplementalflag)."\n".
435: &history_tab_js()."\n".
436: &Apache::lonratedt::editscript('simple')."\n".
437: '// ]]>'."\n".
438: '</script>'."\n";
439: $r->print(&Apache::loncommon::start_page('Content Change Log',$js));
440: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Content Change Log'));
441: $r->print(&startContentScreen(($supplementalflag?'suppdocs':'docs')));
442: my %orderhash;
443: my $container='sequence';
444: my $pathitem;
445: if ($env{'form.pagepath'}) {
446: $container='page';
447: $pathitem = '<input type="hidden" name="pagepath" value="'.
448: &HTML::Entities::encode($env{'form.pagepath'},'<>&"').'" />';
449: } else {
450: my $folderpath=$env{'form.folderpath'};
451: if ($folderpath eq '') {
452: $folderpath = 'default&'.&escape(&mt('Main '.$crstype.' Documents'));
453: }
454: $pathitem = '<input type="hidden" name="folderpath" value="'.&HTML::Entities::encode($folderpath,'<>&"').'" />';
455: }
456: my $readfile="/uploaded/$coursedom/$coursenum/$folder.$container";
457: my $jumpto = $readfile;
458: $jumpto =~ s{^/}{};
459: my $tid = 1;
460: if ($supplementalflag) {
461: $tid = 2;
462: }
463: my ($breadcrumbtrail) = &breadcrumbs($allowed,$crstype);
464: $r->print($breadcrumbtrail.
465: &generate_edit_table($tid,\%orderhash,undef,$iconpath,$jumpto,
466: $readfile));
467: my %docslog=&Apache::lonnet::dump('nohist_docslog',
468: $env{'course.'.$env{'request.course.id'}.'.domain'},
469: $env{'course.'.$env{'request.course.id'}.'.num'});
470:
471: if ((keys(%docslog))[0]=~/^error\:/) { undef(%docslog); }
472:
473: my %saveable_parameters = ('show' => 'scalar',);
474: &Apache::loncommon::store_course_settings('docs_log',
475: \%saveable_parameters);
476: &Apache::loncommon::restore_course_settings('docs_log',
477: \%saveable_parameters);
478: if (!$env{'form.show'}) { $env{'form.show'}=10; }
479: # FIXME: internationalization seems wrong here
480: my %lt=('hiddenresource' => 'Resources hidden',
481: 'encrypturl' => 'URL hidden',
482: 'randompick' => 'Randomly pick',
483: 'randomorder' => 'Randomly ordered',
484: 'set' => 'set to',
485: 'del' => 'deleted');
486: my $filter = &Apache::loncommon::display_filter('docslog')."\n".
487: $pathitem."\n".
488: '<input type="hidden" name="folder" value="'.$env{'form.folder'}.'" />'.
489: (' 'x2).'<input type="submit" value="'.&mt('Display').'" />';
490: $r->print('<div class="LC_left_float">'.
491: '<fieldset><legend>'.&mt('Display of Content Changes').'</legend>'."\n".
492: &makedocslogform($filter,1).
493: '</fieldset></div><br clear="all" />');
494: $r->print(&Apache::loncommon::start_data_table().&Apache::loncommon::start_data_table_header_row().
495: '<th>'.&mt('Time').'</th><th>'.&mt('User').'</th><th>'.&mt('Folder').'</th><th>'.&mt('Before').'</th><th>'.
496: &mt('After').'</th>'.
497: &Apache::loncommon::end_data_table_header_row());
498: my $shown=0;
499: foreach my $id (sort { $docslog{$b}{'exe_time'}<=>$docslog{$a}{'exe_time'} } (keys(%docslog))) {
500: if ($env{'form.displayfilter'} eq 'currentfolder') {
501: if ($docslog{$id}{'logentry'}{'currentfolder'} ne $folder) { next; }
502: }
503: my @changes=keys(%{$docslog{$id}{'logentry'}});
504: if ($env{'form.displayfilter'} eq 'containing') {
505: my $wholeentry=$docslog{$id}{'exe_uname'}.':'.$docslog{$id}{'exe_udom'}.':'.
506: &Apache::loncommon::plainname($docslog{$id}{'exe_uname'},$docslog{$id}{'exe_udom'});
507: foreach my $key (@changes) {
508: $wholeentry.=':'.$docslog{$id}{'logentry'}{$key};
509: }
510: if ($wholeentry!~/\Q$env{'form.containingphrase'}\E/i) { next; }
511: }
512: my $count = 0;
513: my $time =
514: &Apache::lonlocal::locallocaltime($docslog{$id}{'exe_time'});
515: my $plainname =
516: &Apache::loncommon::plainname($docslog{$id}{'exe_uname'},
517: $docslog{$id}{'exe_udom'});
518: my $about_me_link =
519: &Apache::loncommon::aboutmewrapper($plainname,
520: $docslog{$id}{'exe_uname'},
521: $docslog{$id}{'exe_udom'});
522: my $send_msg_link='';
523: if ((($docslog{$id}{'exe_uname'} ne $env{'user.name'})
524: || ($docslog{$id}{'exe_udom'} ne $env{'user.domain'}))) {
525: $send_msg_link ='<br />'.
526: &Apache::loncommon::messagewrapper(&mt('Send message'),
527: $docslog{$id}{'exe_uname'},
528: $docslog{$id}{'exe_udom'});
529: }
530: $r->print(&Apache::loncommon::start_data_table_row());
531: $r->print('<td>'.$time.'</td>
532: <td>'.$about_me_link.
533: '<br /><tt>'.$docslog{$id}{'exe_uname'}.
534: ':'.$docslog{$id}{'exe_udom'}.'</tt>'.
535: $send_msg_link.'</td><td>'.
536: $docslog{$id}{'logentry'}{'folder'}.'</td><td>');
537: my $is_supp = 0;
538: if ($docslog{$id}{'logentry'}{'currentfolder'} =~ /^supplemental/) {
539: $is_supp = 1;
540: }
541: # Before
542: for (my $idx=0;$idx<=$docslog{$id}{'logentry'}{'maxidx'};$idx++) {
543: my $oldname=(split(/\:/,$docslog{$id}{'logentry'}{'before_resources_'.$idx}))[0];
544: my $newname=(split(/\:/,$docslog{$id}{'logentry'}{'after_resources_'.$idx}))[0];
545: if ($oldname ne $newname) {
546: my $shown = &LONCAPA::map::qtescape($oldname);
547: if ($is_supp) {
548: $shown = &Apache::loncommon::parse_supplemental_title($shown);
549: }
550: $r->print($shown);
551: }
552: }
553: $r->print('<ul>');
554: for (my $idx=0;$idx<=$docslog{$id}{'logentry'}{'maxidx'};$idx++) {
555: if ($docslog{$id}{'logentry'}{'before_order_res_'.$idx}) {
556: my $shown = &LONCAPA::map::qtescape((split(/\:/,$docslog{$id}{'logentry'}{'before_order_res_'.$idx}))[0]);
557: if ($is_supp) {
558: $shown = &Apache::loncommon::parse_supplemental_title($shown);
559: }
560: $r->print('<li>'.$shown.'</li>');
561: }
562: }
563: $r->print('</ul>');
564: # After
565: $r->print('</td><td>');
566:
567: for (my $idx=0;$idx<=$docslog{$id}{'logentry'}{'maxidx'};$idx++) {
568: my $oldname=(split(/\:/,$docslog{$id}{'logentry'}{'before_resources_'.$idx}))[0];
569: my $newname=(split(/\:/,$docslog{$id}{'logentry'}{'after_resources_'.$idx}))[0];
570: if ($oldname ne '' && $oldname ne $newname) {
571: my $shown = &LONCAPA::map::qtescape($newname);
572: if ($is_supp) {
573: $shown = &Apache::loncommon::parse_supplemental_title(&LONCAPA::map::qtescape($newname));
574: }
575: $r->print($shown);
576: }
577: }
578: $r->print('<ul>');
579: for (my $idx=0;$idx<=$docslog{$id}{'logentry'}{'maxidx'};$idx++) {
580: if ($docslog{$id}{'logentry'}{'after_order_res_'.$idx}) {
581: my $shown = &LONCAPA::map::qtescape((split(/\:/,$docslog{$id}{'logentry'}{'after_order_res_'.$idx}))[0]);
582: if ($is_supp) {
583: $shown = &Apache::loncommon::parse_supplemental_title($shown);
584: }
585: $r->print('<li>'.$shown.'</li>');
586: }
587: }
588: $r->print('</ul>');
589: if ($docslog{$id}{'logentry'}{'parameter_res'}) {
590: $r->print(&LONCAPA::map::qtescape((split(/\:/,$docslog{$id}{'logentry'}{'parameter_res'}))[0]).':<ul>');
591: foreach my $parameter ('randompick','hiddenresource','encrypturl','randomorder') {
592: if ($docslog{$id}{'logentry'}{'parameter_action_'.$parameter}) {
593: # FIXME: internationalization seems wrong here
594: $r->print('<li>'.
595: &mt($lt{$parameter}.' '.$lt{$docslog{$id}{'logentry'}{'parameter_action_'.$parameter}}.' [_1]',
596: $docslog{$id}{'logentry'}{'parameter_value_'.$parameter})
597: .'</li>');
598: }
599: }
600: $r->print('</ul>');
601: }
602: # End
603: $r->print('</td>'.&Apache::loncommon::end_data_table_row());
604: $shown++;
605: if (!($env{'form.show'} eq &mt('all')
606: || $shown<=$env{'form.show'})) { last; }
607: }
608: $r->print(&Apache::loncommon::end_data_table()."\n".
609: &makesimpleeditform($pathitem)."\n".
610: '</div></div>');
611: $r->print(&endContentScreen());
612: }
613:
614: sub update_paste_buffer {
615: my ($coursenum,$coursedom) = @_;
616:
617: return if (!defined($env{'form.markcopy'}));
618: return if (!defined($env{'form.copyfolder'}));
619: return if ($env{'form.markcopy'} < 0);
620:
621: my ($errtext,$fatal) = &mapread($coursenum,$coursedom,
622: $env{'form.copyfolder'});
623:
624: return if ($fatal);
625:
626: # Mark for copying
627: my ($title,$url)=split(':',$LONCAPA::map::resources[$LONCAPA::map::order[$env{'form.markcopy'}]]);
628: if (&is_supplemental_title($title)) {
629: &Apache::lonnet::appenv({'docs.markedcopy_supplemental' => $title});
630: ($title) = &Apache::loncommon::parse_supplemental_title($title);
631: } elsif ($env{'docs.markedcopy_supplemental'}) {
632: &Apache::lonnet::delenv('docs.markedcopy_supplemental');
633: }
634: $url=~s{http(:|:)//https(:|:)//}{https$2//};
635:
636: &Apache::lonnet::appenv({'docs.markedcopy_title' => $title,
637: 'docs.markedcopy_url' => $url});
638: delete($env{'form.markcopy'});
639: }
640:
641: sub print_paste_buffer {
642: my ($r,$container,$folder) = @_;
643: return if (!defined($env{'docs.markedcopy_url'}));
644:
645: my $is_external;
646: my $extension = (split(/\./,$env{'docs.markedcopy_url'}))[-1];
647: if ($env{'docs.markedcopy_url'} =~ m{^(?:/adm/wrapper/ext|(?:http|https)(?::|:))//} ) {
648: $is_external = 1;
649: }
650:
651: my $canpaste;
652: if ($folder =~ /^supplemental/) {
653: $canpaste = &supp_pasteable($env{'docs.markedcopy_url'});
654: } else {
655: $canpaste = 1;
656: }
657:
658: my $pasteinfo;
659: if ($canpaste) {
660: $pasteinfo = '<form name="pasteform" action="/adm/coursedocs" method="post">'
661: .'<input type="submit" name="pastemarked" value="'.&mt('Paste').'" /> ';
662: } else {
663: $pasteinfo = &mt('Paste buffer contains:').' ';
664: }
665:
666: $r->print('<fieldset>'
667: .'<legend>'.&mt('Clipboard').'</legend>'
668: .$pasteinfo
669: );
670:
671: my $type;
672: if ($is_external) {
673: $type = &mt('External Resource');
674: $r->print($type.': '.
675: &LONCAPA::map::qtescape($env{'docs.markedcopy_title'}).' ('.
676: &LONCAPA::map::qtescape($env{'docs.markedcopy_url'}).')');
677: } else {
678: my $icon = &Apache::loncommon::icon($extension);
679: if ($extension eq 'sequence' &&
680: $env{'docs.markedcopy_url'} =~ m{/default_\d+\.sequence$ }x) {
681: $icon = &Apache::loncommon::lonhttpdurl($r->dir_config('lonIconsURL'));
682: $icon .= '/navmap.folder.closed.gif';
683: }
684: $icon = '<img src="'.$icon.'" alt="" class="LC_icon" />';
685: $r->print($icon.$type.': '. &Apache::loncommon::parse_supplemental_title(&LONCAPA::map::qtescape($env{'docs.markedcopy_title'})));
686: }
687: if ($canpaste) {
688: if ($container eq 'page') {
689: $r->print('
690: <input type="hidden" name="pagepath" value="'.&HTML::Entities::encode($env{'form.pagepath'},'<>&"').'" />
691: <input type="hidden" name="pagesymb" value="'.&HTML::Entities::encode($env{'form.pagesymb'},'<>&"').'" />
692: ');
693: } else {
694: $r->print('
695: <input type="hidden" name="folderpath" value="'.&HTML::Entities::encode($env{'form.folderpath'},'<>&"').'" />
696: ');
697: }
698: $r->print('</form>');
699: } else {
700: $r->print('<br /><p class="LC_info">'.&mt('Paste into Supplemental Content unavailable for this type of content.').'</p>');
701: }
702: $r->print('</fieldset>');
703: }
704:
705: sub supp_pasteable {
706: my ($url) = @_;
707: if (($url =~ m{^(?:/adm/wrapper/ext|(?:http|https)(?::|:))//}) ||
708: (($url =~ /\.sequence$/) && ($url =~ m{^/uploaded/})) ||
709: ($url =~ m{^/uploaded/$match_domain/$match_courseid/(docs|supplemental)/(default|\d+)/\d+/}) ||
710: ($url =~ m{^/adm/$match_domain/$match_username/aboutme}) ||
711: ($url =~ m{^/public/$match_domain/$match_courseid/syllabus})) {
712: return 1;
713: }
714: return;
715: }
716:
717: sub do_paste_from_buffer {
718: my ($coursenum,$coursedom,$folder) = @_;
719:
720: if (!$env{'form.pastemarked'}) {
721: return;
722: }
723:
724: # Supplemental content may only include certain types of content
725: if ($folder =~ /^supplemental/) {
726: unless (&supp_pasteable($env{'docs.markedcopy_url'})) {
727: return &mt('Paste failed: content type is not supported within Supplemental Content');
728: }
729: }
730:
731: # paste resource to end of list
732: my $url=&LONCAPA::map::qtescape($env{'docs.markedcopy_url'});
733: my $title=&LONCAPA::map::qtescape($env{'docs.markedcopy_title'});
734: # Maps need to be copied first
735: my ($oldurl,%removefrommap,%addedmaps,%rewrites,%copies,%dbcopies,%zombies,%params,
736: %moves,$srcdom,$srcnum);
737: $oldurl = $url;
738: if ($url=~/\.(page|sequence)$/) {
739: # If pasting a map, check if map contains other maps
740: &contained_map_check($url,$folder,\%removefrommap,\%addedmaps);
741: if (keys(%addedmaps) > 0) {
742: &reinit_role($coursedom,$coursenum,$env{"course.$env{'request.course.id'}.home"});
743: }
744: my %allmaps;
745: my $navmap = Apache::lonnavmaps::navmap->new();
746: if (defined($navmap)) {
747: foreach my $res ($navmap->retrieveResources(undef,sub { $_[0]->is_map() },1,0,1)) {
748: $allmaps{$res->src()} = 1;
749: }
750: }
751: if ($url=~ m{^/uploaded/}) {
752: $title=&mt('Copy of').' '.$title;
753: }
754: my $newid=$$.int(rand(100)).time;
755: my ($oldid,$ext) = ($url=~/^(.+)\.(\w+)$/);
756: if ($oldid =~ m{^(/uploaded/$match_domain/$match_courseid/)(\D+)(\d+)$}) {
757: my $path = $1;
758: my $prefix = $2;
759: my $ancestor = $3;
760: if (length($ancestor) > 10) {
761: $ancestor = substr($ancestor,-10,10);
762: }
763: $oldid = $path.$prefix.$ancestor;
764: my $counter = 0;
765: my $newurl=$oldid.$newid.'.'.$ext;
766: my $is_unique = &uniqueness_check($newurl);
767: if ($allmaps{$newurl}) {
768: $is_unique = 0;
769: }
770: while (!$is_unique && $allmaps{$newurl} && $counter < 100) {
771: $counter ++;
772: $newid ++;
773: $newurl = $oldid.$newid;
774: $is_unique = &uniqueness_check($newurl);
775: }
776: if ($is_unique) {
777: if ($path =~ m{^/uploaded/($match_domain)/($match_courseid)/$}) {
778: $srcdom = $1;
779: $srcnum = $2;
780: if (($1 ne $coursedom) && ($2 ne $coursenum)) {
781: my $srcdom = $1;
782: my $srcnum = $2;
783: if ($env{"user.priv.cm./$srcdom/$srcnum"} =~ /\Q:mdc&F\E/) {
784: &url_paste_fixups($oldid,$ext,$coursedom,$coursenum,
785: \%allmaps, \%rewrites,\%copies,\%dbcopies,\%zombies,\%params);
786: } else {
787: return &mt('Paste failed: Item is from a different course which you do not have rights to edit');
788: }
789: }
790: }
791: } else {
792: if ($url=~/\.page$/) {
793: return &mt('Paste failed: an error occurred creating a unique URL for the composite page');
794: } else {
795: return &mt('Paste failed: an error occurred creating a unique URL for the folder');
796: }
797: }
798: my $storefn=$newurl;
799: $storefn=~s{^/\w+/$match_domain/$match_username/}{};
800: my $paste_map_result =
801: &Apache::lonclonecourse::writefile($env{'request.course.id'},$storefn,
802: &Apache::lonnet::getfile($url));
803: if ($paste_map_result eq '/adm/notfound.html') {
804: if ($url=~/\.page$/) {
805: return &mt('Paste failed: an error occurred saving the composite page');
806: } else {
807: return &mt('Paste failed: an error occurred saving the folder');
808: }
809: }
810: $url = $newurl;
811: } elsif ($url=~m {^/res/}) {
812: # published maps can only exists once, so remove it from paste buffer when done
813: &Apache::lonnet::delenv('docs.markedcopy');
814: if ($allmaps{$url}) {
815: return &mt('Paste failed: only one instance of a particular published sequence or page is allowed within each course.');
816: }
817: }
818: } elsif ($url =~ m{^/uploaded/($match_domain)/($match_courseid)/}) {
819: if (($1 ne $coursedom) || ($2 ne $coursenum)) {
820: $srcdom = $1;
821: $srcnum = $2;
822: unless ($env{"user.priv.cm./$srcdom/$srcnum"} =~ /\Q:mdc&F\E/) {
823: return &mt('Paste failed: Item is from a different course which you do not have rights to edit');
824: }
825: }
826: }
827: if ($url=~ m{/smppg$}) {
828: my $db_name = &Apache::lonsimplepage::get_db_name($url);
829: if ($db_name =~ /^smppage_/) {
830: #simple pages, need to copy the db contents to a new one.
831: my %contents=&Apache::lonnet::dump($db_name,$coursedom,$coursenum);
832: my $now = time();
833: $db_name =~ s{_\d*$ }{_$now}x;
834: my $result=&Apache::lonnet::put($db_name,\%contents,
835: $coursedom,$coursenum);
836: $url =~ s{/(\d*)/smppg$ }{/$now/smppg}x;
837: $title=&mt('Copy of').' '.$title;
838: }
839: }
840: my ($relpath,$oldprefix,$prefixchg);
841: if ($url =~ m{^/uploaded/$match_domain/$match_courseid/(docs|supplemental)/(.+)$}) {
842: $oldprefix = $1;
843: $relpath = $2;
844: if (($folder =~ /^supplemental/) && ($oldprefix eq 'docs')) {
845: $prefixchg = 1;
846: } elsif (($folder =~ /^default/) && ($oldprefix eq 'supplemental')) {
847: $prefixchg = 1;
848: }
849: }
850: $title = &LONCAPA::map::qtunescape($title);
851: my $ext='false';
852: if ($url=~m{^http(|s)://}) { $ext='true'; }
853: $url = &LONCAPA::map::qtunescape($url);
854: # Now insert the URL at the bottom
855: my $newidx = &LONCAPA::map::getresidx($url);
856: if ($relpath ne '') {
857: my ($prefix,$subdir,$rem) = ($relpath =~ m{^(default|\d+)/(\d+)/(.+)$});
858: my ($newloc,$newsubdir) = ($folder =~ /^(default|supplemental)_?(\d*)/);
859: my $newprefix = $newloc;
860: if ($newloc eq 'default') {
861: $newprefix = 'docs';
862: }
863: if ($newsubdir eq '') {
864: $newsubdir = 'default';
865: }
866: if (($prefixchg) || ($srcdom ne '') && ($srcnum ne '')) {
867: my $newpath = "$newprefix/$newsubdir/$newidx/$rem";
868: $url =
869: &Apache::lonclonecourse::writefile($env{'request.course.id'},$newpath,
870: &Apache::lonnet::getfile($oldurl));
871: if ($url eq '/adm/notfound.html') {
872: return &mt('Paste failed: an error occurred saving the file.');
873: } else {
874: my ($newsubpath) = ($newpath =~ m{^(.*/)[^/]*$});
875: $newsubpath =~ s{/+$}{/};
876: $moves{$oldurl} = $newsubpath;
877: }
878: }
879: }
880: my $noparams = 0;
881: if ((ref($params{$oldurl}) eq 'HASH') && ($relpath ne '') && ($folder =~ /^supplemental/)) {
882: $noparams = 1;
883: }
884: &apply_fixups($coursedom,$coursenum,$oldurl,$url,$noparams,\%rewrites,\%copies,
885: \%dbcopies,\%zombies,\%params,\%moves);
886: if ($env{'docs.markedcopy_supplemental'}) {
887: if ($folder =~ /^supplemental/) {
888: $title = $env{'docs.markedcopy_supplemental'};
889: } else {
890: (undef,undef,$title) =
891: &Apache::loncommon::parse_supplemental_title($env{'docs.markedcopy_supplemental'});
892: }
893: } else {
894: if ($folder=~/^supplemental/) {
895: $title=time.'___&&&___'.$env{'user.name'}.'___&&&___'.
896: $env{'user.domain'}.'___&&&___'.$title;
897: }
898: }
899:
900: $LONCAPA::map::resources[$newidx]= $title.':'.$url.':'.$ext.':normal:res';
901: push(@LONCAPA::map::order, $newidx);
902: return 'ok';
903: # Store the result
904: }
905:
906: sub dbcopy {
907: my ($url,$coursedom,$coursenum) = @_;
908: if ($url=~ m{/smppg$}) {
909: my $db_name = &Apache::lonsimplepage::get_db_name($url);
910: if ($db_name =~ /^smppage_/) {
911: #simple pages, need to copy the db contents to a new one.
912: my %contents=&Apache::lonnet::dump($db_name,$coursedom,$coursenum);
913: my $now = time();
914: $db_name =~ s{_\d*$ }{_$now}x;
915: my $result=&Apache::lonnet::put($db_name,\%contents,
916: $coursedom,$coursenum);
917: $url =~ s{/(\d*)/smppg$ }{/$now/smppg}x;
918: }
919: }
920: return $url;
921: }
922:
923: sub uniqueness_check {
924: my ($newurl) = @_;
925: my $unique = 1;
926: foreach my $res (@LONCAPA::map::order) {
927: my ($name,$url)=split(/\:/,$LONCAPA::map::resources[$res]);
928: $url=&LONCAPA::map::qtescape($url);
929: if ($newurl eq $url) {
930: $unique = 0;
931: last;
932: }
933: }
934: return $unique;
935: }
936:
937: sub contained_map_check {
938: my ($url,$folder,$removefrommap,$addedmaps) = @_;
939: my $content = &Apache::lonnet::getfile($url);
940: unless ($content eq '-1') {
941: my $parser = HTML::TokeParser->new(\$content);
942: $parser->attr_encoded(1);
943: while (my $token = $parser->get_token) {
944: next if ($token->[0] ne 'S');
945: if ($token->[1] eq 'resource') {
946: next if ($token->[2]->{'type'} eq 'zombie');
947: my $ressrc = $token->[2]->{'src'};
948: if ($folder =~ /^supplemental/) {
949: unless (&supp_pasteable($ressrc)) {
950: $removefrommap->{$url}{$token->[2]->{'id'}};
951: next;
952: }
953: }
954: if ($ressrc =~ /\.(sequence|page)$/) {
955: if (ref($addedmaps->{$ressrc}) eq 'ARRAY') {
956: push(@{$addedmaps->{$ressrc}},$url);
957: } else {
958: $addedmaps->{$ressrc} = [$url];
959: }
960: &contained_map_check($ressrc,$folder,$removefrommap,$addedmaps);
961: }
962: } elsif ($token->[1] !~ /^resource|map|link$/) {
963: if ($folder =~ /^supplemental/) {
964: $removefrommap->{$url}{$token->[1]};
965: }
966: }
967: }
968: }
969: return;
970: }
971:
972: sub reinit_role {
973: my ($cdom,$cnum,$chome) = @_;
974: my ($furl,$ferr) = &Apache::lonuserstate::readmap("$cdom/$cnum");
975: unless ($ferr) {
976: &Apache::loncommon::update_content_constraints($cdom,$cnum,$chome,$cdom.'_'.$cnum);
977: }
978: return;
979: }
980:
981: sub url_paste_fixups {
982: my ($oldurl,$ext,$cdom,$cnum,$allmaps,$rewrites,$copies,$dbcopies,$zombies,$params) = @_;
983: my $file = &Apache::lonnet::getfile("$oldurl.$ext");
984: return if ($file eq '-1');
985: my $parser = HTML::TokeParser->new(\$file);
986: $parser->attr_encoded(1);
987: while (my $token = $parser->get_token) {
988: next if ($token->[0] ne 'S');
989: if ($token->[1] eq 'resource') {
990: my $ressrc = $token->[2]->{'src'};
991: next if ($ressrc eq '');
992: next if ($token->[2]->{'type'} eq 'external');
993: my $id = $token->[2]->{'id'};
994: if ($token->[2]->{'type'} eq 'zombie') {
995: $zombies->{$oldurl}{$ressrc} = $id;
996: } elsif ($ressrc =~ m{^/uploaded/($match_domain)/($match_courseid)/(.+)}) {
997: my $srccdom = $1;
998: my $srccnum = $2;
999: my $rem = $3;
1000: if (($srccdom ne $cdom) || ($srccnum ne $cnum)) {
1001: if ($rem =~ /^(default|supplemental)(_?\d*).(sequence|page)$/) {
1002: $rewrites->{$oldurl}{$ressrc} = $id;
1003: &url_paste_fixups($ressrc,$3,$cdom,$cnum,$allmaps,$rewrites,$copies,$dbcopies,$zombies,$params);
1004: } else {
1005: $rewrites->{$oldurl}{$ressrc} = $id;
1006: $copies->{$oldurl}{$ressrc} = $id;
1007: }
1008: }
1009: } elsif ($ressrc =~ m{^/adm/($match_domain)/($match_courseid)/(.+)$}) {
1010: my $srccdom = $1;
1011: my $srccnum = $2;
1012: if (($srccdom ne $cdom) || ($srccnum ne $cnum)) {
1013: $rewrites->{$oldurl}{$ressrc} = $id;
1014: $dbcopies->{$oldurl}{$ressrc} = $id;
1015: }
1016: } elsif ($ressrc =~ m{^/public/($match_domain)/($match_courseid)/(.+)$}) {
1017: my $srccdom = $1;
1018: my $srccnum = $2;
1019: if (($srccdom ne $cdom) || ($srccnum ne $cnum)) {
1020: $rewrites->{$oldurl}{$ressrc} = $id;
1021: $dbcopies->{$oldurl}{$ressrc} = $id;
1022: }
1023: }
1024: } elsif ($token->[1] eq 'param') {
1025: my $to = $token->[2]->{'to'};
1026: if ($to ne '') {
1027: if (ref($params->{$oldurl}{$to}) eq 'ARRAY') {
1028: push (@{$params->{$oldurl}{$to}},$token->[2]->{'name'});
1029: } else {
1030: @{$params->{$oldurl}{$to}} = ($token->[2]->{'name'});
1031: }
1032: }
1033: }
1034: }
1035: return;
1036: }
1037:
1038: sub apply_fixups {
1039: my ($cdom,$cnum,$oldurl,$url,$noparams,$rewrites,$copies,$dbcopies,$zombies,$params,
1040: $moves) = @_;
1041: my (%newdb,%newdoc);
1042: if (ref($dbcopies->{$oldurl}) eq 'HASH') {
1043: foreach my $item (keys(%{$dbcopies->{$oldurl}})) {
1044: $newdb{$item} = &dbcopy($item);
1045: }
1046: }
1047: my @allcopies;
1048: if (ref($copies->{$oldurl}) eq 'HASH') {
1049: push(@allcopies,keys(%{$copies->{$oldurl}}));
1050: }
1051: if ((ref($moves) eq 'HASH') && (exists($moves->{$oldurl}))) {
1052: push(@allcopies,$oldurl);
1053: }
1054: if (@allcopies > 0) {
1055: foreach my $item (@allcopies) {
1056: my $content = &Apache::lonnet::getfile($item);
1057: unless ($content eq '-1') {
1058: my $mm = new File::MMagic;
1059: my $mimetype = $mm->checktype_contents($content);
1060: if ($mimetype eq 'text/html') {
1061: my (%allfiles,%codebase,$state);
1062: if (&Apache::lonnet::extract_embedded_items(undef,\%allfiles,\%codebase,\$content) eq 'ok') {
1063: my ($numexisting,$numpathchanges,$existing);
1064: (undef,$numexisting,$numpathchanges,$existing) =
1065: &Apache::loncommon::ask_for_embedded_content(
1066: '/adm/coursedocs',$state,\%allfiles,\%codebase,
1067: {'error_on_invalid_names' => 1,
1068: 'ignore_remote_references' => 1,
1069: 'docs_url' => $oldurl,
1070: 'context' => 'paste'});
1071: if ($numexisting > 0) {
1072: if (ref($existing) eq 'HASH') {
1073: my ($relpath) = ($item =~ m{^(/uploaded/$match_domain/$match_courseid/(?:docs|supplemental)/(?:default|\d+)/.*/)[^/]+$});
1074: foreach my $dep (keys(%{$existing})) {
1075: $dep =~ s{^\Q$relpath\E}{};
1076: my $depfile = $relpath.$dep;
1077: my $depstorefn;
1078: if ((ref($copies->{$oldurl}) eq 'HASH') &&
1079: ($copies->{$oldurl}{$item})) {
1080: $depstorefn = $relpath;
1081: $depstorefn =~s{^/\w+/$match_domain/$match_courseid/}{};
1082: } elsif ((ref($moves) eq 'HASH') &&
1083: (exists($moves->{$oldurl}))) {
1084: $depstorefn = $moves->{$oldurl};
1085: }
1086: $depstorefn .= $dep;
1087: my $depcontent = &Apache::lonnet::getfile($depfile);
1088: unless ($depcontent eq '-1') {
1089: &Apache::lonclonecourse::writefile($env{'request.course.id'},$depstorefn,$depcontent);
1090: }
1091: }
1092: }
1093: }
1094: }
1095: }
1096: my $storefn=$item;
1097: unless (exists($moves->{$oldurl})) {
1098: $storefn=~s{^/\w+/$match_domain/$match_courseid/}{};
1099: $newdoc{$item} = &Apache::lonclonecourse::writefile($env{'request.course.id'},$storefn,$content);
1100: }
1101: }
1102: }
1103: }
1104: if (((ref($rewrites->{$oldurl}) eq 'HASH') || (ref($zombies->{$oldurl}) eq 'HASH')) ||
1105: ($noparams) || (keys(%newdb) > 0) || (keys(%newdoc) > 0)) {
1106: my $map = &Apache::lonnet::getfile($url);
1107: my $newcontent;
1108: unless ($map eq '-1') {
1109: my $parser = HTML::TokeParser->new(\$map);
1110: $parser->attr_encoded(1);
1111: while (my $token = $parser->get_token) {
1112: if ($token->[0] eq 'S') {
1113: next if ($token->[2]->{'type'} eq 'zombie');
1114: next if (($token->[1] eq 'param') && $noparams);
1115: if ($token->[1] eq 'resource') {
1116: my $src = $token->[2]->{'src'};
1117: my $id = $token->[2]->{'id'};
1118: if (($rewrites->{$oldurl}{$src} eq $id) || ($newdb{$src} ne '')
1119: || ($newdoc{$src} ne '')) {
1120: if (ref($rewrites->{$oldurl}) eq 'HASH') {
1121: if ($rewrites->{$oldurl}{$src} eq $id) {
1122: $token->[2]->{'src'} =~ s{^(/uploaded|adm|public)/$match_domain/$match_courseid/}{$1/$cdom/$cnum};
1123: }
1124: } elsif ($newdb{$src} ne '') {
1125: $token->[2]->{'src'} = $newdb{$src};
1126: }
1127: $newcontent .= "<$token->[1] ";
1128: foreach my $attr (@{$token->[3]}) {
1129: $newcontent .= ' '.$attr.'="'.$token->[2]->{$attr},'"'
1130: }
1131: $newcontent .= ' />';
1132: } else {
1133: $newcontent .= $token->[4]."\n";
1134: }
1135: }
1136: } elsif ($token->[0] eq 'E') {
1137: $newcontent .= $token->[2]."\n";
1138: }
1139: }
1140: }
1141: my $storefn=$url;
1142: $storefn=~s{^/\w+/$match_domain/$match_courseid/}{};
1143: my $storeres =
1144: &Apache::lonclonecourse::writefile($env{'request.course.id'},$storefn,
1145: $newcontent);
1146: }
1147: return;
1148: }
1149:
1150: my %parameter_type = ( 'randompick' => 'int_pos',
1151: 'hiddenresource' => 'string_yesno',
1152: 'encrypturl' => 'string_yesno',
1153: 'randomorder' => 'string_yesno',);
1154: my $valid_parameters_re = join('|',keys(%parameter_type));
1155: # set parameters
1156: sub update_parameter {
1157:
1158: return 0 if ($env{'form.changeparms'} !~ /^($valid_parameters_re)$/);
1159:
1160: my $which = $env{'form.changeparms'};
1161: my $idx = $env{'form.setparms'};
1162: if ($env{'form.'.$which.'_'.$idx}) {
1163: my $value = ($which eq 'randompick') ? $env{'form.'.$which.'_'.$idx}
1164: : 'yes';
1165: &LONCAPA::map::storeparameter($idx, 'parameter_'.$which, $value,
1166: $parameter_type{$which});
1167: &remember_parms($idx,$which,'set',$value);
1168: } else {
1169: &LONCAPA::map::delparameter($idx,'parameter_'.$which);
1170:
1171: &remember_parms($idx,$which,'del');
1172: }
1173: return 1;
1174: }
1175:
1176:
1177: sub handle_edit_cmd {
1178: my ($coursenum,$coursedom) =@_;
1179: my ($cmd,$idx)=split('_',$env{'form.cmd'});
1180:
1181: my $ratstr = $LONCAPA::map::resources[$LONCAPA::map::order[$idx]];
1182: my ($title, $url, @rrest) = split(':', $ratstr);
1183:
1184: if ($cmd eq 'del') {
1185: if (($url=~m|/+uploaded/\Q$coursedom\E/\Q$coursenum\E/|) &&
1186: ($url!~/$LONCAPA::assess_page_seq_re/)) {
1187: &Apache::lonnet::removeuploadedurl($url);
1188: } else {
1189: &LONCAPA::map::makezombie($LONCAPA::map::order[$idx]);
1190: }
1191: splice(@LONCAPA::map::order, $idx, 1);
1192:
1193: } elsif ($cmd eq 'cut') {
1194: &LONCAPA::map::makezombie($LONCAPA::map::order[$idx]);
1195: splice(@LONCAPA::map::order, $idx, 1);
1196:
1197: } elsif ($cmd eq 'up'
1198: && ($idx) && (defined($LONCAPA::map::order[$idx-1]))) {
1199: @LONCAPA::map::order[$idx-1,$idx] = @LONCAPA::map::order[$idx,$idx-1];
1200:
1201: } elsif ($cmd eq 'down'
1202: && defined($LONCAPA::map::order[$idx+1])) {
1203: @LONCAPA::map::order[$idx+1,$idx] = @LONCAPA::map::order[$idx,$idx+1];
1204:
1205: } elsif ($cmd eq 'rename') {
1206:
1207: my $comment = &LONCAPA::map::qtunescape($env{'form.title'});
1208: if ($comment=~/\S/) {
1209: $LONCAPA::map::resources[$LONCAPA::map::order[$idx]]=
1210: $comment.':'.join(':', $url, @rrest);
1211: }
1212: # Devalidate title cache
1213: my $renamed_url=&LONCAPA::map::qtescape($url);
1214: &Apache::lonnet::devalidate_title_cache($renamed_url);
1215: } else {
1216: return 0;
1217: }
1218: return 1;
1219: }
1220:
1221: sub editor {
1222: my ($r,$coursenum,$coursedom,$folder,$allowed,$upload_output,$crstype,
1223: $supplementalflag,$orderhash,$iconpath)=@_;
1224: my $container= ($env{'form.pagepath'}) ? 'page'
1225: : 'sequence';
1226:
1227: my ($breadcrumbtrail,$randompick,$ishidden,$isencrypted,$plain,$is_random_order) =
1228: &breadcrumbs($allowed,$crstype);
1229: $r->print($breadcrumbtrail);
1230:
1231: my $jumpto = "uploaded/$coursedom/$coursenum/$folder.$container";
1232:
1233: unless ($allowed) {
1234: $randompick = -1;
1235: }
1236:
1237: my ($errtext,$fatal) = &mapread($coursenum,$coursedom,
1238: $folder.'.'.$container);
1239: return $errtext if ($fatal);
1240:
1241: if ($#LONCAPA::map::order<1) {
1242: my $idx=&LONCAPA::map::getresidx();
1243: if ($idx<=0) { $idx=1; }
1244: $LONCAPA::map::order[0]=$idx;
1245: $LONCAPA::map::resources[$idx]='';
1246: }
1247:
1248: # ------------------------------------------------------------ Process commands
1249:
1250: # ---------------- if they are for this folder and user allowed to make changes
1251: if (($allowed) && ($env{'form.folder'} eq $folder)) {
1252: # set parameters and change order
1253: &snapshotbefore();
1254:
1255: if (&update_parameter()) {
1256: ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container);
1257: return $errtext if ($fatal);
1258: }
1259:
1260: if ($env{'form.newpos'} && $env{'form.currentpos'}) {
1261: # change order
1262: my $res = splice(@LONCAPA::map::order,$env{'form.currentpos'}-1,1);
1263: splice(@LONCAPA::map::order,$env{'form.newpos'}-1,0,$res);
1264:
1265: ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container);
1266: return $errtext if ($fatal);
1267: }
1268:
1269: if ($env{'form.pastemarked'}) {
1270: my $paste_res =
1271: &do_paste_from_buffer($coursenum,$coursedom,$folder);
1272: if ($paste_res eq 'ok') {
1273: ($errtext,$fatal) = &storemap($coursenum,$coursedom,$folder.'.'.$container);
1274: return $errtext if ($fatal);
1275: } elsif ($paste_res ne '') {
1276: $r->print('<p><span class="LC_error">'.$paste_res.'</span></p>');
1277: }
1278: }
1279:
1280: $r->print($upload_output);
1281:
1282: if (&handle_edit_cmd()) {
1283: ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container);
1284: return $errtext if ($fatal);
1285: }
1286: # Group import/search
1287: if ($env{'form.importdetail'}) {
1288: my @imports;
1289: foreach my $item (split(/\&/,$env{'form.importdetail'})) {
1290: if (defined($item)) {
1291: my ($name,$url,$residx)=
1292: map {&unescape($_)} split(/\=/,$item);
1293: push(@imports, [$name, $url, $residx]);
1294: }
1295: }
1296: ($errtext,$fatal)=&group_import($coursenum, $coursedom, $folder,
1297: $container,'londocs',@imports);
1298: return $errtext if ($fatal);
1299: }
1300: # Loading a complete map
1301: if ($env{'form.loadmap'}) {
1302: if ($env{'form.importmap'}=~/\w/) {
1303: foreach my $res (&Apache::lonsequence::attemptread(&Apache::lonnet::filelocation('',$env{'form.importmap'}))) {
1304: my ($title,$url,$ext,$type)=split(/\:/,$res);
1305: my $idx=&LONCAPA::map::getresidx($url);
1306: $LONCAPA::map::resources[$idx]=$res;
1307: $LONCAPA::map::order[$#LONCAPA::map::order+1]=$idx;
1308: }
1309: ($errtext,$fatal)=&storemap($coursenum,$coursedom,
1310: $folder.'.'.$container);
1311: return $errtext if ($fatal);
1312: } else {
1313: $r->print('<p><span class="LC_error">'.&mt('No map selected.').'</span></p>');
1314:
1315: }
1316: }
1317: &log_differences($plain);
1318: }
1319: # ---------------------------------------------------------------- End commands
1320: # ---------------------------------------------------------------- Print screen
1321: my $idx=0;
1322: my $shown=0;
1323: if (($ishidden) || ($isencrypted) || ($randompick>=0) || ($is_random_order)) {
1324: $r->print('<div class="LC_Box">'.
1325: '<ol class="LC_docs_parameters"><li class="LC_docs_parameters_title">'.&mt('Parameters:').'</li>'.
1326: ($randompick>=0?'<li>'.&mt('randomly pick [quant,_1,resource]',$randompick).'</li>':'').
1327: ($ishidden?'<li>'.&mt('contents hidden').'</li>':'').
1328: ($isencrypted?'<li>'.&mt('URLs hidden').'</li>':'').
1329: ($is_random_order?'<li>'.&mt('random order').'</li>':'').
1330: '</ol>');
1331: if ($randompick>=0) {
1332: $r->print('<p class="LC_warning">'
1333: .&mt('Caution: this folder is set to randomly pick a subset'
1334: .' of resources. Adding or removing resources from this'
1335: .' folder will change the set of resources that the'
1336: .' students see, resulting in spurious or missing credit'
1337: .' for completed problems, not limited to ones you'
1338: .' modify. Do not modify the contents of this folder if'
1339: .' it is in active student use.')
1340: .'</p>'
1341: );
1342: }
1343: if ($is_random_order) {
1344: $r->print('<p class="LC_warning">'
1345: .&mt('Caution: this folder is set to randomly order its'
1346: .' contents. Adding or removing resources from this folder'
1347: .' will change the order of resources shown.')
1348: .'</p>'
1349: );
1350: }
1351: $r->print('</div>');
1352: }
1353:
1354: my ($to_show,$output);
1355:
1356: &Apache::loncommon::start_data_table_count(); #setup a row counter
1357: foreach my $res (@LONCAPA::map::order) {
1358: my ($name,$url)=split(/\:/,$LONCAPA::map::resources[$res]);
1359: $name=&LONCAPA::map::qtescape($name);
1360: $url=&LONCAPA::map::qtescape($url);
1361: unless ($name) { $name=(split(/\//,$url))[-1]; }
1362: unless ($name) { $idx++; next; }
1363: $output .= &entryline($idx,$name,$url,$folder,$allowed,$res,
1364: $coursenum,$crstype);
1365: $idx++;
1366: $shown++;
1367: }
1368: &Apache::loncommon::end_data_table_count();
1369:
1370: if ($shown) {
1371: $to_show = &Apache::loncommon::start_scrollbox('900px','880px','400px','contentscroll')
1372: .&Apache::loncommon::start_data_table(undef,'contentlist');
1373: if ($allowed) {
1374: $to_show .= &Apache::loncommon::start_data_table_header_row()
1375: .'<th colspan="2">'.&mt('Move').'</th>'
1376: .'<th>'.&mt('Actions').'</th>'
1377: .'<th colspan="2">'.&mt('Document').'</th>';
1378: if ($folder !~ /^supplemental/) {
1379: $to_show .= '<th colspan="4">'.&mt('Settings').'</th>';
1380: }
1381: $to_show .= &Apache::loncommon::end_data_table_header_row();
1382: }
1383: $to_show .= $output.' '
1384: .&Apache::loncommon::end_data_table()
1385: .'<br style="line-height:2px;" />'
1386: .&Apache::loncommon::end_scrollbox();
1387: } else {
1388: $to_show .= &Apache::loncommon::start_scrollbox('400px','380px','200px','contentscroll')
1389: .'<div class="LC_info" id="contentlist">'
1390: .&mt('Currently no documents.')
1391: .'</div>'
1392: .&Apache::loncommon::end_scrollbox();
1393: }
1394: my $tid = 1;
1395: if ($supplementalflag) {
1396: $tid = 2;
1397: }
1398: if ($allowed) {
1399: my $readfile="/uploaded/$coursedom/$coursenum/$folder.$container";
1400: $r->print(&generate_edit_table($tid,$orderhash,$to_show,$iconpath,$jumpto,
1401: $readfile));
1402: &print_paste_buffer($r,$container,$folder);
1403: } else {
1404: if (&Apache::lonnet::allowed('mdc',$env{'request.course.id'})) {
1405: #Function Box for Supplemental Content for users with mdc priv.
1406: my $funcname = &mt('Folder Editor');
1407: $r->print(
1408: &Apache::loncommon::head_subbox(
1409: &Apache::lonhtmlcommon::start_funclist().
1410: &Apache::lonhtmlcommon::add_item_funclist(
1411: '<a href="/adm/coursedocs?command=direct&forcesupplement=1&'.
1412: 'supppath='.&HTML::Entities::encode($env{'form.folderpath'}).'">'.
1413: '<img src="/res/adm/pages/docs.png" alt="'.$funcname.'" class="LC_icon" />'.
1414: '<span class="LC_menubuttons_inline_text">'.$funcname.'</span></a>').
1415: &Apache::lonhtmlcommon::end_funclist()));
1416: }
1417: $r->print($to_show);
1418: }
1419: return;
1420: }
1421:
1422: sub process_file_upload {
1423: my ($upload_output,$coursenum,$coursedom,$allfiles,$codebase,$uploadcmd) = @_;
1424: # upload a file, if present
1425: my ($parseaction,$showupload,$nextphase,$mimetype);
1426: if ($env{'form.parserflag'}) {
1427: $parseaction = 'parse';
1428: }
1429: my $folder=$env{'form.folder'};
1430: if ($folder eq '') {
1431: $folder='default';
1432: }
1433: if ( ($folder=~/^$uploadcmd/) || ($uploadcmd eq 'default') ) {
1434: my $errtext='';
1435: my $fatal=0;
1436: my $container='sequence';
1437: if ($env{'form.pagepath'}) {
1438: $container='page';
1439: }
1440: ($errtext,$fatal)=
1441: &mapread($coursenum,$coursedom,$folder.'.'.$container);
1442: if ($#LONCAPA::map::order<1) {
1443: $LONCAPA::map::order[0]=1;
1444: $LONCAPA::map::resources[1]='';
1445: }
1446: if ($fatal) {
1447: $$upload_output = '<div class="LC_error" id="uploadfileresult">'.&mt('The uploaded file has not been stored as an error occurred reading the contents of the current folder.').'</div>';
1448: return;
1449: }
1450: my $destination = 'docs/';
1451: if ($folder =~ /^supplemental/) {
1452: $destination = 'supplemental/';
1453: }
1454: if (($folder eq 'default') || ($folder eq 'supplemental')) {
1455: $destination .= 'default/';
1456: } elsif ($folder =~ /^(default|supplemental)_(\d+)$/) {
1457: $destination .= $2.'/';
1458: }
1459: # this is for a course, not a user, so set context to coursedoc.
1460: my $newidx=&LONCAPA::map::getresidx();
1461: $destination .= $newidx;
1462: my $url=&Apache::lonnet::userfileupload('uploaddoc','coursedoc',$destination,
1463: $parseaction,$allfiles,
1464: $codebase,undef,undef,undef,undef,
1465: undef,undef,\$mimetype);
1466: if ($url =~ m{^/uploaded/\Q$coursedom\E/\Q$coursenum\E.*/([^/]+)$}) {
1467: my $stored = $1;
1468: $showupload = '<p>'.&mt('Uploaded [_1]','<span class="LC_filename">'.
1469: $stored.'</span>').'</p>';
1470: } else {
1471: my ($filename) = ($env{'form.uploaddoc.filename'} =~ m{([^/]+)$});
1472:
1473: $$upload_output = '<div class="LC_error" id="uploadfileresult">'.&mt('Unable to save file [_1].','<span class="LC_filename">'.$filename.'</span>').'</div>';
1474: return;
1475: }
1476: my $ext='false';
1477: if ($url=~m{^http://}) { $ext='true'; }
1478: $url = &LONCAPA::map::qtunescape($url);
1479: my $comment=$env{'form.comment'};
1480: $comment = &LONCAPA::map::qtunescape($comment);
1481: if ($folder=~/^supplemental/) {
1482: $comment=time.'___&&&___'.$env{'user.name'}.'___&&&___'.
1483: $env{'user.domain'}.'___&&&___'.$comment;
1484: }
1485:
1486: $LONCAPA::map::resources[$newidx]=
1487: $comment.':'.$url.':'.$ext.':normal:res';
1488: $LONCAPA::map::order[$#LONCAPA::map::order+1]= $newidx;
1489: ($errtext,$fatal)=&storemap($coursenum,$coursedom,
1490: $folder.'.'.$container);
1491: if ($fatal) {
1492: $$upload_output = '<div class="LC_error" id="uploadfileresult">'.$errtext.'</div>';
1493: return;
1494: } else {
1495: if ($parseaction eq 'parse' && $mimetype eq 'text/html') {
1496: $$upload_output = $showupload;
1497: my $total_embedded = scalar(keys(%{$allfiles}));
1498: if ($total_embedded > 0) {
1499: my $uploadphase = 'upload_embedded';
1500: my $primaryurl = &HTML::Entities::encode($url,'<>&"');
1501: my $state = &embedded_form_elems($uploadphase,$primaryurl,$newidx);
1502: my ($embedded,$num) =
1503: &Apache::loncommon::ask_for_embedded_content(
1504: '/adm/coursedocs',$state,$allfiles,$codebase,{'docs_url' => $url});
1505: if ($embedded) {
1506: if ($num) {
1507: $$upload_output .=
1508: '<p>'.&mt('This file contains embedded multimedia objects, which need to be uploaded.').'</p>'.$embedded;
1509: $nextphase = $uploadphase;
1510: } else {
1511: $$upload_output .= $embedded;
1512: }
1513: } else {
1514: $$upload_output .= &mt('Embedded item(s) already present, so no additional upload(s) required').'<br />';
1515: }
1516: } else {
1517: $$upload_output .= &mt('No embedded items identified').'<br />';
1518: }
1519: $$upload_output = '<div id="uploadfileresult">'.$$upload_output.'</div>';
1520: } elsif (&Apache::loncommon::is_archive_file($mimetype)) {
1521: $nextphase = 'decompress_uploaded';
1522: my $position = scalar(@LONCAPA::map::order)-1;
1523: my $noextract = &return_to_editor();
1524: my $archiveurl = &HTML::Entities::encode($url,'<>&"');
1525: my %archiveitems = (
1526: folderpath => $env{'form.folderpath'},
1527: pagepath => $env{'form.pagepath'},
1528: cmd => $nextphase,
1529: newidx => $newidx,
1530: position => $position,
1531: phase => $nextphase,
1532: comment => $comment,
1533: );
1534: my ($destination,$dir_root) = &embedded_destination($coursenum,$coursedom);
1535: my @current = &get_dir_list($url,$coursenum,$coursedom,$newidx);
1536: $$upload_output = $showupload.
1537: &Apache::loncommon::decompress_form($mimetype,
1538: $archiveurl,'/adm/coursedocs',$noextract,
1539: \%archiveitems,\@current);
1540: }
1541: }
1542: }
1543: return $nextphase;
1544: }
1545:
1546: sub get_dir_list {
1547: my ($url,$coursenum,$coursedom,$newidx) = @_;
1548: my ($destination,$dir_root) = &embedded_destination();
1549: my ($dirlistref,$listerror) =
1550: &Apache::lonnet::dirlist("$dir_root/$destination/$newidx",$coursedom,$coursenum,1);
1551: my @dir_lines;
1552: my $dirptr=16384;
1553: if (ref($dirlistref) eq 'ARRAY') {
1554: foreach my $dir_line (sort
1555: {
1556: my ($afile)=split('&',$a,2);
1557: my ($bfile)=split('&',$b,2);
1558: return (lc($afile) cmp lc($bfile));
1559: } (@{$dirlistref})) {
1560: my ($filename,$dom,undef,$testdir,undef,undef,undef,undef,$size,undef,$mtime,undef,undef,undef,$obs,undef)=split(/\&/,$dir_line,16);
1561: $filename =~ s/\s+$//;
1562: next if ($filename =~ /^\.\.?$/);
1563: my $isdir = 0;
1564: if ($dirptr&$testdir) {
1565: $isdir = 1;
1566: }
1567: push(@dir_lines, [$filename,$dom,$isdir,$size,$mtime,$obs]);
1568: }
1569: }
1570: return @dir_lines;
1571: }
1572:
1573: sub is_supplemental_title {
1574: my ($title) = @_;
1575: return scalar($title =~ m/^(\d+)___&&&___($match_username)___&&&___($match_domain)___&&&___(.*)$/);
1576: }
1577:
1578: # --------------------------------------------------------------- An entry line
1579:
1580: sub entryline {
1581: my ($index,$title,$url,$folder,$allowed,$residx,$coursenum,$crstype)=@_;
1582: my ($foldertitle,$pagetitle,$renametitle);
1583: if (&is_supplemental_title($title)) {
1584: ($title,$foldertitle,$renametitle) = &Apache::loncommon::parse_supplemental_title($title);
1585: $pagetitle = $foldertitle;
1586: } else {
1587: $title=&HTML::Entities::encode($title,'"<>&\'');
1588: $renametitle=$title;
1589: $foldertitle=$title;
1590: $pagetitle=$title;
1591: }
1592:
1593: my $orderidx=$LONCAPA::map::order[$index];
1594:
1595:
1596: $renametitle=~s/\\/\\\\/g;
1597: $renametitle=~s/\"\;/\\\"/g;
1598: $renametitle=~s/ /%20/g;
1599: my $line=&Apache::loncommon::start_data_table_row();
1600: my ($form_start,$form_end,$form_common);
1601: # Edit commands
1602: my ($container, $type, $esc_path, $path, $symb);
1603: if ($env{'form.folderpath'}) {
1604: $type = 'folder';
1605: $container = 'sequence';
1606: $esc_path=&escape($env{'form.folderpath'});
1607: $path = &HTML::Entities::encode($env{'form.folderpath'},'<>&"');
1608: # $htmlfoldername=&HTML::Entities::encode($env{'form.foldername'},'<>&"');
1609: }
1610: if ($env{'form.pagepath'}) {
1611: $type = $container = 'page';
1612: $esc_path=&escape($env{'form.pagepath'});
1613: $path = &HTML::Entities::encode($env{'form.pagepath'},'<>&"');
1614: $symb=&escape($env{'form.pagesymb'});
1615: }
1616: my $cpinfo='';
1617: if ($allowed) {
1618: my $incindex=$index+1;
1619: my $selectbox='';
1620: if (($#LONCAPA::map::order>0) &&
1621: ((split(/\:/,
1622: $LONCAPA::map::resources[$LONCAPA::map::order[0]]))[1]
1623: ne '') &&
1624: ((split(/\:/,
1625: $LONCAPA::map::resources[$LONCAPA::map::order[1]]))[1]
1626: ne '')) {
1627: $selectbox=
1628: '<input type="hidden" name="currentpos" value="'.$incindex.'" />'.
1629: '<select name="newpos" onchange="this.form.submit()">';
1630: for (my $i=1;$i<=$#LONCAPA::map::order+1;$i++) {
1631: if ($i==$incindex) {
1632: $selectbox.='<option value="" selected="selected">('.$i.')</option>';
1633: } else {
1634: $selectbox.='<option value="'.$i.'">'.$i.'</option>';
1635: }
1636: }
1637: $selectbox.='</select>';
1638: }
1639: my %lt=&Apache::lonlocal::texthash(
1640: 'up' => 'Move Up',
1641: 'dw' => 'Move Down',
1642: 'rm' => 'Remove',
1643: 'ct' => 'Cut',
1644: 'rn' => 'Rename',
1645: 'cp' => 'Copy');
1646: my $nocopy=0;
1647: my $nocut=0;
1648: if ($url=~/\.(page|sequence)$/) {
1649: if ($url =~ m{/res/}) {
1650: # no copy for published maps
1651: $nocopy = 1;
1652: } else {
1653: foreach my $item (&Apache::lonsequence::attemptread(&Apache::lonnet::filelocation('',$url),1)) {
1654: my ($title,$url,$ext,$type)=split(/\:/,$item);
1655: if (($url=~/\.(page|sequence)/) && ($type ne 'zombie')) {
1656: $nocopy=1;
1657: last;
1658: }
1659: }
1660: }
1661: }
1662: if ($url=~/^\/res\/lib\/templates\//) {
1663: $nocopy=1;
1664: $nocut=1;
1665: }
1666: my $copylink=' ';
1667: my $cutlink=' ';
1668:
1669: my $skip_confirm = 0;
1670: if ( $folder =~ /^supplemental/
1671: || ($url =~ m{( /smppg$
1672: |/syllabus$
1673: |/aboutme$
1674: |/navmaps$
1675: |/bulletinboard$
1676: |\.html$
1677: |^/adm/wrapper/ext)}x)) {
1678: $skip_confirm = 1;
1679: }
1680:
1681: if (!$nocopy) {
1682: $copylink=(<<ENDCOPY);
1683: <a href="javascript:markcopy('$esc_path','$index','$renametitle','$container','$symb','$folder');" class="LC_docs_copy">$lt{'cp'}</a>
1684: ENDCOPY
1685: }
1686: if (!$nocut) {
1687: $cutlink=(<<ENDCUT);
1688: <a href="javascript:cutres('$esc_path','$index','$renametitle','$container','$symb','$folder',$skip_confirm);" class="LC_docs_cut">$lt{'ct'}</a>
1689: ENDCUT
1690: }
1691: $form_start = '
1692: <form action="/adm/coursedocs" method="post">
1693: ';
1694: $form_common=(<<END);
1695: <input type="hidden" name="${type}path" value="$path" />
1696: <input type="hidden" name="${type}symb" value="$symb" />
1697: <input type="hidden" name="setparms" value="$orderidx" />
1698: <input type="hidden" name="changeparms" value="0" />
1699: END
1700: $form_end = '</form>';
1701: $line.=(<<END);
1702: <td>
1703: <div class="LC_docs_entry_move">
1704: <a href='/adm/coursedocs?cmd=up_$index&${type}path=$esc_path&${type}symb=$symb$cpinfo'>
1705: <img src="${iconpath}move_up.gif" alt='$lt{'up'}' class="LC_icon" />
1706: </a>
1707: </div>
1708: <div class="LC_docs_entry_move">
1709: <a href='/adm/coursedocs?cmd=down_$index&${type}path=$esc_path&${type}symb=$symb$cpinfo'>
1710: <img src="${iconpath}move_down.gif" alt='$lt{'dw'}' class="LC_icon" />
1711: </a>
1712: </div>
1713: </td>
1714: <td>
1715: $form_start
1716: $form_common
1717: $selectbox
1718: $form_end
1719: </td>
1720: <td class="LC_docs_entry_commands">
1721: <a href='javascript:removeres("$esc_path","$index","$renametitle","$container","$symb",$skip_confirm);' class="LC_docs_remove">$lt{'rm'}</a>
1722: $cutlink
1723: <a href='javascript:changename("$esc_path","$index","$renametitle","$container","$symb");' class="LC_docs_rename">$lt{'rn'}</a>
1724: $copylink
1725: </td>
1726: END
1727:
1728: }
1729: # Figure out what kind of a resource this is
1730: my ($extension)=($url=~/\.(\w+)$/);
1731: my $uploaded=($url=~/^\/*uploaded\//);
1732: my $icon=&Apache::loncommon::icon($url);
1733: my $isfolder=0;
1734: my $ispage=0;
1735: my $folderarg;
1736: my $pagearg;
1737: my $pagefile;
1738: if ($uploaded) {
1739: if (($extension eq 'sequence') || ($extension eq 'page')) {
1740: $url=~/\Q$coursenum\E\/([\/\w]+)\.\Q$extension\E$/;
1741: my $containerarg = $1;
1742: if ($extension eq 'sequence') {
1743: $icon=$iconpath.'navmap.folder.closed.gif';
1744: $folderarg=$containerarg;
1745: $isfolder=1;
1746: } else {
1747: $icon=$iconpath.'page.gif';
1748: $pagearg=$containerarg;
1749: $ispage=1;
1750: }
1751: if ($allowed) {
1752: $url='/adm/coursedocs?';
1753: } else {
1754: $url='/adm/supplemental?';
1755: }
1756: } else {
1757: &Apache::lonnet::allowuploaded('/adm/coursedoc',$url);
1758: }
1759: }
1760:
1761: my $orig_url = $url;
1762: $orig_url=~s{http(:|:)//https(:|:)//}{https$2//};
1763: my $external = ($url=~s{^http(|s)(:|:)//}{/adm/wrapper/ext/});
1764: if ((!$isfolder) && ($residx) && ($folder!~/supplemental/) && (!$ispage)) {
1765: my $symb=&Apache::lonnet::symbclean(
1766: &Apache::lonnet::declutter('uploaded/'.
1767: $env{'course.'.$env{'request.course.id'}.'.domain'}.'/'.
1768: $env{'course.'.$env{'request.course.id'}.'.num'}.'/'.$folder.
1769: '.sequence').
1770: '___'.$residx.'___'.
1771: &Apache::lonnet::declutter($url));
1772: (undef,undef,$url)=&Apache::lonnet::decode_symb($symb);
1773: $url=&Apache::lonnet::clutter($url);
1774: if ($url=~/^\/*uploaded\//) {
1775: $url=~/\.(\w+)$/;
1776: my $embstyle=&Apache::loncommon::fileembstyle($1);
1777: if (($embstyle eq 'img') || ($embstyle eq 'emb')) {
1778: $url='/adm/wrapper'.$url;
1779: } elsif ($embstyle eq 'ssi') {
1780: #do nothing with these
1781: } elsif ($url!~/\.(sequence|page)$/) {
1782: $url='/adm/coursedocs/showdoc'.$url;
1783: }
1784: } elsif ($url=~m|^/ext/|) {
1785: $url='/adm/wrapper'.$url;
1786: $external = 1;
1787: }
1788: if (&Apache::lonnet::symbverify($symb,$url)) {
1789: $url.=(($url=~/\?/)?'&':'?').'symb='.&escape($symb);
1790: } else {
1791: $url='';
1792: }
1793: if ($container eq 'page') {
1794: my $symb=$env{'form.pagesymb'};
1795:
1796: $url=&Apache::lonnet::clutter((&Apache::lonnet::decode_symb($symb))[2]);
1797: $url.=(($url=~/\?/)?'&':'?').'symb='.&escape($symb);
1798: }
1799: }
1800: my ($rand_pick_text,$rand_order_text);
1801: if ($isfolder || $extension eq 'sequence') {
1802: my $foldername=&escape($foldertitle);
1803: my $folderpath=$env{'form.folderpath'};
1804: if ($folderpath) { $folderpath.='&' };
1805: # Append randompick number, hidden, and encrypted with ":" to foldername,
1806: # so it gets transferred between levels
1807: $folderpath.=$folderarg.'&'.$foldername.':'.(&LONCAPA::map::getparameter($orderidx,
1808: 'parameter_randompick'))[0]
1809: .':'.((&LONCAPA::map::getparameter($orderidx,
1810: 'parameter_hiddenresource'))[0]=~/^yes$/i)
1811: .':'.((&LONCAPA::map::getparameter($orderidx,
1812: 'parameter_encrypturl'))[0]=~/^yes$/i)
1813: .':'.((&LONCAPA::map::getparameter($orderidx,
1814: 'parameter_randomorder'))[0]=~/^yes$/i);
1815: $url.='folderpath='.&escape($folderpath).$cpinfo;
1816: my $rpicknum = (&LONCAPA::map::getparameter($orderidx,
1817: 'parameter_randompick'))[0];
1818: my $rpckchk;
1819: if ($rpicknum) {
1820: $rpckchk = ' checked="checked"';
1821: }
1822: my $formname = 'edit_rpick_'.$orderidx;
1823: $rand_pick_text =
1824: '<form action="/adm/coursedocs" method="post" name="'.$formname.'">'."\n".
1825: $form_common."\n".
1826: '<span class="LC_nobreak"><label><input type="checkbox" name="randpickon_'.$orderidx.'" id="rpick_'.$orderidx.'" onclick="'."updatePick(this.form,'$orderidx','check');".'"'.$rpckchk.' /> '.&mt('Randomly Pick').'</label><input type="hidden" name="randompick_'.$orderidx.'" id="rpicknum_'.$orderidx.'" value="'.$rpicknum.'" />';
1827: if ($rpicknum ne '') {
1828: $rand_pick_text .= ': <a href="javascript:updatePick('."document.$formname,'$orderidx','link'".')">'.$rpicknum.'</a>';
1829: }
1830: $rand_pick_text .= '</span></form>';
1831: my $ro_set=
1832: ((&LONCAPA::map::getparameter($orderidx,'parameter_randomorder'))[0]=~/^yes$/i?' checked="checked"':'');
1833: $rand_order_text =
1834: $form_start.
1835: $form_common.'
1836: <span class="LC_nobreak"><label><input type="checkbox" name="randomorder_'.$orderidx.'" onclick="'."this.form.changeparms.value='randomorder';this.form.submit()".'" '.$ro_set.' /> '.&mt('Random Order').' </label></span></form>';
1837: }
1838: if ($ispage) {
1839: my $pagename=&escape($pagetitle);
1840: my $pagepath;
1841: my $folderpath=$env{'form.folderpath'};
1842: if ($folderpath) { $pagepath = $folderpath.'&' };
1843: $pagepath.=$pagearg.'&'.$pagename;
1844: my $symb=$env{'form.pagesymb'};
1845: if (!$symb) {
1846: my $path='uploaded/'.
1847: $env{'course.'.$env{'request.course.id'}.'.domain'}.'/'.
1848: $env{'course.'.$env{'request.course.id'}.'.num'}.'/';
1849: $symb=&Apache::lonnet::encode_symb($path.$folder.'.sequence',
1850: $residx,
1851: $path.$pagearg.'.page');
1852: }
1853: $url.='pagepath='.&escape($pagepath).
1854: '&pagesymb='.&escape($symb).$cpinfo;
1855: }
1856: if (($external) && ($allowed)) {
1857: my $form = ($folder =~ /^default/)? 'newext' : 'supnewext';
1858: $external = ' <a class="LC_docs_ext_edit" href="javascript:edittext(\''.$form.'\',\''.$residx.'\',\''.&escape($title).'\',\''.&escape($orig_url).'\');" >'.&mt('Edit').'</a>';
1859: } else {
1860: undef($external);
1861: }
1862: my $reinit;
1863: if ($crstype eq 'Community') {
1864: $reinit = &mt('(re-initialize community to access)');
1865: } else {
1866: $reinit = &mt('(re-initialize course to access)');
1867: }
1868: $line.='<td>';
1869: if (($url=~m{/adm/(coursedocs|supplemental)}) || (!$allowed && $url)) {
1870: $line.='<a href="'.$url.'"><img src="'.$icon.'" alt="" class="LC_icon" /></a>';
1871: } elsif ($url) {
1872: $line.=&Apache::loncommon::modal_link($url.(($url=~/\?/)?'&':'?').'inhibitmenu=yes',
1873: '<img src="'.$icon.'" alt="" class="LC_icon" />',600,500);
1874: } else {
1875: $line.='<img src="'.$icon.'" alt="" class="LC_icon" />';
1876: }
1877: $line.='</td><td>';
1878: if (($url=~m{/adm/(coursedocs|supplemental)}) || (!$allowed && $url)) {
1879: $line.='<a href="'.$url.'">'.$title.'</a>';
1880: } elsif ($url) {
1881: $line.=&Apache::loncommon::modal_link($url.(($url=~/\?/)?'&':'?').'inhibitmenu=yes',
1882: $title,600,500);
1883: } else {
1884: $line.=$title.' <span class="LC_docs_reinit_warn">'.$reinit.'</span>';
1885: }
1886: $line.=$external."</td>";
1887: $rand_pick_text = ' ' if ($rand_pick_text eq '');
1888: $rand_order_text = ' ' if ($rand_order_text eq '');
1889: if (($allowed) && ($folder!~/^supplemental/)) {
1890: my %lt=&Apache::lonlocal::texthash(
1891: 'hd' => 'Hidden',
1892: 'ec' => 'URL hidden');
1893: my $enctext=
1894: ((&LONCAPA::map::getparameter($orderidx,'parameter_encrypturl'))[0]=~/^yes$/i?' checked="checked"':'');
1895: my $hidtext=
1896: ((&LONCAPA::map::getparameter($orderidx,'parameter_hiddenresource'))[0]=~/^yes$/i?' checked="checked"':'');
1897: $line.=(<<ENDPARMS);
1898: <td class="LC_docs_entry_parameter">
1899: $form_start
1900: $form_common
1901: <label><input type="checkbox" name="hiddenresource_$orderidx" onclick="this.form.changeparms.value='hiddenresource';this.form.submit()" $hidtext /> $lt{'hd'}</label>
1902: $form_end
1903: <br />
1904: $form_start
1905: $form_common
1906: <label><input type="checkbox" name="encrypturl_$orderidx" onclick="this.form.changeparms.value='encrypturl';this.form.submit()" $enctext /> $lt{'ec'}</label>
1907: $form_end
1908: </td>
1909: <td class="LC_docs_entry_parameter">$rand_pick_text<br />
1910: $rand_order_text</td>
1911: ENDPARMS
1912: }
1913: $line.=&Apache::loncommon::end_data_table_row();
1914: return $line;
1915: }
1916:
1917: =pod
1918:
1919: =item tiehash()
1920:
1921: tie the hash
1922:
1923: =cut
1924:
1925: sub tiehash {
1926: my ($mode)=@_;
1927: $hashtied=0;
1928: if ($env{'request.course.fn'}) {
1929: if ($mode eq 'write') {
1930: if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.".db",
1931: &GDBM_WRCREAT(),0640)) {
1932: $hashtied=2;
1933: }
1934: } else {
1935: if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.".db",
1936: &GDBM_READER(),0640)) {
1937: $hashtied=1;
1938: }
1939: }
1940: }
1941: }
1942:
1943: sub untiehash {
1944: if ($hashtied) { untie %hash; }
1945: $hashtied=0;
1946: return OK;
1947: }
1948:
1949:
1950:
1951:
1952: sub checkonthis {
1953: my ($r,$url,$level,$title)=@_;
1954: $url=&unescape($url);
1955: $alreadyseen{$url}=1;
1956: $r->rflush();
1957: if (($url) && ($url!~/^\/uploaded\//) && ($url!~/\*$/)) {
1958: $r->print("\n<br />");
1959: if ($level==0) {
1960: $r->print("<br />");
1961: }
1962: for (my $i=0;$i<=$level*5;$i++) {
1963: $r->print(' ');
1964: }
1965: $r->print('<a href="'.$url.'" target="cat">'.
1966: ($title?$title:$url).'</a> ');
1967: if ($url=~/^\/res\//) {
1968: my $result=&Apache::lonnet::repcopy(
1969: &Apache::lonnet::filelocation('',$url));
1970: if ($result eq 'ok') {
1971: $r->print('<span class="LC_success">'.&mt('ok').'</span>');
1972: $r->rflush();
1973: &Apache::lonnet::countacc($url);
1974: $url=~/\.(\w+)$/;
1975: if (&Apache::loncommon::fileembstyle($1) eq 'ssi') {
1976: $r->print('<br />');
1977: $r->rflush();
1978: for (my $i=0;$i<=$level*5;$i++) {
1979: $r->print(' ');
1980: }
1981: $r->print('- '.&mt('Rendering:').' ');
1982: my ($errorcount,$warningcount)=split(/:/,
1983: &Apache::lonnet::ssi_body($url,
1984: ('grade_target'=>'web',
1985: 'return_only_error_and_warning_counts' => 1)));
1986: if (($errorcount) ||
1987: ($warningcount)) {
1988: if ($errorcount) {
1989: $r->print('<img src="/adm/lonMisc/bomb.gif" alt="'.&mt('bomb').'" /><span class="LC_error">'.
1990: &mt('[quant,_1,error]',$errorcount).'</span>');
1991: }
1992: if ($warningcount) {
1993: $r->print('<span class="LC_warning">'.
1994: &mt('[quant,_1,warning]',$warningcount).'</span>');
1995: }
1996: } else {
1997: $r->print('<span class="LC_success">'.&mt('ok').'</span>');
1998: }
1999: $r->rflush();
2000: }
2001: my $dependencies=
2002: &Apache::lonnet::metadata($url,'dependencies');
2003: foreach my $dep (split(/\,/,$dependencies)) {
2004: if (($dep=~/^\/res\//) && (!$alreadyseen{$dep})) {
2005: &checkonthis($r,$dep,$level+1);
2006: }
2007: }
2008: } elsif ($result eq 'unavailable') {
2009: $r->print('<span class="LC_error">'.&mt('connection down').'</span>');
2010: } elsif ($result eq 'not_found') {
2011: unless ($url=~/\$/) {
2012: $r->print('<span class="LC_error">'.&mt('not found').'</b></span>');
2013: } else {
2014: $r->print('<span class="LC_error">'.&mt('unable to verify variable URL').'</span>');
2015: }
2016: } else {
2017: $r->print('<span class="LC_error">'.&mt('access denied').'</span>');
2018: }
2019: }
2020: }
2021: }
2022:
2023:
2024:
2025: =pod
2026:
2027: =item list_symbs()
2028:
2029: List Content Identifiers
2030:
2031: =cut
2032:
2033: sub list_symbs {
2034: my ($r) = @_;
2035:
2036: my $crstype = &Apache::loncommon::course_type();
2037: $r->print(&Apache::loncommon::start_page('List of Content Identifiers'));
2038: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Content Identifiers'));
2039: $r->print(&startContentScreen('tools'));
2040: my $navmap = Apache::lonnavmaps::navmap->new();
2041: if (!defined($navmap)) {
2042: $r->print('<h2>'.&mt('Retrieval of List Failed').'</h2>'.
2043: '<div class="LC_error">'.
2044: &mt('Unable to retrieve information about course contents').
2045: '</div>');
2046: &Apache::lonnet::logthis('Symb list failed - could not create navmap object in '.lc($crstype).':'.$env{'request.course.id'});
2047: } else {
2048: $r->print('<h4 class="LC_info">'.&mt("$crstype Content Identifiers").'</h4>'.
2049: &Apache::loncommon::start_data_table().
2050: &Apache::loncommon::start_data_table_header_row().
2051: '<th>'.&mt('Title').'</th><th>'.&mt('Identifier').'</th>'.
2052: &Apache::loncommon::end_data_table_header_row()."\n");
2053: my $count;
2054: foreach my $res ($navmap->retrieveResources()) {
2055: $r->print(&Apache::loncommon::start_data_table_row().
2056: '<td>'.$res->compTitle().'</td>'.
2057: '<td>'.$res->symb().'</td>'.
2058: &Apache::loncommon::start_data_table_row());
2059: $count ++;
2060: }
2061: if (!$count) {
2062: $r->print(&Apache::loncommon::start_data_table_row().
2063: '<td colspan="2">'.&mt("$crstype is empty").'</td>'.
2064: &Apache::loncommon::end_data_table_row());
2065: }
2066: $r->print(&Apache::loncommon::end_data_table());
2067: }
2068: }
2069:
2070:
2071: sub verifycontent {
2072: my ($r) = @_;
2073: my $crstype = &Apache::loncommon::course_type();
2074: $r->print(&Apache::loncommon::start_page('Verify '.$crstype.' Documents'));
2075: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Verify '.$crstype.' Documents'));
2076: $r->print(&startContentScreen('tools'));
2077: $r->print('<h4 class="LC_info">'.&mt($crstype.' content verification').'</h4>');
2078: $hashtied=0;
2079: undef %alreadyseen;
2080: %alreadyseen=();
2081: &tiehash();
2082:
2083: foreach my $key (keys(%hash)) {
2084: if ($hash{$key}=~/\.(page|sequence)$/) {
2085: if (($key=~/^src_/) && ($alreadyseen{&unescape($hash{$key})})) {
2086: $r->print('<hr /><span class="LC_error">'.
2087: &mt('The following sequence or page is included more than once in your '.$crstype.':').' '.
2088: &unescape($hash{$key}).'</span><br />'.
2089: &mt('Note that grading records for problems included in this sequence or folder will overlap.').'<hr />');
2090: }
2091: }
2092: if (($key=~/^src\_(.+)$/) && (!$alreadyseen{&unescape($hash{$key})})) {
2093: &checkonthis($r,$hash{$key},0,$hash{'title_'.$1});
2094: }
2095: }
2096: &untiehash();
2097: $r->print('<p class="LC_success">'.&mt('Done').'</p>');
2098: }
2099:
2100:
2101: sub devalidateversioncache {
2102: my $src=shift;
2103: &Apache::lonnet::devalidate_cache_new('courseresversion',$env{'request.course.id'}.'_'.
2104: &Apache::lonnet::clutter($src));
2105: }
2106:
2107: sub checkversions {
2108: my ($r) = @_;
2109: my $crstype = &Apache::loncommon::course_type();
2110: $r->print(&Apache::loncommon::start_page("Check $crstype Document Versions"));
2111: $r->print(&Apache::lonhtmlcommon::breadcrumbs("Check $crstype Document Versions"));
2112: $r->print(&startContentScreen('tools'));
2113:
2114: my $header='';
2115: my $startsel='';
2116: my $monthsel='';
2117: my $weeksel='';
2118: my $daysel='';
2119: my $allsel='';
2120: my %changes=();
2121: my $starttime=0;
2122: my $haschanged=0;
2123: my %setversions=&Apache::lonnet::dump('resourceversions',
2124: $env{'course.'.$env{'request.course.id'}.'.domain'},
2125: $env{'course.'.$env{'request.course.id'}.'.num'});
2126:
2127: $hashtied=0;
2128: &tiehash();
2129: my %newsetversions=();
2130: if ($env{'form.setmostrecent'}) {
2131: $haschanged=1;
2132: foreach my $key (keys(%hash)) {
2133: if ($key=~/^ids\_(\/res\/.+)$/) {
2134: $newsetversions{$1}='mostrecent';
2135: &devalidateversioncache($1);
2136: }
2137: }
2138: } elsif ($env{'form.setcurrent'}) {
2139: $haschanged=1;
2140: foreach my $key (keys(%hash)) {
2141: if ($key=~/^ids\_(\/res\/.+)$/) {
2142: my $getvers=&Apache::lonnet::getversion($1);
2143: if ($getvers>0) {
2144: $newsetversions{$1}=$getvers;
2145: &devalidateversioncache($1);
2146: }
2147: }
2148: }
2149: } elsif ($env{'form.setversions'}) {
2150: $haschanged=1;
2151: foreach my $key (keys(%env)) {
2152: if ($key=~/^form\.set_version_(.+)$/) {
2153: my $src=$1;
2154: if (($env{$key}) && ($env{$key} ne $setversions{$src})) {
2155: $newsetversions{$src}=$env{$key};
2156: &devalidateversioncache($src);
2157: }
2158: }
2159: }
2160: }
2161: if ($haschanged) {
2162: if (&Apache::lonnet::put('resourceversions',\%newsetversions,
2163: $env{'course.'.$env{'request.course.id'}.'.domain'},
2164: $env{'course.'.$env{'request.course.id'}.'.num'}) eq 'ok') {
2165: $r->print(&Apache::loncommon::confirmwrapper(
2166: &Apache::lonhtmlcommon::confirm_success(&mt('Your Version Settings have been Saved'))));
2167: } else {
2168: $r->print(&Apache::loncommon::confirmwrapper(
2169: &Apache::lonhtmlcommon::confirm_success(&mt('An Error Occured while Attempting to Save your Version Settings'),1)));
2170: }
2171: &mark_hash_old();
2172: }
2173: &changewarning($r,'');
2174: if ($env{'form.timerange'} eq 'all') {
2175: # show all documents
2176: $header=&mt('All Documents in '.$crstype);
2177: $allsel=1;
2178: foreach my $key (keys(%hash)) {
2179: if ($key=~/^ids\_(\/res\/.+)$/) {
2180: my $src=$1;
2181: $changes{$src}=1;
2182: }
2183: }
2184: } else {
2185: # show documents which changed
2186: %changes=&Apache::lonnet::dump
2187: ('versionupdate',$env{'course.'.$env{'request.course.id'}.'.domain'},
2188: $env{'course.'.$env{'request.course.id'}.'.num'});
2189: my $firstkey=(keys(%changes))[0];
2190: unless ($firstkey=~/^error\:/) {
2191: unless ($env{'form.timerange'}) {
2192: $env{'form.timerange'}=604800;
2193: }
2194: my $seltext=&mt('during the last').' '.$env{'form.timerange'}.' '
2195: .&mt('seconds');
2196: if ($env{'form.timerange'}==-1) {
2197: $seltext='since start of course';
2198: $startsel='selected';
2199: $env{'form.timerange'}=time;
2200: }
2201: $starttime=time-$env{'form.timerange'};
2202: if ($env{'form.timerange'}==2592000) {
2203: $seltext=&mt('during the last month').' ('.&Apache::lonlocal::locallocaltime($starttime).')';
2204: $monthsel='selected';
2205: } elsif ($env{'form.timerange'}==604800) {
2206: $seltext=&mt('during the last week').' ('.&Apache::lonlocal::locallocaltime($starttime).')';
2207: $weeksel='selected';
2208: } elsif ($env{'form.timerange'}==86400) {
2209: $seltext=&mt('since yesterday').' ('.&Apache::lonlocal::locallocaltime($starttime).')';
2210: $daysel='selected';
2211: }
2212: $header=&mt('Content changed').' '.$seltext;
2213: } else {
2214: $header=&mt('No content modifications yet.');
2215: }
2216: }
2217: %setversions=&Apache::lonnet::dump('resourceversions',
2218: $env{'course.'.$env{'request.course.id'}.'.domain'},
2219: $env{'course.'.$env{'request.course.id'}.'.num'});
2220: my %lt=&Apache::lonlocal::texthash
2221: ('st' => 'Version changes since start of '.$crstype,
2222: 'lm' => 'Version changes since last Month',
2223: 'lw' => 'Version changes since last Week',
2224: 'sy' => 'Version changes since Yesterday',
2225: 'al' => 'All Resources (possibly large output)',
2226: 'cd' => 'Change display',
2227: 'sd' => 'Display',
2228: 'fi' => 'File',
2229: 'md' => 'Modification Date',
2230: 'mr' => 'Most recently published Version',
2231: 've' => 'Version used in '.$crstype,
2232: 'vu' => 'Set Version to be used in '.$crstype,
2233: 'sv' => 'Set Versions to be used in '.$crstype.' according to Selections below',
2234: 'sm' => 'Keep all Resources up-to-date with most recent Versions (default)',
2235: 'sc' => 'Set all Resource Versions to current Version (Fix Versions)',
2236: 'di' => 'Differences',
2237: 'save' => 'Save changes',
2238: 'vers' => 'Version choice(s) for specific resources',
2239: 'act' => 'Actions');
2240: $r->print(<<ENDHEADERS);
2241: <h4 class="LC_info">$header</h4>
2242: <form action="/adm/coursedocs" method="post">
2243: <input type="hidden" name="versions" value="1" />
2244: <div class="LC_left_float">
2245: <fieldset>
2246: <legend>$lt{'cd'}</legend>
2247: <select name="timerange">
2248: <option value='all' $allsel>$lt{'al'}</option>
2249: <option value="-1" $startsel>$lt{'st'}</option>
2250: <option value="2592000" $monthsel>$lt{'lm'}</option>
2251: <option value="604800" $weeksel>$lt{'lw'}</option>
2252: <option value="86400" $daysel>$lt{'sy'}</option>
2253: </select>
2254: <input type="submit" name="display" value="$lt{'sd'}" />
2255: </fieldset>
2256: </div>
2257: <div class="LC_left_float">
2258: <fieldset>
2259: <legend>$lt{'act'}</legend>
2260: $lt{'sm'}: <input type="submit" name="setmostrecent" value="Go" /><br />
2261: $lt{'sc'}: <input type="submit" name="setcurrent" value="Go" />
2262: </fieldset>
2263: </div>
2264: <br clear="all" />
2265: <hr />
2266: <h4>$lt{'vers'}</h4>
2267: <input type="submit" name="setversions" value="$lt{'save'}" />
2268: <table border="0">
2269: ENDHEADERS
2270: #number of columns for version history
2271: my $num_ver_col = 1;
2272: $r->print(
2273: &Apache::loncommon::start_data_table().
2274: &Apache::loncommon::start_data_table_header_row().
2275: '<th>'.&mt('Resources').'</th>'.
2276: "<th>$lt{'mr'}</th>".
2277: "<th>$lt{'ve'}</th>".
2278: "<th>$lt{'vu'}</th>".
2279: '<th colspan="'.$num_ver_col.'">'.&mt('History').'</th>'.
2280: '</b>');
2281: foreach my $key (sort(keys(%changes))) {
2282: if ($changes{$key}>$starttime) {
2283: my ($root,$extension)=($key=~/^(.*)\.(\w+)$/);
2284: my $currentversion=&Apache::lonnet::getversion($key);
2285: if ($currentversion<0) {
2286: $currentversion='<span class="LC_error">'.&mt('Could not be determined.').'</span>';
2287: }
2288: my $linkurl=&Apache::lonnet::clutter($key);
2289: $r->print(
2290: &Apache::loncommon::end_data_table_header_row().
2291: &Apache::loncommon::start_data_table_row().
2292: '<td><b>'.&Apache::lonnet::gettitle($linkurl).'</b><br>'.
2293: '<a href="'.$linkurl.'" target="cat">'.$linkurl.'</a></td>'.
2294: '<td align="right">'.$currentversion.'<span class="LC_fontsize_medium"><br>('.
2295: &Apache::lonlocal::locallocaltime(&Apache::lonnet::metadata($root.'.'.$extension,'lastrevisiondate')).')</span></td>'.
2296: '<td align="right">');
2297: # Used in course
2298: my $usedversion=$hash{'version_'.$linkurl};
2299: if (($usedversion) && ($usedversion ne 'mostrecent')) {
2300: if($usedversion != $currentversion){
2301: $r->print('<span class="LC_warning">'.$usedversion.'</span>');
2302: }else{
2303: $r->print($usedversion);
2304: }
2305: } else {
2306: $r->print($currentversion);
2307: }
2308: $r->print('</td><td title="'.$lt{'vu'}.'">');
2309: # Set version
2310: $r->print(&Apache::loncommon::select_form($setversions{$linkurl},
2311: 'set_version_'.$linkurl,
2312: {'select_form_order' =>
2313: ['',1..$currentversion,'mostrecent'],
2314: '' => '',
2315: 'mostrecent' => &mt('most recent'),
2316: map {$_,$_} (1..$currentversion)}));
2317: my $lastold=1;
2318: for (my $prevvers=1;$prevvers<$currentversion;$prevvers++) {
2319: my $url=$root.'.'.$prevvers.'.'.$extension;
2320: if (&Apache::lonnet::metadata($url,'lastrevisiondate')<
2321: $starttime) {
2322: $lastold=$prevvers;
2323: }
2324: }
2325: #
2326: # Code to figure out how many version entries should go in
2327: # each of the four columns
2328: my $entries_per_col = 0;
2329: my $num_entries = ($currentversion-$lastold);
2330: if ($num_entries % $num_ver_col == 0) {
2331: $entries_per_col = $num_entries/$num_ver_col;
2332: } else {
2333: $entries_per_col = $num_entries/$num_ver_col + 1;
2334: }
2335: my $entries_count = 0;
2336: $r->print('<td valign="top"><span class="LC_fontsize_medium">');
2337: my $cols_output = 1;
2338: for (my $prevvers=$lastold;$prevvers<$currentversion;$prevvers++) {
2339: my $url=$root.'.'.$prevvers.'.'.$extension;
2340: $r->print('<span class="LC_nobreak"><a href="'.&Apache::lonnet::clutter($url).
2341: '">'.&mt('Version').' '.$prevvers.'</a> ('.
2342: &Apache::lonlocal::locallocaltime(
2343: &Apache::lonnet::metadata($url,
2344: 'lastrevisiondate')
2345: ).
2346: ')');
2347: if (&Apache::loncommon::fileembstyle($extension) eq 'ssi') {
2348: $r->print(' <a href="/adm/diff?filename='.
2349: &Apache::lonnet::clutter($root.'.'.$extension).
2350: '&versionone='.$prevvers.
2351: '" target="diffs">'.&mt('Diffs').'</a>');
2352: }
2353: $r->print('</span><br />');
2354: if (++$entries_count % $entries_per_col == 0) {
2355: $r->print('</span></td>');
2356: if ($cols_output != $num_ver_col) {
2357: $r->print('<td valign="top"><span class="LC_fontsize_medium">');
2358: $cols_output++;
2359: }
2360: }
2361: }
2362: while($cols_output++ < $num_ver_col) {
2363: $r->print('</span></td><td>');
2364: }
2365: }
2366: }
2367: $r->print('</td>'.&Apache::loncommon::end_data_table_row().
2368: &Apache::loncommon::end_data_table().
2369: '<input type="submit" name="setversions" value="'.$lt{'save'}.'" />');
2370:
2371: &untiehash();
2372: }
2373:
2374: sub mark_hash_old {
2375: my $retie_hash=0;
2376: if ($hashtied) {
2377: $retie_hash=1;
2378: &untiehash();
2379: }
2380: &tiehash('write');
2381: $hash{'old'}=1;
2382: &untiehash();
2383: if ($retie_hash) { &tiehash(); }
2384: }
2385:
2386: sub is_hash_old {
2387: my $untie_hash=0;
2388: if (!$hashtied) {
2389: $untie_hash=1;
2390: &tiehash();
2391: }
2392: my $return=$hash{'old'};
2393: if ($untie_hash) { &untiehash(); }
2394: return $return;
2395: }
2396:
2397: sub changewarning {
2398: my ($r,$postexec,$message,$url)=@_;
2399: if (!&is_hash_old()) { return; }
2400: my $pathvar='folderpath';
2401: my $path=&escape($env{'form.folderpath'});
2402: if (!defined($url)) {
2403: if (defined($env{'form.pagepath'})) {
2404: $pathvar='pagepath';
2405: $path=&escape($env{'form.pagepath'});
2406: $path.='&pagesymb='.&escape($env{'form.pagesymb'});
2407: }
2408: $url='/adm/coursedocs?'.$pathvar.'='.$path;
2409: }
2410: my $course_type = &Apache::loncommon::course_type();
2411: if (!defined($message)) {
2412: $message='Changes will become active for your current session after [_1], or the next time you log in.';
2413: }
2414: $r->print("\n\n".
2415: '<script type="text/javascript">'."\n".
2416: '// <![CDATA['."\n".
2417: 'function reinit(tf) { tf.submit();'.$postexec.' }'."\n".
2418: '// ]]>'."\n".
2419: '</script>'."\n".
2420: '<form name="reinitform" method="post" action="/adm/roles" target="loncapaclient">'.
2421: '<input type="hidden" name="orgurl" value="'.$url.
2422: '" /><input type="hidden" name="selectrole" value="1" /><p class="LC_warning">'.
2423: &mt($message,' <input type="hidden" name="'.
2424: $env{'request.role'}.'" value="1" /><input type="button" value="'.
2425: &mt('re-initializing '.$course_type).'" onclick="reinit(this.form)" />').
2426: $help{'Caching'}.'</p></form>'."\n\n");
2427: }
2428:
2429:
2430: sub init_breadcrumbs {
2431: my ($form,$text)=@_;
2432: &Apache::lonhtmlcommon::clear_breadcrumbs();
2433: &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/coursedocs?tools=1",
2434: text=>&Apache::loncommon::course_type().' Editor',
2435: faq=>273,
2436: bug=>'Instructor Interface',
2437: help => 'Docs_Adding_Course_Doc'});
2438: &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/coursedocs?".$form.'=1',
2439: text=>$text,
2440: faq=>273,
2441: bug=>'Instructor Interface'});
2442: }
2443:
2444: # subroutine to list form elements
2445: sub create_list_elements {
2446: my @formarr = @_;
2447: my $list = '';
2448: for my $button (@formarr){
2449: for my $picture(keys %$button) {
2450: $list .= &Apache::lonhtmlcommon::htmltag('li', $picture.' '.$button->{$picture}, {class => 'LC_menubuttons_inline_text'});
2451: }
2452: }
2453: return $list;
2454: }
2455:
2456: # subroutine to create ul from list elements
2457: sub create_form_ul {
2458: my $list = shift;
2459: my $ul = &Apache::lonhtmlcommon::htmltag('ul',$list, {class => 'LC_ListStyleNormal'});
2460: return $ul;
2461: }
2462:
2463: #
2464: # Start tabs
2465: #
2466:
2467: sub startContentScreen {
2468: my ($mode) = @_;
2469: my $output = '<ul class="LC_TabContentBigger" id="mainnav">';
2470: if (($mode eq 'navmaps') || ($mode eq 'supplemental')) {
2471: $output .= '<li'.(($mode eq 'navmaps')?' class="active"':'').'><a href="/adm/navmaps"><b> '.&mt('Content Overview').' </b></a></li>'."\n";
2472: $output .= '<li'.(($mode eq 'coursesearch')?' class="active"':'').'><a href="/adm/searchcourse"><b> '.&mt('Content Search').' </b></a></li>'."\n";
2473: $output .= '<li'.(($mode eq 'courseindex')?' class="active"':'').'><a href="/adm/indexcourse"><b> '.&mt('Content Index').' </b></a></li>'."\n";
2474: $output .= '<li '.(($mode eq 'suppdocs')?' class="active"':'').'><a href="/adm/supplemental"><b>'.&mt('Supplemental Content').'</b></a></li>';
2475: } else {
2476: $output .= '<li '.(($mode eq 'docs')?' class="active"':'').' id="tabbededitor"><a href="/adm/coursedocs?forcestandard=1"><b> '.&mt('Content Editor').' </b></a></li>'."\n";
2477: $output .= '<li '.(($mode eq 'suppdocs')?' class="active"':'').'><a href="/adm/coursedocs?forcesupplement=1"><b>'.&mt('Supplemental Content Editor').'</b></a></li>'."\n";
2478: $output .= '<li '.(($mode eq 'tools')?' class="active"':'').'><a href="/adm/coursedocs?tools=1"><b> '.&mt('Content Utilities').' </b></a></li>'."\n";
2479: '><a href="/adm/coursedocs?tools=1"><b> '.&mt('Content Utilities').' </b></a></li>';
2480: }
2481: $output .= "\n".'</ul>'."\n";
2482: $output .= '<div class="LC_DocsBox" style="clear:both;margin:0;" id="contenteditor">'.
2483: '<div id="maincoursedoc" style="margin:0 0;padding:0 0;">'.
2484: '<div class="LC_ContentBox" id="mainCourseDocuments" style="display: block;">';
2485: return $output;
2486: }
2487:
2488: #
2489: # End tabs
2490: #
2491:
2492: sub endContentScreen {
2493: return '</div></div></div>';
2494: }
2495:
2496: sub supplemental_base {
2497: return 'supplemental&'.&escape(&mt('Supplemental '.&Apache::loncommon::course_type().' Content'));
2498: }
2499:
2500: sub handler {
2501: my $r = shift;
2502: &Apache::loncommon::content_type($r,'text/html');
2503: $r->send_http_header;
2504: return OK if $r->header_only;
2505:
2506: # get course data
2507: my $crstype = &Apache::loncommon::course_type();
2508: my $coursenum=$env{'course.'.$env{'request.course.id'}.'.num'};
2509: my $coursedom=$env{'course.'.$env{'request.course.id'}.'.domain'};
2510:
2511: # graphics settings
2512: $iconpath = &Apache::loncommon::lonhttpdurl($r->dir_config('lonIconsURL').'/');
2513:
2514: #
2515: # --------------------------------------------- Initialize help topics for this
2516: foreach my $topic ('Adding_Course_Doc','Main_Course_Documents',
2517: 'Adding_External_Resource','Navigate_Content',
2518: 'Adding_Folders','Docs_Overview', 'Load_Map',
2519: 'Supplemental','Score_Upload_Form','Adding_Pages',
2520: 'Importing_LON-CAPA_Resource','Uploading_From_Harddrive',
2521: 'Check_Resource_Versions','Verify_Content') {
2522: $help{$topic}=&Apache::loncommon::help_open_topic('Docs_'.$topic);
2523: }
2524: # Composite help files
2525: $help{'Syllabus'} = &Apache::loncommon::help_open_topic(
2526: 'Docs_About_Syllabus,Docs_Editing_Templated_Pages');
2527: $help{'Simple Page'} = &Apache::loncommon::help_open_topic(
2528: 'Docs_About_Simple_Page,Docs_Editing_Templated_Pages');
2529: $help{'Simple Problem'} = &Apache::loncommon::help_open_topic(
2530: 'Option_Response_Simple');
2531: $help{'Bulletin Board'} = &Apache::loncommon::help_open_topic(
2532: 'Docs_About_Bulletin_Board,Docs_Editing_Templated_Pages');
2533: $help{'My Personal Information Page'} = &Apache::loncommon::help_open_topic(
2534: 'Docs_About_My_Personal_Info,Docs_Editing_Templated_Pages');
2535: $help{'Group Portfolio'} = &Apache::loncommon::help_open_topic('Docs_About_Group_Files');
2536: $help{'Caching'} = &Apache::loncommon::help_open_topic('Caching');
2537:
2538:
2539: my $allowed;
2540: # URI is /adm/supplemental when viewing supplemental docs in non-edit mode.
2541: unless ($r->uri eq '/adm/supplemental') {
2542: # does this user have privileges to modify content.
2543: $allowed = &Apache::lonnet::allowed('mdc',$env{'request.course.id'});
2544: }
2545:
2546: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['chooseserver',
2547: 'inhibitmenu']);
2548: if ($allowed && $env{'form.chooseserver'}) {
2549: &choose_dump_server($r);
2550: return OK;
2551: } elsif ($allowed && $env{'form.verify'}) {
2552: &init_breadcrumbs('verify','Verify Content');
2553: &verifycontent($r);
2554: } elsif ($allowed && $env{'form.listsymbs'}) {
2555: &init_breadcrumbs('listsymbs','List Content IDs');
2556: &list_symbs($r);
2557: } elsif ($allowed && $env{'form.docslog'}) {
2558: &init_breadcrumbs('docslog','Show Log');
2559: my $folder = $env{'form.folder'};
2560: if ($folder eq '') {
2561: $folder='default';
2562: }
2563: &docs_change_log($r,$coursenum,$coursedom,$folder,$allowed,$crstype,$iconpath);
2564: } elsif ($allowed && $env{'form.versions'}) {
2565: &init_breadcrumbs('versions','Check/Set Resource Versions');
2566: &checkversions($r);
2567: } elsif ($allowed && $env{'form.dumpcourse'}) {
2568: &init_breadcrumbs('dumpcourse','Dump '.&Apache::loncommon::course_type().' Content to Authoring Space');
2569: &dumpcourse($r);
2570: } elsif ($allowed && $env{'form.exportcourse'}) {
2571: &init_breadcrumbs('exportcourse','IMS Export');
2572: &Apache::imsexport::exportcourse($r);
2573: } else {
2574: #
2575: # Done catching special calls
2576: # The whole rest is for course and supplemental documents and utilities menu
2577: # Get the parameters that may be needed
2578: #
2579: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
2580: ['folderpath','pagepath',
2581: 'pagesymb','forcesupplement','forcestandard',
2582: 'tools','symb','command']);
2583:
2584: # standard=1: this is a "new-style" course with an uploaded map as top level
2585: # standard=2: this is a "old-style" course, and there is nothing we can do
2586:
2587: my $standard=($env{'request.course.uri'}=~/^\/uploaded\//);
2588:
2589: # Decide whether this should display supplemental or main content or utilities
2590: # supplementalflag=1: show supplemental documents
2591: # supplementalflag=0: show standard documents
2592: # toolsflag=1: show utilities
2593:
2594:
2595: my $supplementalflag=($env{'form.folderpath'}=~/^supplemental/);
2596: if (($env{'form.folderpath'}=~/^default/) || $env{'form.folderpath'} eq "" || ($env{'form.pagepath'})) {
2597: $supplementalflag=0;
2598: }
2599: if ($env{'form.forcesupplement'}) { $supplementalflag=1; }
2600: if ($env{'form.forcestandard'}) { $supplementalflag=0; }
2601: unless ($allowed) { $supplementalflag=1; }
2602: unless ($standard) { $supplementalflag=1; }
2603: my $toolsflag=0;
2604: if ($env{'form.tools'}) { $toolsflag=1; }
2605:
2606: my $script='';
2607: my $showdoc=0;
2608: my $addentries = {};
2609: my $container;
2610: my $containertag;
2611: my $uploadtag;
2612:
2613: # Do we directly jump somewhere?
2614:
2615: if ($env{'form.command'} eq 'direct') {
2616: my ($mapurl,$id,$resurl);
2617: if ($env{'form.symb'} ne '') {
2618: ($mapurl,$id,$resurl) = &Apache::lonnet::decode_symb($env{'form.symb'});
2619: if ($resurl=~/\.(sequence|page)$/) {
2620: $mapurl=$resurl;
2621: } elsif ($resurl eq 'adm/navmaps') {
2622: $mapurl=$env{'course.'.$env{'request.course.id'}.'.url'};
2623: }
2624: my $mapresobj;
2625: my $navmap = Apache::lonnavmaps::navmap->new();
2626: if (ref($navmap)) {
2627: $mapresobj = $navmap->getResourceByUrl($mapurl);
2628: }
2629: $mapurl=~s{^.*/([^/]+)\.(\w+)$}{$1};
2630: my $type=$2;
2631: my $path;
2632: if (ref($mapresobj)) {
2633: my $pcslist = $mapresobj->map_hierarchy();
2634: if ($pcslist ne '') {
2635: foreach my $pc (split(/,/,$pcslist)) {
2636: next if ($pc <= 1);
2637: my $res = $navmap->getByMapPc($pc);
2638: if (ref($res)) {
2639: my $thisurl = $res->src();
2640: $thisurl=~s{^.*/([^/]+)\.\w+$}{$1};
2641: my $thistitle = $res->title();
2642: $path .= '&'.
2643: &Apache::lonhtmlcommon::entity_encode($thisurl).'&'.
2644: &Apache::lonhtmlcommon::entity_encode($thistitle).
2645: ':'.$res->randompick().
2646: ':'.$res->randomout().
2647: ':'.$res->encrypted().
2648: ':'.$res->randomorder();
2649: }
2650: }
2651: }
2652: $path .= '&'.&Apache::lonhtmlcommon::entity_encode($mapurl).'&'.
2653: &Apache::lonhtmlcommon::entity_encode($mapresobj->title()).
2654: ':'.$mapresobj->randompick().
2655: ':'.$mapresobj->randomout().
2656: ':'.$mapresobj->encrypted().
2657: ':'.$mapresobj->randomorder();
2658: } else {
2659: my $maptitle = &Apache::lonnet::gettitle($mapurl);
2660: $path = '&default&...::::'.
2661: '&'.&Apache::lonhtmlcommon::entity_encode($mapurl).'&'.
2662: &Apache::lonhtmlcommon::entity_encode($maptitle).'::::';
2663: }
2664: $path = 'default&'.
2665: &Apache::lonhtmlcommon::entity_encode('Main Course Documents').
2666: $path;
2667: if ($type eq 'sequence') {
2668: $env{'form.folderpath'}=$path;
2669: $env{'form.pagepath'}='';
2670: } else {
2671: $env{'form.pagepath'}=$path;
2672: $env{'form.folderpath'}='';
2673: }
2674: } elsif ($env{'form.supppath'} ne '') {
2675: $env{'form.folderpath'}=$env{'form.supppath'};
2676: }
2677: } elsif ($env{'form.command'} eq 'editdocs') {
2678: $env{'form.folderpath'} = 'default&'.
2679: &Apache::lonhtmlcommon::entity_encode('Main Course Content');
2680: $env{'form.pagepath'}='';
2681: } elsif ($env{'form.command'} eq 'editsupp') {
2682: $env{'form.folderpath'} = 'default&'.
2683: &Apache::lonhtmlcommon::entity_encode('Supplemental Content');
2684: $env{'form.pagepath'}='';
2685: }
2686:
2687: # Where do we store these for when we come back?
2688: my $stored_folderpath='docs_folderpath';
2689: if ($supplementalflag) {
2690: $stored_folderpath='docs_sup_folderpath';
2691: }
2692:
2693: # No folderpath, no pagepath, see if we have something stored
2694: if ((!$env{'form.folderpath'}) && (!$env{'form.pagepath'})) {
2695: &Apache::loncommon::restore_course_settings($stored_folderpath,
2696: {'folderpath' => 'scalar'});
2697: }
2698:
2699: # If we are not allowed to make changes, all we can see are supplemental docs
2700: if (!$allowed) {
2701: $env{'form.pagepath'}='';
2702: unless ($env{'form.folderpath'} =~ /^supplemental/) {
2703: $env{'form.folderpath'} = &supplemental_base();
2704: }
2705: }
2706: # If we still not have a folderpath, see if we can resurrect at pagepath
2707: if (!$env{'form.folderpath'} && $allowed) {
2708: &Apache::loncommon::restore_course_settings($stored_folderpath,
2709: {'pagepath' => 'scalar'});
2710: }
2711: # Make the zeroth entry in supplemental docs page paths, so we can get to top level
2712: if ($env{'form.folderpath'} =~ /^supplemental_\d+/) {
2713: $env{'form.folderpath'} = &supplemental_base()
2714: .'&'.
2715: $env{'form.folderpath'};
2716: }
2717: # If after all of this, we still don't have any paths, make them
2718: unless (($env{'form.pagepath'}) || ($env{'form.folderpath'})) {
2719: if ($supplementalflag) {
2720: $env{'form.folderpath'}=&supplemental_base();
2721: } else {
2722: $env{'form.folderpath'}='default';
2723: }
2724: }
2725:
2726: # Store this
2727: unless ($toolsflag) {
2728: &Apache::loncommon::store_course_settings($stored_folderpath,
2729: {'pagepath' => 'scalar',
2730: 'folderpath' => 'scalar'});
2731: if ($env{'form.folderpath'}) {
2732: my (@folderpath)=split('&',$env{'form.folderpath'});
2733: $env{'form.foldername'}=&unescape(pop(@folderpath));
2734: $env{'form.folder'}=pop(@folderpath);
2735: $container='sequence';
2736: }
2737: if ($env{'form.pagepath'}) {
2738: my (@pagepath)=split('&',$env{'form.pagepath'});
2739: $env{'form.pagename'}=&unescape(pop(@pagepath));
2740: $env{'form.folder'}=pop(@pagepath);
2741: $container='page';
2742: $containertag = '<input type="hidden" name="pagepath" value="" />'.
2743: '<input type="hidden" name="pagesymb" value="" />';
2744: $uploadtag =
2745: '<input type="hidden" name="pagepath" value="'.&HTML::Entities::encode($env{'form.pagepath'},'<>&"').'" />'.
2746: '<input type="hidden" name="pagesymb" value="'.&HTML::Entities::encode($env{'form.pagesymb'},'<>&"').'" />'.
2747: '<input type="hidden" name="folderpath" value="" />';
2748: } else {
2749: my $folderpath=$env{'form.folderpath'};
2750: if (!$folderpath) {
2751: if ($env{'form.folder'} eq '' ||
2752: $env{'form.folder'} eq 'supplemental') {
2753: $folderpath='default&'.
2754: &escape(&mt('Main '.$crstype.' Documents'));
2755: }
2756: }
2757: $containertag = '<input type="hidden" name="folderpath" value="" />';
2758: $uploadtag = '<input type="hidden" name="folderpath" value="'.&HTML::Entities::encode($folderpath,'<>&"').'" />';
2759: }
2760: if ($r->uri=~/^\/adm\/coursedocs\/showdoc\/(.*)$/) {
2761: $showdoc='/'.$1;
2762: }
2763: if ($showdoc) { # got called in sequence from course
2764: $allowed=0;
2765: } else {
2766: if ($allowed) {
2767: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['cmd']);
2768: $script=&Apache::lonratedt::editscript('simple');
2769: }
2770: }
2771: }
2772:
2773: # get personal data
2774: my $uname=$env{'user.name'};
2775: my $udom=$env{'user.domain'};
2776: my $plainname=&escape(&Apache::loncommon::plainname($uname,$udom));
2777:
2778: if ($allowed) {
2779: if ($toolsflag) {
2780: $script .= &inject_data_js();
2781: my ($home,$other,%outhash)=&authorhosts();
2782: if (!$home && $other) {
2783: my @hosts;
2784: foreach my $aurole (keys(%outhash)) {
2785: unless(grep(/^\Q$outhash{$aurole}\E/,@hosts)) {
2786: push(@hosts,$outhash{$aurole});
2787: }
2788: }
2789: $script .= &dump_switchserver_js(@hosts);
2790: }
2791: } else {
2792: my @tabids;
2793: if ($supplementalflag) {
2794: @tabids = ('002','ee2','ff2');
2795: } else {
2796: @tabids = ('aa1','bb1','cc1','ff1');
2797: unless ($env{'form.pagepath'}) {
2798: unshift(@tabids,'001');
2799: push(@tabids,('dd1','ee1'));
2800: }
2801: }
2802: my $tabidstr = join("','",@tabids);
2803: $script .= &editing_js($udom,$uname,$supplementalflag).
2804: &history_tab_js().
2805: &inject_data_js().
2806: &Apache::lonhtmlcommon::resize_scrollbox_js('docs',$tabidstr);
2807: $addentries = {
2808: onload => "javascript:resize_scrollbox('contentscroll','1','1');",
2809: };
2810: }
2811: }
2812: # -------------------------------------------------------------------- Body tag
2813: $script = '<script type="text/javascript">'."\n"
2814: .'// <![CDATA['."\n"
2815: .$script."\n"
2816: .'// ]]>'."\n"
2817: .'</script>'."\n";
2818:
2819: # Breadcrumbs
2820: &Apache::lonhtmlcommon::clear_breadcrumbs();
2821: unless ($showdoc) {
2822: &Apache::lonhtmlcommon::add_breadcrumb({
2823: href=>"/adm/coursedocs",text=>"$crstype Contents"});
2824:
2825: $r->print(&Apache::loncommon::start_page("$crstype Contents", $script,
2826: {'force_register' => $showdoc,
2827: 'add_entries' => $addentries,
2828: })
2829: .&Apache::loncommon::help_open_menu('','',273,'RAT')
2830: .&Apache::lonhtmlcommon::breadcrumbs(
2831: 'Editing '.$crstype.' Contents',
2832: 'Docs_Adding_Course_Doc')
2833: );
2834: } else {
2835: $r->print(&Apache::loncommon::start_page("$crstype documents",undef,
2836: {'force_register' => $showdoc,}));
2837: }
2838:
2839: my %allfiles = ();
2840: my %codebase = ();
2841: my ($upload_result,$upload_output,$uploadphase);
2842: if ($allowed) {
2843: if (($env{'form.uploaddoc.filename'}) &&
2844: ($env{'form.cmd'}=~/^upload_(\w+)/)) {
2845: my $context = $1;
2846: # Process file upload - phase one - upload and parse primary file.
2847: undef($hadchanges);
2848: $uploadphase = &process_file_upload(\$upload_output,$coursenum,$coursedom,
2849: \%allfiles,\%codebase,$context);
2850: if ($hadchanges) {
2851: &mark_hash_old();
2852: }
2853: $r->print($upload_output);
2854: } elsif ($env{'form.phase'} eq 'upload_embedded') {
2855: # Process file upload - phase two - upload embedded objects
2856: $uploadphase = 'check_embedded';
2857: my $primaryurl = &HTML::Entities::encode($env{'form.primaryurl'},'<>&"');
2858: my $state = &embedded_form_elems($uploadphase,$primaryurl,
2859: $env{'form.newidx'});
2860: my $docuname=$env{'course.'.$env{'request.course.id'}.'.num'};
2861: my $docudom=$env{'course.'.$env{'request.course.id'}.'.domain'};
2862: my ($destination,$dir_root) = &embedded_destination();
2863: my $url_root = '/uploaded/'.$docudom.'/'.$docuname;
2864: my $actionurl = '/adm/coursedocs';
2865: my ($result,$flag) =
2866: &Apache::loncommon::upload_embedded('coursedoc',$destination,
2867: $docuname,$docudom,$dir_root,$url_root,undef,undef,undef,$state,
2868: $actionurl);
2869: $r->print($result.&return_to_editor());
2870: } elsif ($env{'form.phase'} eq 'check_embedded') {
2871: # Process file upload - phase three - modify references in HTML file
2872: $uploadphase = 'modified_orightml';
2873: my $docuname=$env{'course.'.$env{'request.course.id'}.'.num'};
2874: my $docudom=$env{'course.'.$env{'request.course.id'}.'.domain'};
2875: my ($destination,$dir_root) = &embedded_destination();
2876: my $result =
2877: &Apache::loncommon::modify_html_refs('coursedoc',$destination,
2878: $docuname,$docudom,undef,
2879: $dir_root);
2880: $r->print($result.&return_to_editor());
2881: } elsif ($env{'form.phase'} eq 'decompress_uploaded') {
2882: $uploadphase = 'decompress_phase_one';
2883: $r->print(&decompression_phase_one().
2884: &return_to_editor());
2885: } elsif ($env{'form.phase'} eq 'decompress_cleanup') {
2886: $uploadphase = 'decompress_phase_two';
2887: $r->print(&decompression_phase_two().
2888: &return_to_editor());
2889: }
2890: }
2891:
2892: if ($allowed && $toolsflag) {
2893: $r->print(&startContentScreen('tools'));
2894: $r->print(&generate_admin_menu($crstype));
2895: $r->print(&endContentScreen());
2896: } elsif ((!$showdoc) && (!$uploadphase)) {
2897: # -----------------------------------------------------------------------------
2898: my %lt=&Apache::lonlocal::texthash(
2899: 'uplm' => 'Upload a new main '.lc($crstype).' document',
2900: 'upls' => 'Upload a new supplemental '.lc($crstype).' document',
2901: 'impp' => 'Import a document',
2902: 'copm' => 'All documents out of a published map into this folder',
2903: 'upld' => 'Import Document',
2904: 'srch' => 'Search',
2905: 'impo' => 'Import',
2906: 'lnks' => 'Import from Stored Links',
2907: 'selm' => 'Select Map',
2908: 'load' => 'Load Map',
2909: 'reco' => 'Recover Deleted Documents',
2910: 'newf' => 'New Folder',
2911: 'newp' => 'New Composite Page',
2912: 'extr' => 'External Resource',
2913: 'syll' => 'Syllabus',
2914: 'navc' => 'Table of Contents',
2915: 'sipa' => 'Simple Course Page',
2916: 'sipr' => 'Simple Problem',
2917: 'drbx' => 'Drop Box',
2918: 'scuf' => 'External Scores (handgrade, upload, clicker)',
2919: 'bull' => 'Discussion Board',
2920: 'mypi' => 'My Personal Information Page',
2921: 'grpo' => 'Group Portfolio',
2922: 'rost' => 'Course Roster',
2923: 'abou' => 'Personal Information Page for a User',
2924: 'imsf' => 'IMS Import',
2925: 'imsl' => 'Import IMS package',
2926: 'file' => 'File',
2927: 'title' => 'Title',
2928: 'comment' => 'Comment',
2929: 'parse' => 'Upload embedded images/multimedia files if HTML file',
2930: 'nd' => 'Upload Document',
2931: 'pm' => 'Published Map',
2932: 'sd' => 'Special Document',
2933: 'mo' => 'More Options',
2934: );
2935: # -----------------------------------------------------------------------------
2936: my $fileupload=(<<FIUP);
2937: $lt{'file'}:<br />
2938: <input type="file" name="uploaddoc" size="40" />
2939: FIUP
2940:
2941: my $checkbox=(<<CHBO);
2942: <!-- <label>$lt{'parse'}?
2943: <input type="checkbox" name="parserflag" />
2944: </label> -->
2945: <label>
2946: <input type="checkbox" name="parserflag" checked="checked" /> $lt{'parse'}
2947: </label>
2948: CHBO
2949:
2950: my $fileuploada = "<br clear='all' /><input type='submit' value='".$lt{'upld'}."' /> $help{'Uploading_From_Harddrive'}";
2951: my $fileuploadform=(<<FUFORM);
2952: <form name="uploaddocument" action="/adm/coursedocs" method="post" enctype="multipart/form-data">
2953: <input type="hidden" name="active" value="aa" />
2954: $fileupload
2955: <br />
2956: $lt{'title'}:<br />
2957: <input type="text" size="60" name="comment" />
2958: $uploadtag
2959: <input type="hidden" name="cmd" value="upload_default" />
2960: <br />
2961: <span class="LC_nobreak" style="float:left">
2962: $checkbox
2963: </span>
2964: FUFORM
2965: $fileuploadform .= $fileuploada.'</form>';
2966:
2967: my $simpleeditdefaultform=(<<SEDFFORM);
2968: <form action="/adm/coursedocs" method="post" name="simpleeditdefault">
2969: <input type="hidden" name="active" value="bb" />
2970: SEDFFORM
2971: my @simpleeditdefaultforma = (
2972: { '<img class="LC_noBorder LC_middle" src="/res/adm/pages/src.png" alt="'.$lt{srch}.'" onclick="javascript:groupsearch()" />' => "$uploadtag<a class='LC_menubuttons_link' href='javascript:groupsearch()'>$lt{'srch'}</a>" },
2973: { '<img class="LC_noBorder LC_middle" src="/res/adm/pages/res.png" alt="'.$lt{impo}.'" onclick="javascript:groupimport();"/>' => "<a class='LC_menubuttons_link' href='javascript:groupimport();'>$lt{'impo'}</a>$help{'Importing_LON-CAPA_Resource'}" },
2974: { '<img class="LC_noBorder LC_middle" src="/res/adm/pages/wishlist.png" alt="'.$lt{lnks}.'" onclick="javascript:open_StoredLinks_Import();" />' => "<a class='LC_menubuttons_link' href='javascript:open_StoredLinks_Import();'>$lt{'lnks'}</a>" },
2975: );
2976: $simpleeditdefaultform .= &create_form_ul(&create_list_elements(@simpleeditdefaultforma));
2977: $simpleeditdefaultform .=(<<SEDFFORM);
2978: <hr id="bb_hrule" style="width:0px;text-align:left;margin-left:0" />
2979: $lt{'copm'}<br />
2980: <input type="text" size="40" name="importmap" /><br />
2981: <span class="LC_nobreak" style="float:left"><input type="button"
2982: onclick="javascript:openbrowser('simpleeditdefault','importmap','sequence,page','')"
2983: value="$lt{'selm'}" /> <input type="submit" name="loadmap" value="$lt{'load'}" />
2984: $help{'Load_Map'}</span>
2985: </form>
2986: SEDFFORM
2987:
2988: my $extresourcesform=(<<ERFORM);
2989: <form action="/adm/coursedocs" method="post" name="newext">
2990: $uploadtag
2991: <input type="hidden" name="importdetail" value="" />
2992: <a class="LC_menubuttons_link" href="javascript:makenewext('newext');">$lt{'extr'}</a>$help{'Adding_External_Resource'}
2993: </form>
2994: ERFORM
2995:
2996:
2997: if ($allowed) {
2998: &update_paste_buffer($coursenum,$coursedom);
2999: $r->print(<<HIDDENFORM);
3000: <form name="renameform" method="post" action="/adm/coursedocs">
3001: <input type="hidden" name="title" />
3002: <input type="hidden" name="cmd" />
3003: <input type="hidden" name="markcopy" />
3004: <input type="hidden" name="copyfolder" />
3005: $containertag
3006: </form>
3007:
3008: HIDDENFORM
3009: $r->print(&makesimpleeditform($uploadtag)."\n".
3010: &makedocslogform($uploadtag."\n".
3011: '<input type="hidden" name="folder" value="'.
3012: $env{'form.folder'}.'" />'."\n"));
3013: }
3014:
3015: # Generate the tabs
3016: my $mode;
3017: if (($supplementalflag) && (!$allowed)) {
3018: &Apache::lonnavdisplay::startContentScreen($r,'supplemental');
3019: } else {
3020: $r->print(&startContentScreen(($supplementalflag?'suppdocs':'docs')));
3021: }
3022:
3023: #
3024:
3025: my $savefolderpath;
3026:
3027: if ($allowed) {
3028: my $folder=$env{'form.folder'};
3029: if ($folder eq '' || $supplementalflag) {
3030: $folder='default';
3031: $savefolderpath = $env{'form.folderpath'};
3032: $env{'form.folderpath'}='default&'.&escape(&mt('Content'));
3033: $uploadtag = '<input type="hidden" name="folderpath" value="'.
3034: &HTML::Entities::encode($env{'form.folderpath'},'<>&"').'" />';
3035: }
3036: my $postexec='';
3037: if ($folder eq 'default') {
3038: $r->print('<script type="text/javascript">'."\n"
3039: .'// <![CDATA['."\n"
3040: .'this.window.name="loncapaclient";'."\n"
3041: .'// ]]>'."\n"
3042: .'</script>'."\n"
3043: );
3044: } else {
3045: #$postexec='self.close();';
3046: }
3047: my $folderseq='/uploaded/'.$coursedom.'/'.$coursenum.'/default_'.time.
3048: '.sequence';
3049: my $pageseq = '/uploaded/'.$coursedom.'/'.$coursenum.'/default_'.time.
3050: '.page';
3051: my $container='sequence';
3052: if ($env{'form.pagepath'}) {
3053: $container='page';
3054: }
3055: my $readfile='/uploaded/'.$coursedom.'/'.$coursenum.'/'.$folder.'.'.$container;
3056:
3057: my $imspform=(<<IMSPFORM);
3058: <form action="/adm/imsimportdocs" method="post" name="ims">
3059: <input type="hidden" name="folder" value="$folder" />
3060: <a class="LC_menubuttons_link" href="javascript:makeims();">$lt{'imsf'}</a>
3061: </form>
3062: IMSPFORM
3063:
3064: my $newnavform=(<<NNFORM);
3065: <form action="/adm/coursedocs" method="post" name="newnav">
3066: <input type="hidden" name="active" value="cc" />
3067: $uploadtag
3068: <input type="hidden" name="importdetail"
3069: value="$lt{'navc'}=/adm/navmaps" />
3070: <a class="LC_menubuttons_link" href="javascript:document.newnav.submit()">$lt{'navc'}</a>
3071: $help{'Navigate_Content'}
3072: </form>
3073: NNFORM
3074: my $newsmppageform=(<<NSPFORM);
3075: <form action="/adm/coursedocs" method="post" name="newsmppg">
3076: <input type="hidden" name="active" value="cc" />
3077: $uploadtag
3078: <input type="hidden" name="importdetail" value="" />
3079: <a class="LC_menubuttons_link" href="javascript:makesmppage();"> $lt{'sipa'}</a>
3080: $help{'Simple Page'}
3081: </form>
3082: NSPFORM
3083:
3084: my $newsmpproblemform=(<<NSPROBFORM);
3085: <form action="/adm/coursedocs" method="post" name="newsmpproblem">
3086: <input type="hidden" name="active" value="cc" />
3087: $uploadtag
3088: <input type="hidden" name="importdetail" value="" />
3089: <a class="LC_menubuttons_link" href="javascript:makesmpproblem();">$lt{'sipr'}</a>
3090: $help{'Simple Problem'}
3091: </form>
3092:
3093: NSPROBFORM
3094:
3095: my $newdropboxform=(<<NDBFORM);
3096: <form action="/adm/coursedocs" method="post" name="newdropbox">
3097: <input type="hidden" name="active" value="cc" />
3098: $uploadtag
3099: <input type="hidden" name="importdetail" value="" />
3100: <a class="LC_menubuttons_link" href="javascript:makedropbox();">$lt{'drbx'}</a>
3101: </form>
3102: NDBFORM
3103:
3104: my $newexuploadform=(<<NEXUFORM);
3105: <form action="/adm/coursedocs" method="post" name="newexamupload">
3106: <input type="hidden" name="active" value="cc" />
3107: $uploadtag
3108: <input type="hidden" name="importdetail" value="" />
3109: <a class="LC_menubuttons_link" href="javascript:makeexamupload();">$lt{'scuf'}</a>
3110: $help{'Score_Upload_Form'}
3111: </form>
3112: NEXUFORM
3113:
3114: my $newbulform=(<<NBFORM);
3115: <form action="/adm/coursedocs" method="post" name="newbul">
3116: <input type="hidden" name="active" value="cc" />
3117: $uploadtag
3118: <input type="hidden" name="importdetail" value="" />
3119: <a class="LC_menubuttons_link" href="javascript:makebulboard();" >$lt{'bull'}</a>
3120: $help{'Bulletin Board'}
3121: </form>
3122: NBFORM
3123:
3124: my $newaboutmeform=(<<NAMFORM);
3125: <form action="/adm/coursedocs" method="post" name="newaboutme">
3126: <input type="hidden" name="active" value="cc" />
3127: $uploadtag
3128: <input type="hidden" name="importdetail"
3129: value="$plainname=/adm/$udom/$uname/aboutme" />
3130: <a class="LC_menubuttons_link" href="javascript:document.newaboutme.submit()">$lt{'mypi'}</a>
3131: $help{'My Personal Information Page'}
3132: </form>
3133: NAMFORM
3134:
3135: my $newaboutsomeoneform=(<<NASOFORM);
3136: <form action="/adm/coursedocs" method="post" name="newaboutsomeone">
3137: <input type="hidden" name="active" value="cc" />
3138: $uploadtag
3139: <input type="hidden" name="importdetail" value="" />
3140: <a class="LC_menubuttons_link" href="javascript:makeabout();">$lt{'abou'}</a>
3141: </form>
3142: NASOFORM
3143:
3144:
3145: my $newrosterform=(<<NROSTFORM);
3146: <form action="/adm/coursedocs" method="post" name="newroster">
3147: <input type="hidden" name="active" value="cc" />
3148: $uploadtag
3149: <input type="hidden" name="importdetail"
3150: value="$lt{'rost'}=/adm/viewclasslist" />
3151: <a class="LC_menubuttons_link" href="javascript:document.newroster.submit()">$lt{'rost'}</a>
3152: $help{'Course Roster'}
3153: </form>
3154: NROSTFORM
3155:
3156: my $specialdocumentsform;
3157: my @specialdocumentsforma;
3158: my $gradingform;
3159: my @gradingforma;
3160: my $communityform;
3161: my @communityforma;
3162: my $newfolderform;
3163: my $newfolderb;
3164:
3165: my $path = &HTML::Entities::encode($env{'form.folderpath'},'<>&"');
3166:
3167: my $newpageform=(<<NPFORM);
3168: <form action="/adm/coursedocs" method="post" name="newpage">
3169: <input type="hidden" name="folderpath" value="$path" />
3170: <input type="hidden" name="importdetail" value="" />
3171: <input type="hidden" name="active" value="cc" />
3172: <a class="LC_menubuttons_link" href="javascript:makenewpage(document.newpage,'$pageseq');">$lt{'newp'}</a>
3173: $help{'Adding_Pages'}
3174: </form>
3175: NPFORM
3176:
3177:
3178: $newfolderform=(<<NFFORM);
3179: <form action="/adm/coursedocs" method="post" name="newfolder">
3180: <input type="hidden" name="folderpath" value="$path" />
3181: <input type="hidden" name="importdetail" value="" />
3182: <input type="hidden" name="active" value="aa" />
3183: <a href="javascript:makenewfolder(document.newfolder,'$folderseq');">$lt{'newf'}</a>$help{'Adding_Folders'}
3184: </form>
3185: NFFORM
3186:
3187: my $newsylform=(<<NSYLFORM);
3188: <form action="/adm/coursedocs" method="post" name="newsyl">
3189: <input type="hidden" name="active" value="cc" />
3190: $uploadtag
3191: <input type="hidden" name="importdetail"
3192: value="$lt{'syll'}=/public/$coursedom/$coursenum/syllabus" />
3193: <a class="LC_menubuttons_link" href="javascript:document.newsyl.submit()">$lt{'syll'}</a>
3194: $help{'Syllabus'}
3195:
3196: </form>
3197: NSYLFORM
3198:
3199: my $newgroupfileform=(<<NGFFORM);
3200: <form action="/adm/coursedocs" method="post" name="newgroupfiles">
3201: <input type="hidden" name="active" value="cc" />
3202: $uploadtag
3203: <input type="hidden" name="importdetail"
3204: value="$lt{'grpo'}=/adm/$coursedom/$coursenum/aboutme" />
3205: <a class="LC_menubuttons_link" href="javascript:document.newgroupfiles.submit()">$lt{'grpo'}</a>
3206: $help{'Group Portfolio'}
3207: </form>
3208: NGFFORM
3209: @specialdocumentsforma=(
3210: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/page.png" alt="'.$lt{newp}.'" onclick="javascript:makenewpage(document.newpage,\''.$pageseq.'\');" />'=>$newpageform},
3211: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/syllabus.png" alt="'.$lt{syll}.'" onclick="document.newsyl.submit()" />'=>$newsylform},
3212: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/navigation.png" alt="'.$lt{navc}.'" onclick="document.newnav.submit()" />'=>$newnavform},
3213: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/simple.png" alt="'.$lt{sipa}.'" onclick="javascript:makesmppage();" />'=>$newsmppageform},
3214: );
3215: $specialdocumentsform = &create_form_ul(&create_list_elements(@specialdocumentsforma));
3216:
3217:
3218: my @importdoc = (
3219: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/extres.png" alt="'.$lt{extr}.'" onclick="javascript:makenewext(\'newext\');" />'=>$extresourcesform},
3220: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/ims.png" alt="'.$lt{imsf}.'" onclick="javascript:makeims();" />'=>$imspform},);
3221: $fileuploadform = &create_form_ul(&create_list_elements(@importdoc)) . '<hr id="cc_hrule" style="width:0px;text-align:left;margin-left:0" />' . $fileuploadform;
3222:
3223: @gradingforma=(
3224: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/simpprob.png" alt="'.$lt{sipr}.'" onclick="javascript:makesmpproblem();" />'=>$newsmpproblemform},
3225: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/dropbox.png" alt="'.$lt{drbx}.'" onclick="javascript:makedropbox();" />'=>$newdropboxform},
3226: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/scoreupfrm.png" alt="'.$lt{scuf}.'" onclick="javascript:makeexamupload();" />'=>$newexuploadform},
3227:
3228: );
3229: $gradingform = &create_form_ul(&create_list_elements(@gradingforma));
3230:
3231: @communityforma=(
3232: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/bchat.png" alt="'.$lt{bull}.'" onclick="javascript:makebulboard();" />'=>$newbulform},
3233: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/myaboutme.png" alt="'.$lt{mypi}.'" onclick="javascript:makebulboard();" />'=>$newaboutmeform},
3234: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/aboutme.png" alt="'.$lt{abou}.'" onclick="javascript:makeabout();" />'=>$newaboutsomeoneform},
3235: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/clst.png" alt="'.$lt{rost}.'" onclick="document.newroster.submit()" />'=>$newrosterform},
3236: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/groupportfolio.png" alt="'.$lt{grpo}.'" onclick="document.newgroupfiles.submit()" />'=>$newgroupfileform},
3237: );
3238: $communityform = &create_form_ul(&create_list_elements(@communityforma));
3239:
3240: my %orderhash = (
3241: 'aa' => ['Import Content',$fileuploadform],
3242: 'bb' => ['Published Content',$simpleeditdefaultform],
3243: 'cc' => ['Grading Resources',$gradingform],
3244: );
3245: unless ($env{'form.pagepath'}) {
3246: $orderhash{'00'} = ['Newfolder',$newfolderform];
3247: $orderhash{'dd'} = ['Collaboration',$communityform];
3248: $orderhash{'ee'} = ['Special Documents',$specialdocumentsform];
3249: }
3250:
3251: $hadchanges=0;
3252: unless (($supplementalflag || $toolsflag)) {
3253: my $error = &editor($r,$coursenum,$coursedom,$folder,$allowed,'',$crstype,
3254: $supplementalflag,\%orderhash,$iconpath);
3255: if ($error) {
3256: $r->print('<p><span class="LC_error">'.$error.'</span></p>');
3257: }
3258: if ($hadchanges) {
3259: &mark_hash_old();
3260: }
3261:
3262: &changewarning($r,'');
3263: }
3264: }
3265:
3266: # Supplemental documents start here
3267:
3268: my $folder=$env{'form.folder'};
3269: unless ($supplementalflag) {
3270: $folder='supplemental';
3271: }
3272: if ($folder =~ /^supplemental$/ &&
3273: (($env{'form.folderpath'} =~ /^default\&/) || ($env{'form.folderpath'} eq ''))) {
3274: $env{'form.folderpath'} = &supplemental_base();
3275: } elsif ($allowed) {
3276: $env{'form.folderpath'} = $savefolderpath;
3277: }
3278: $env{'form.pagepath'} = '';
3279: if ($allowed) {
3280: my $folderseq=
3281: '/uploaded/'.$coursedom.'/'.$coursenum.'/supplemental_'.time.
3282: '.sequence';
3283:
3284: my $path = &HTML::Entities::encode($env{'form.folderpath'},'<>&"');
3285:
3286: my $supupdocformbtn = "<input type='submit' value='".$lt{'upld'}."' />$help{'Uploading_From_Harddrive'}";
3287: my $supupdocform=(<<SUPDOCFORM);
3288: <form action="/adm/coursedocs" method="post" name="supuploaddocument" enctype="multipart/form-data">
3289: <input type="hidden" name="active" value="ee" />
3290: $fileupload
3291: <br />
3292: <br />
3293: <span class="LC_nobreak">
3294: $checkbox
3295: </span>
3296: <br /><br />
3297: $lt{'comment'}:<br />
3298: <textarea cols="50" rows="4" name="comment"></textarea>
3299: <br />
3300: <input type="hidden" name="folderpath" value="$path" />
3301: <input type="hidden" name="cmd" value="upload_supplemental" />
3302: SUPDOCFORM
3303: $supupdocform .= &create_form_ul(&Apache::lonhtmlcommon::htmltag('li',$supupdocformbtn,{class => 'LC_menubuttons_inline_text'}))."</form>";
3304:
3305: my $supnewfolderform=(<<SNFFORM);
3306: <form action="/adm/coursedocs" method="post" name="supnewfolder">
3307: <input type="hidden" name="active" value="ee" />
3308: <input type="hidden" name="folderpath" value="$path" />
3309: <input type="hidden" name="importdetail" value="" />
3310: <a class="LC_menubuttons_link" href="javascript:makenewfolder(document.supnewfolder,'$folderseq');">$lt{'newf'}</a>
3311: $help{'Adding_Folders'}
3312: </form>
3313: SNFFORM
3314:
3315:
3316: my $supnewextform=(<<SNEFORM);
3317: <form action="/adm/coursedocs" method="post" name="supnewext">
3318: <input type="hidden" name="active" value="ff" />
3319: <input type="hidden" name="folderpath" value="$path" />
3320: <input type="hidden" name="importdetail" value="" />
3321: <a class="LC_menubuttons_link" href="javascript:makenewext('supnewext');">$lt{'extr'}</a> $help{'Adding_External_Resource'}
3322: </form>
3323: SNEFORM
3324:
3325: my $supnewsylform=(<<SNSFORM);
3326: <form action="/adm/coursedocs" method="post" name="supnewsyl">
3327: <input type="hidden" name="active" value="ff" />
3328: <input type="hidden" name="folderpath" value="$path" />
3329: <input type="hidden" name="importdetail"
3330: value="Syllabus=/public/$coursedom/$coursenum/syllabus" />
3331: <a class="LC_menubuttons_link" href="javascript:document.supnewsyl.submit()">$lt{'syll'}</a>
3332: $help{'Syllabus'}
3333: </form>
3334: SNSFORM
3335:
3336: my $supnewaboutmeform=(<<SNAMFORM);
3337: <form action="/adm/coursedocs" method="post" name="supnewaboutme">
3338: <input type="hidden" name="active" value="ff" />
3339: <input type="hidden" name="folderpath" value="$path" />
3340: <input type="hidden" name="importdetail"
3341: value="$plainname=/adm/$udom/$uname/aboutme" />
3342: <a class="LC_menubuttons_link" href="javascript:document.supnewaboutme.submit()">$lt{'mypi'}</a>
3343: $help{'My Personal Information Page'}
3344: </form>
3345: SNAMFORM
3346:
3347:
3348: my @specialdocs = (
3349: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/syllabus.png" alt="'.$lt{syll}.'" onclick="document.supnewsyl.submit()" />'
3350: =>$supnewsylform},
3351: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/myaboutme.png" alt="'.$lt{mypi}.'" onclick="document.supnewaboutme.submit()" />'
3352: =>$supnewaboutmeform},
3353: );
3354: my @supimportdoc = (
3355: {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/extres.png" alt="'.$lt{extr}.'" onclick="javascript:makenewext(\'supnewext\');" />'
3356: =>$supnewextform},
3357: );
3358: $supupdocform = &create_form_ul(&create_list_elements(@supimportdoc)) . '<hr id="ee_hrule" style="width:0px;text-align:left;margin-left:0" />' . $supupdocform;
3359: my %suporderhash = (
3360: '00' => ['Supnewfolder', $supnewfolderform],
3361: 'ee' => ['Import Content',$supupdocform],
3362: 'ff' => ['Special Documents',&create_form_ul(&create_list_elements(@specialdocs))]
3363: );
3364: if ($supplementalflag) {
3365: my $error = &editor($r,$coursenum,$coursedom,$folder,$allowed,'',$crstype,
3366: $supplementalflag,\%suporderhash,$iconpath);
3367: if ($error) {
3368: $r->print('<p><span class="LC_error">'.$error.'</span></p>');
3369: }
3370: }
3371: } elsif ($supplementalflag) {
3372: my $error = &editor($r,$coursenum,$coursedom,$folder,$allowed,'',$crstype,
3373: $supplementalflag,'',$iconpath);
3374: if ($error) {
3375: $r->print('<p><span class="LC_error">'.$error.'</span></p>');
3376: }
3377: }
3378:
3379: $r->print(&endContentScreen());
3380:
3381: if ($allowed) {
3382: $r->print('
3383: <form method="post" name="extimport" action="/adm/coursedocs">
3384: <input type="hidden" name="title" />
3385: <input type="hidden" name="url" />
3386: <input type="hidden" name="useform" />
3387: <input type="hidden" name="residx" />
3388: </form>');
3389: }
3390: } elsif ($showdoc) {
3391: # -------------------------------------------------------- This is showdoc mode
3392: $r->print("<h1>".&mt('Uploaded Document').' - '.
3393: &Apache::lonnet::gettitle($r->uri).'</h1><p>'.
3394: &mt('It is recommended that you use an up-to-date virus scanner before handling this file.')."</p><table>".
3395: &entryline(0,&mt("Click to download or use your browser's Save Link function"),$showdoc).'</table>');
3396: }
3397: }
3398: $r->print(&Apache::loncommon::end_page());
3399: return OK;
3400: }
3401:
3402: sub embedded_form_elems {
3403: my ($phase,$primaryurl,$newidx) = @_;
3404: my $folderpath = &HTML::Entities::encode($env{'form.folderpath'},'<>&"');
3405: return <<STATE;
3406: <input type="hidden" name="folderpath" value="$folderpath" />
3407: <input type="hidden" name="cmd" value="upload_embedded" />
3408: <input type="hidden" name="newidx" value="$newidx" />
3409: <input type="hidden" name="phase" value="$phase" />
3410: <input type="hidden" name="primaryurl" value="$primaryurl" />
3411: STATE
3412: }
3413:
3414: sub embedded_destination {
3415: my $folder=$env{'form.folder'};
3416: my $destination = 'docs/';
3417: if ($folder =~ /^supplemental/) {
3418: $destination = 'supplemental/';
3419: }
3420: if (($folder eq 'default') || ($folder eq 'supplemental')) {
3421: $destination .= 'default/';
3422: } elsif ($folder =~ /^(default|supplemental)_(\d+)$/) {
3423: $destination .= $2.'/';
3424: }
3425: $destination .= $env{'form.newidx'};
3426: my $dir_root = '/userfiles';
3427: return ($destination,$dir_root);
3428: }
3429:
3430: sub return_to_editor {
3431: my $actionurl = '/adm/coursedocs';
3432: return '<p><form name="backtoeditor" method="post" action="'.$actionurl.'" />'."\n".
3433: '<input type="hidden" name="folderpath" value="'.&HTML::Entities::encode($env{'form.folderpath'},'<>&"').'" /></form>'."\n".
3434: '<a href="javascript:document.backtoeditor.submit();">'.&mt('Return to Editor').
3435: '</a></p>';
3436: }
3437:
3438: sub decompression_info {
3439: my ($destination,$dir_root) = &embedded_destination();
3440: my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'};
3441: my $docudom=$env{'course.'.$env{'request.course.id'}.'.domain'};
3442: my $docuname=$env{'course.'.$env{'request.course.id'}.'.num'};
3443: my $container='sequence';
3444: my ($pathitem,$hiddenelem);
3445: my @hiddens = ('newidx','comment','position');
3446: if ($env{'form.pagepath'}) {
3447: $container='page';
3448: $pathitem = 'pagepath';
3449: } else {
3450: $pathitem = 'folderpath';
3451: }
3452: unshift(@hiddens,$pathitem);
3453: foreach my $item (@hiddens) {
3454: if ($env{'form.'.$item}) {
3455: $hiddenelem .= '<input type="hidden" name="'.$item.'" value="'.
3456: $env{'form.'.$item}.'" />'."\n";
3457: }
3458: }
3459: return ($destination,$dir_root,$londocroot,$docudom,$docuname,$container,
3460: $hiddenelem);
3461: }
3462:
3463: sub decompression_phase_one {
3464: my ($dir,$file,$warning,$error,$output);
3465: my ($destination,$dir_root,$londocroot,$docudom,$docuname,$container,$hiddenelem)=
3466: &decompression_info();
3467: if ($env{'form.archiveurl'} !~ m{^/uploaded/\Q$docudom/$docuname/docs/\E(?:default|supplemental|\d+).*/([^/]+)$}) {
3468: $error = &mt('Archive file "[_1]" not in the expected location.',$env{'form.archiveurl'});
3469: } else {
3470: my $file = $1;
3471: $output =
3472: &Apache::loncommon::process_decompression($docudom,$docuname,$file,
3473: $destination,$dir_root,
3474: $hiddenelem);
3475: if ($env{'form.autoextract_camtasia'}) {
3476: $output .= &remove_archive($docudom,$docuname,$container);
3477: }
3478: }
3479: if ($error) {
3480: $output .= '<p class="LC_error">'.&mt('Not extracted.').'<br />'.
3481: $error.'</p>'."\n";
3482: }
3483: if ($warning) {
3484: $output .= '<p class="LC_warning">'.$warning.'</p>'."\n";
3485: }
3486: return $output;
3487: }
3488:
3489: sub decompression_phase_two {
3490: my ($destination,$dir_root,$londocroot,$docudom,$docuname,$container,$hiddenelem)=
3491: &decompression_info();
3492: my $output;
3493: if ($env{'form.archivedelete'}) {
3494: $output = &remove_archive($docudom,$docuname,$container);
3495: }
3496: $output .=
3497: &Apache::loncommon::process_extracted_files('coursedocs',$docudom,$docuname,
3498: $destination,$dir_root,$hiddenelem);
3499: return $output;
3500: }
3501:
3502: sub remove_archive {
3503: my ($docudom,$docuname,$container) = @_;
3504: my $map = $env{'form.folder'}.'.'.$container;
3505: my ($output,$delwarning,$delresult,$url);
3506: my ($errtext,$fatal) = &mapread($docuname,$docudom,$map);
3507: if ($fatal) {
3508: if ($container eq 'page') {
3509: $delwarning = &mt('An error occurred retrieving the contents of the current page.');
3510: } else {
3511: $delwarning = &mt('An error occurred retrieving the contents of the current folder.');
3512: }
3513: $delwarning .= &mt('As a result the archive file has not been removed.');
3514: } else {
3515: my $currcmd = $env{'form.cmd'};
3516: my $position = $env{'form.position'};
3517: if ($position > 0) {
3518: $env{'form.cmd'} = 'del_'.$position;
3519: my ($title,$url,@rrest) =
3520: split(/:/,$LONCAPA::map::resources[$LONCAPA::map::order[$position]]);
3521: if (&handle_edit_cmd($docuname,$docudom)) {
3522: ($errtext,$fatal) = &storemap($docuname,$docudom,$map);
3523: if ($fatal) {
3524: if ($container eq 'page') {
3525: $delwarning = &mt('An error occurred updating the contents of the current page.');
3526: } else {
3527: $delwarning = &mt('An error occurred updating the contents of the current folder.');
3528: }
3529: } else {
3530: $delresult = &mt('Archive file removed.');
3531: }
3532: }
3533: }
3534: $env{'form.cmd'} = $currcmd;
3535: }
3536: if ($delwarning) {
3537: $output = '<p class="LC_warning">'.
3538: $delwarning.
3539: '</p>';
3540: }
3541: if ($delresult) {
3542: $output .= '<p class="LC_info">'.
3543: $delresult.
3544: '</p>';
3545: }
3546: return $output;
3547: }
3548:
3549: sub generate_admin_menu {
3550: my ($crstype) = @_;
3551: my $lc_crstype = lc($crstype);
3552: my ($home,$other,%outhash)=&authorhosts();
3553: my %lt=&Apache::lonlocal::texthash (
3554: 'vc' => 'Verify Content',
3555: 'cv' => 'Check/Set Resource Versions',
3556: 'ls' => 'List Resource Identifiers',
3557: 'imse' => 'Export contents to IMS Archive',
3558: 'dcd' => "Dump $crstype Content to Authoring Space",
3559: );
3560: my ($candump,$dumpurl);
3561: if ($home + $other > 0) {
3562: $candump = 'F';
3563: if ($home) {
3564: $dumpurl = "javascript:injectData(document.courseverify,'dummy','dumpcourse','$lt{'dcd'}')";
3565: } else {
3566: my @hosts;
3567: foreach my $aurole (keys(%outhash)) {
3568: unless(grep(/^\Q$outhash{$aurole}\E/,@hosts)) {
3569: push(@hosts,$outhash{$aurole});
3570: }
3571: }
3572: if (@hosts == 1) {
3573: my $switchto = '/adm/switchserver?otherserver='.$hosts[0].
3574: '&role='.
3575: &HTML::Entities::encode($env{'request.role'},'"<>&').'&origurl='.
3576: &HTML::Entities::encode('/adm/coursedocs?dumpcourse=1','"<>&');
3577: $dumpurl = "javascript:dump_needs_switchserver('$switchto')";
3578: } else {
3579: $dumpurl = "javascript:choose_switchserver_window()";
3580: }
3581: }
3582: }
3583: my @menu=
3584: ({ categorytitle=>'Administration',
3585: items =>[
3586: { linktext => $lt{'vc'},
3587: url => "javascript:injectData(document.courseverify,'dummy','verify','$lt{'vc'}')",
3588: permission => 'F',
3589: help => 'Verify_Content',
3590: icon => 'verify.png',
3591: linktitle => 'Verify contents can be retrieved/rendered',
3592: },
3593: { linktext => $lt{'cv'},
3594: url => "javascript:injectData(document.courseverify,'dummy','versions','$lt{'cv'}')",
3595: permission => 'F',
3596: help => 'Check_Resource_Versions',
3597: icon => 'resversion.png',
3598: linktitle => "View version information for resources in your $lc_crstype, and fix/unfix use of specific versions",
3599: },
3600: { linktext => $lt{'ls'},
3601: url => "javascript:injectData(document.courseverify,'dummy','listsymbs','$lt{'ls'}')",
3602: permission => 'F',
3603: #help => '',
3604: icon => 'symbs.png',
3605: linktitle => "List the unique identifier used for each resource instance in your $lc_crstype"
3606: },
3607: ]
3608: },
3609: { categorytitle=>'Export',
3610: items =>[
3611: { linktext => $lt{'imse'},
3612: url => "javascript:injectData(document.courseverify,'dummy','exportcourse','$lt{'imse'}')",
3613: permission => 'F',
3614: help => 'Docs_Export_Course_Docs',
3615: icon => 'imsexport.png',
3616: linktitle => $lt{'imse'},
3617: },
3618: { linktext => $lt{'dcd'},
3619: url => $dumpurl,
3620: permission => $candump,
3621: #help => '',
3622: icon => 'dump.png',
3623: linktitle => $lt{'dcd'},
3624: },
3625: ]
3626: });
3627: return '<form action="/adm/coursedocs" method="post" name="courseverify">'."\n".
3628: '<input type="hidden" id="dummy" />'."\n".
3629: &Apache::lonhtmlcommon::generate_menu(@menu)."\n".
3630: '</form>';
3631: }
3632:
3633: sub generate_edit_table {
3634: my ($tid,$orderhash_ref,$to_show,$iconpath,$jumpto,$readfile) = @_;
3635: return unless(ref($orderhash_ref) eq 'HASH');
3636: my %orderhash = %{$orderhash_ref};
3637: my $form;
3638: my $activetab;
3639: my $active;
3640: if($env{'form.active'} ne ''){
3641: $activetab = $env{'form.active'};
3642: }
3643: my $backicon = $iconpath.'clickhere.gif';
3644: my $backtext = &mt('To Overview');
3645: $form = '<div class="LC_Box" style="margin:0;">'.
3646: '<ul id="navigation'.$tid.'" class="LC_TabContent">'."\n".
3647: '<li class="goback">'.
3648: '<a href="javascript:toContents('."'$jumpto'".');">'.
3649: '<img src="'.$backicon.'" class="LC_icon" style="border: none; vertical-align: top;"'.
3650: ' alt="'.$backtext.'" />'.$backtext.'</a></li>'."\n".
3651: '<li>'.
3652: '<a href="javascript:groupopen('."'$readfile'".',1);">'.
3653: &mt('Undo Delete').'</a></li>'."\n";
3654: if ($env{'form.docslog'}) {
3655: $form .= '<li class="active">';
3656: } else {
3657: $form .= '<li>';
3658: }
3659: $form .= '<a href="javascript:toggleHistoryDisp(1);">'.
3660: &mt('History').'</a></li>'."\n";
3661: if ($env{'form.docslog'}) {
3662: $form .= '<li><a href="javascript:toggleHistoryDisp(0);">'.
3663: &mt('Edit').'</a></li>'."\n";
3664: }
3665: foreach my $name (reverse(sort(keys(%orderhash)))) {
3666: if($name ne '00'){
3667: if($activetab eq '' || $activetab ne $name){
3668: $active = '';
3669: }elsif($activetab eq $name){
3670: $active = 'class="active"';
3671: }
3672: $form .= '<li style="float:right" '.$active
3673: .' onmouseover="javascript:showPage(this, \''.$name.$tid.'\', \'navigation'.$tid.'\',\'content'.$tid.'\');"'
3674: .' onclick="javascript:showPage(this, \''.$name.$tid.'\', \'navigation'.$tid.'\',\'content'.$tid.'\');"><a href="javascript:;"><b>'.&mt(${$orderhash{$name}}[0]).'</b></a></li>'."\n";
3675: } else {
3676: $form .= '<li '.$active.' style="float:right">'.${$orderhash{$name}}[1].'</li>'."\n";
3677:
3678: }
3679: }
3680: $form .= '</ul>'."\n";
3681: $form .= '<div id="content'.$tid.'" style="padding: 0 0; margin: 0 0; overflow: hidden; clear:right">'."\n";
3682:
3683: if ($to_show ne '') {
3684: $form .= '<div style="padding:0;margin:0;float:left">'.$to_show.'</div>'."\n";
3685: }
3686: foreach my $field (keys(%orderhash)){
3687: if($field ne '00'){
3688: if($activetab eq '' || $activetab ne $field){
3689: $active = 'style="display: none;float:left"';
3690: }elsif($activetab eq $field){
3691: $active = 'style="display:block;float:left"';
3692: }
3693: $form .= '<div id="'.$field.$tid.'"'
3694: .' class="LC_ContentBox" '.$active.'>'.${$orderhash{$field}}[1]
3695: .'</div>'."\n";
3696: }
3697: }
3698: unless ($env{'form.docslog'}) {
3699: $form .= '</div></div>'."\n";
3700: }
3701: return $form;
3702: }
3703:
3704: sub editing_js {
3705: my ($udom,$uname,$supplementalflag) = @_;
3706: my $now = time();
3707: my %lt = &Apache::lonlocal::texthash(
3708: p_mnf => 'Name of New Folder',
3709: t_mnf => 'New Folder',
3710: p_mnp => 'Name of New Page',
3711: t_mnp => 'New Page',
3712: p_mxu => 'Title for the External Score',
3713: p_msp => 'Name of Simple Course Page',
3714: p_msb => 'Title for the Problem',
3715: p_mdb => 'Title for the Drop Box',
3716: p_mbb => 'Title for the Discussion Board',
3717: p_mab => "Enter user:domain for User's Personal Information Page",
3718: p_mab2 => 'Personal Information Page of ',
3719: p_mab_alrt1 => 'Not a valid user:domain',
3720: p_mab_alrt2 => 'Please enter both user and domain in the format user:domain',
3721: p_chn => 'New Title',
3722: p_rmr1 => 'WARNING: Removing a resource makes associated grades and scores inaccessible!',
3723: p_rmr2a => 'Remove[_99]',
3724: p_rmr2b => '?[_99]',
3725: p_ctr1a => 'WARNING: Cutting a resource makes associated grades and scores inaccessible!',
3726: p_ctr1b => 'Grades remain inaccessible if resource is pasted into another folder.',
3727: p_ctr2a => 'Cut[_98]',
3728: p_ctr2b => '?[_98]',
3729: rpck => 'Enter number to pick (e.g., 3)',
3730: );
3731:
3732: my $crstype = &Apache::loncommon::course_type();
3733: my $docs_folderpath = &HTML::Entities::encode($env{'environment.internal.'.$env{'request.course.id'}.'.docs_folderpath.folderpath'},'<>&"');
3734: my $docs_pagepath = &HTML::Entities::encode($env{'environment.internal.'.$env{'request.course.id'}.'.docs_folderpath.pagepath'},'<>&"');
3735: my $main_container_page;
3736: if ($docs_folderpath eq '') {
3737: if ($docs_pagepath ne '') {
3738: $main_container_page = 1;
3739: }
3740: }
3741: my $toplevelmain = 'default&Main%20'.$crstype.'%20Documents';
3742: my $toplevelsupp = &supplemental_base();
3743:
3744: my $backtourl = '/adm/navmaps';
3745: if ($supplementalflag) {
3746: $backtourl = '/adm/supplemental';
3747: }
3748:
3749: return <<ENDNEWSCRIPT;
3750: function makenewfolder(targetform,folderseq) {
3751: var foldername=prompt('$lt{"p_mnf"}','$lt{"t_mnf"}');
3752: if (foldername) {
3753: targetform.importdetail.value=escape(foldername)+"="+folderseq;
3754: targetform.submit();
3755: }
3756: }
3757:
3758: function makenewpage(targetform,folderseq) {
3759: var pagename=prompt('$lt{"p_mnp"}','$lt{"t_mnp"}');
3760: if (pagename) {
3761: targetform.importdetail.value=escape(pagename)+"="+folderseq;
3762: targetform.submit();
3763: }
3764: }
3765:
3766: function makenewext(targetname) {
3767: this.document.forms.extimport.useform.value=targetname;
3768: this.document.forms.extimport.title.value='';
3769: this.document.forms.extimport.url.value='';
3770: this.document.forms.extimport.residx.value='';
3771: window.open('/adm/rat/extpickframe.html');
3772: }
3773:
3774: function edittext(targetname,residx,title,url) {
3775: this.document.forms.extimport.useform.value=targetname;
3776: this.document.forms.extimport.residx.value=residx;
3777: this.document.forms.extimport.url.value=url;
3778: this.document.forms.extimport.title.value=title;
3779: window.open('/adm/rat/extpickframe.html');
3780: }
3781:
3782: function makeexamupload() {
3783: var title=prompt('$lt{"p_mxu"}');
3784: if (title) {
3785: this.document.forms.newexamupload.importdetail.value=
3786: escape(title)+'=/res/lib/templates/examupload.problem';
3787: this.document.forms.newexamupload.submit();
3788: }
3789: }
3790:
3791: function makesmppage() {
3792: var title=prompt('$lt{"p_msp"}');
3793: if (title) {
3794: this.document.forms.newsmppg.importdetail.value=
3795: escape(title)+'=/adm/$udom/$uname/$now/smppg';
3796: this.document.forms.newsmppg.submit();
3797: }
3798: }
3799:
3800: function makesmpproblem() {
3801: var title=prompt('$lt{"p_msb"}');
3802: if (title) {
3803: this.document.forms.newsmpproblem.importdetail.value=
3804: escape(title)+'=/res/lib/templates/simpleproblem.problem';
3805: this.document.forms.newsmpproblem.submit();
3806: }
3807: }
3808:
3809: function makedropbox() {
3810: var title=prompt('$lt{"p_mdb"}');
3811: if (title) {
3812: this.document.forms.newdropbox.importdetail.value=
3813: escape(title)+'=/res/lib/templates/DropBox.problem';
3814: this.document.forms.newdropbox.submit();
3815: }
3816: }
3817:
3818: function makebulboard() {
3819: var title=prompt('$lt{"p_mbb"}');
3820: if (title) {
3821: this.document.forms.newbul.importdetail.value=
3822: escape(title)+'=/adm/$udom/$uname/$now/bulletinboard';
3823: this.document.forms.newbul.submit();
3824: }
3825: }
3826:
3827: function makeabout() {
3828: var user=prompt("$lt{'p_mab'}");
3829: if (user) {
3830: var comp=new Array();
3831: comp=user.split(':');
3832: if ((typeof(comp[0])!=undefined) && (typeof(comp[1])!=undefined)) {
3833: if ((comp[0]) && (comp[1])) {
3834: this.document.forms.newaboutsomeone.importdetail.value=
3835: '$lt{"p_mab2"}'+escape(user)+'=/adm/'+comp[1]+'/'+comp[0]+'/aboutme';
3836: this.document.forms.newaboutsomeone.submit();
3837: } else {
3838: alert("$lt{'p_mab_alrt1'}");
3839: }
3840: } else {
3841: alert("$lt{'p_mab_alrt2'}");
3842: }
3843: }
3844: }
3845:
3846: function makeims() {
3847: var caller = document.forms.ims.folder.value;
3848: var newlocation = "/adm/imsimportdocs?folder="+caller+"&phase=one";
3849: newWindow = window.open("","IMSimport","HEIGHT=700,WIDTH=750,scrollbars=yes");
3850: newWindow.location.href = newlocation;
3851: }
3852:
3853: function finishpick() {
3854: var title=this.document.forms.extimport.title.value;
3855: var url=this.document.forms.extimport.url.value;
3856: var form=this.document.forms.extimport.useform.value;
3857: var residx=this.document.forms.extimport.residx.value;
3858: eval('this.document.forms.'+form+'.importdetail.value="'+title+'='+url+'='+residx+'";this.document.forms.'+form+'.submit();');
3859: }
3860:
3861: function changename(folderpath,index,oldtitle,container,pagesymb) {
3862: var title=prompt('$lt{"p_chn"}',oldtitle);
3863: if (title) {
3864: this.document.forms.renameform.markcopy.value=-1;
3865: this.document.forms.renameform.title.value=title;
3866: this.document.forms.renameform.cmd.value='rename_'+index;
3867: if (container == 'sequence') {
3868: this.document.forms.renameform.folderpath.value=folderpath;
3869: }
3870: if (container == 'page') {
3871: this.document.forms.renameform.pagepath.value=folderpath;
3872: this.document.forms.renameform.pagesymb.value=pagesymb;
3873: }
3874: this.document.forms.renameform.submit();
3875: }
3876: }
3877:
3878: function removeres(folderpath,index,oldtitle,container,pagesymb,skip_confirm) {
3879: if (skip_confirm || confirm('$lt{"p_rmr1"}\\n\\n$lt{"p_rmr2a"} "'+oldtitle+'" $lt{"p_rmr2b"}')) {
3880: this.document.forms.renameform.markcopy.value=-1;
3881: this.document.forms.renameform.cmd.value='del_'+index;
3882: if (container == 'sequence') {
3883: this.document.forms.renameform.folderpath.value=folderpath;
3884: }
3885: if (container == 'page') {
3886: this.document.forms.renameform.pagepath.value=folderpath;
3887: this.document.forms.renameform.pagesymb.value=pagesymb;
3888: }
3889: this.document.forms.renameform.submit();
3890: }
3891: }
3892:
3893: function cutres(folderpath,index,oldtitle,container,pagesymb,folder,skip_confirm) {
3894: if (skip_confirm || confirm('$lt{"p_ctr1a"}\\n$lt{"p_ctr1b"}\\n\\n$lt{"p_ctr2a"} "'+oldtitle+'" $lt{"p_ctr2b"}')) {
3895: this.document.forms.renameform.cmd.value='cut_'+index;
3896: this.document.forms.renameform.markcopy.value=index;
3897: this.document.forms.renameform.copyfolder.value=folder+'.'+container;
3898: if (container == 'sequence') {
3899: this.document.forms.renameform.folderpath.value=folderpath;
3900: }
3901: if (container == 'page') {
3902: this.document.forms.renameform.pagepath.value=folderpath;
3903: this.document.forms.renameform.pagesymb.value=pagesymb;
3904: }
3905: this.document.forms.renameform.submit();
3906: }
3907: }
3908:
3909: function markcopy(folderpath,index,oldtitle,container,pagesymb,folder) {
3910: this.document.forms.renameform.markcopy.value=index;
3911: this.document.forms.renameform.copyfolder.value=folder+'.'+container;
3912: if (container == 'sequence') {
3913: this.document.forms.renameform.folderpath.value=folderpath;
3914: }
3915: if (container == 'page') {
3916: this.document.forms.renameform.pagepath.value=folderpath;
3917: this.document.forms.renameform.pagesymb.value=pagesymb;
3918: }
3919: this.document.forms.renameform.submit();
3920: }
3921:
3922: function updatePick(targetform,index,caller) {
3923: var pickitem = document.getElementById('rpick_'+index);
3924: var picknumitem = document.getElementById('rpicknum_'+index);
3925: if (pickitem.checked) {
3926: var picknum=prompt('$lt{"rpck"}',picknumitem.value);
3927: if (picknum == '' || picknum == null) {
3928: if (caller == 'check') {
3929: pickitem.checked=false;
3930: return;
3931: }
3932: } else {
3933: picknum.toString();
3934: var regexdigit=/^\\d+\$/;
3935: if (regexdigit.test(picknum)) {
3936: picknumitem.value = picknum;
3937: targetform.changeparms.value='randompick';
3938: targetform.submit();
3939: } else {
3940: if (caller == 'check') {
3941: pickitem.checked=false;
3942: }
3943: return;
3944: }
3945: }
3946: } else {
3947: picknumitem.value = 0;
3948: targetform.changeparms.value='randompick';
3949: targetform.submit();
3950: }
3951: }
3952:
3953: function unselectInactive(nav) {
3954: currentNav = document.getElementById(nav);
3955: currentLis = currentNav.getElementsByTagName('LI');
3956: for (i = 0; i < currentLis.length; i++) {
3957: if (currentLis[i].className == 'goback') {
3958: currentLis[i].className = 'goback';
3959: } else {
3960: if (currentLis[i].className == 'right active' || currentLis[i].className == 'right') {
3961: currentLis[i].className = 'right';
3962: } else {
3963: currentLis[i].className = 'i';
3964: }
3965: }
3966: }
3967: }
3968:
3969: function hideAll(current, nav, data) {
3970: unselectInactive(nav);
3971: if(current.className == 'right'){
3972: current.className = 'right active'
3973: }else{
3974: current.className = 'active';
3975: }
3976: currentData = document.getElementById(data);
3977: currentDivs = currentData.getElementsByTagName('DIV');
3978: for (i = 0; i < currentDivs.length; i++) {
3979: if(currentDivs[i].className == 'LC_ContentBox'){
3980: currentDivs[i].style.display = 'none';
3981: }
3982: }
3983: }
3984:
3985: function openTabs(pageId) {
3986: tabnav = document.getElementById(pageId).getElementsByTagName('UL');
3987: if(tabnav.length > 2 ){
3988: currentNav = document.getElementById(tabnav[1].id);
3989: currentLis = currentNav.getElementsByTagName('LI');
3990: for(i = 0; i< currentLis.length; i++){
3991: if(currentLis[i].className == 'active') {
3992: funcString = currentLis[i].onclick.toString();
3993: tab = funcString.split('"');
3994: if(tab.length < 2) {
3995: tab = funcString.split("'");
3996: }
3997: currentData = document.getElementById(tab[1]);
3998: currentData.style.display = 'block';
3999: }
4000: }
4001: }
4002: }
4003:
4004: function showPage(current, pageId, nav, data) {
4005: hideAll(current, nav, data);
4006: openTabs(pageId);
4007: unselectInactive(nav);
4008: current.className = 'active';
4009: currentData = document.getElementById(pageId);
4010: currentData.style.display = 'block';
4011: activeTab = pageId;
4012: if (nav == 'mainnav') {
4013: var storedpath = "$docs_folderpath";
4014: if (storedpath == '') {
4015: storedpath = "$docs_pagepath";
4016: }
4017: var storedpage = "$main_container_page";
4018: var reg = new RegExp("^supplemental");
4019: if (pageId == 'mainCourseDocuments') {
4020: if (storedpage == 1) {
4021: document.simpleedit.folderpath.value = '';
4022: document.uploaddocument.folderpath.value = '';
4023: } else {
4024: if (reg.test(storedpath)) {
4025: document.simpleedit.folderpath.value = '$toplevelmain';
4026: document.uploaddocument.folderpath.value = '$toplevelmain';
4027: document.newext.folderpath.value = '$toplevelmain';
4028: } else {
4029: document.simpleedit.folderpath.value = storedpath;
4030: document.uploaddocument.folderpath.value = storedpath;
4031: document.newext.folderpath.value = storedpath;
4032: }
4033: }
4034: } else {
4035: if (reg.test(storedpath)) {
4036: document.simpleedit.folderpath.value = storedpath;
4037: document.supuploaddocument.folderpath.value = storedpath;
4038: document.supnewext.folderpath.value = storedpath;
4039: } else {
4040: document.simpleedit.folderpath.value = '$toplevelsupp';
4041: document.supuploaddocument.folderpath.value = '$toplevelsupp';
4042: document.supnewext.folderpath.value = '$toplevelsupp';
4043: }
4044: }
4045: }
4046: resize_scrollbox('contentscroll','1','0');
4047: return false;
4048: }
4049:
4050: function toContents(jumpto) {
4051: var newurl = '$backtourl';
4052: if (jumpto != '') {
4053: newurl = newurl+'?postdata='+jumpto;
4054: ;
4055: }
4056: location.href=newurl;
4057: }
4058:
4059: ENDNEWSCRIPT
4060: }
4061:
4062: sub history_tab_js {
4063: return <<"ENDHIST";
4064: function toggleHistoryDisp(choice) {
4065: document.docslogform.docslog.value = choice;
4066: document.docslogform.submit();
4067: return;
4068: }
4069:
4070: ENDHIST
4071: }
4072:
4073: sub inject_data_js {
4074: return <<ENDINJECT;
4075:
4076: function injectData(current, hiddenField, name, value) {
4077: currentElement = document.getElementById(hiddenField);
4078: currentElement.name = name;
4079: currentElement.value = value;
4080: current.submit();
4081: }
4082:
4083: ENDINJECT
4084: }
4085:
4086: sub dump_switchserver_js {
4087: my @hosts = @_;
4088: my %lt = &Apache::lonlocal::texthash(
4089: dump => 'Dumping to Authoring Space requires switching server.',
4090: swit => 'Switch server?',
4091: duco => 'Dump content to Authoring Space',
4092: yone => 'You need to switch to a server housing an Authoring Space for which you are author or co-author.',
4093: chos => 'Choose server',
4094: );
4095: my $role = $env{'request.role'};
4096: my $js = <<"ENDSWJS";
4097: <script type="text/javascript">
4098: function write_switchserver() {
4099: var server;
4100: if (document.setserver.posshosts.length > 0) {
4101: for (var i=0; i<document.setserver.posshosts.length; i++) {
4102: if (document.setserver.posshosts[i].checked) {
4103: server = document.setserver.posshosts[i].value;
4104: }
4105: }
4106: opener.document.location.href="/adm/switchserver?otherserver="+server+"&role=$role&origurl=/adm/coursedocs";
4107: }
4108: window.close();
4109: }
4110: </script>
4111:
4112: ENDSWJS
4113:
4114: my $startpage = &Apache::loncommon::start_page('Choose server',$js,
4115: {'only_body' => 1,
4116: 'js_ready' => 1,});
4117: my $endpage = &Apache::loncommon::end_page({'js_ready' => 1});
4118:
4119: my $hostpicker;
4120: my $count = 0;
4121: foreach my $host (sort(@hosts)) {
4122: my $checked;
4123: if ($count == 0) {
4124: $checked = ' checked="checked"';
4125: }
4126: $hostpicker .= '<label><input type="radio" name="posshosts" value="'.
4127: $host.'"'.$checked.' />'.$host.'</label> ';
4128: $count++;
4129: }
4130:
4131: return <<"ENDSWITCHJS";
4132:
4133: function dump_needs_switchserver(url) {
4134: if (url!='' && url!= null) {
4135: if (confirm("$lt{'dump'}\\n$lt{'swit'}")) {
4136: go(url);
4137: }
4138: }
4139: return;
4140: }
4141:
4142: function choose_switchserver_window() {
4143: newWindow = window.open('','ChooseServer','height=400,width=500,scrollbars=yes')
4144: newWindow.document.open();
4145: newWindow.document.writeln('$startpage');
4146: newWindow.document.write('<h3>$lt{'duco'}<\\/h3>\\n'+
4147: '<p>$lt{'yone'}<\\/p>\\n'+
4148: '<div class="LC_left_float"><fieldset><legend>$lt{'chos'}<\\/legend>\\n'+
4149: '<form name="setserver" method="post" action="" \\/>\\n'+
4150: '$hostpicker\\n'+
4151: '<br \\/><br \\/>\\n'+
4152: '<input type="button" name="makeswitch" value="$lt{'swit'}" '+
4153: 'onclick="write_switchserver();" \\/>\\n'+
4154: '<\\/form><\\/fieldset><\\/div><br clear="all" \\/>\\n');
4155: newWindow.document.writeln('$endpage');
4156: newWindow.document.close();
4157: newWindow.focus();
4158: }
4159:
4160: ENDSWITCHJS
4161: }
4162:
4163: sub makedocslogform {
4164: my ($formelems,$docslog) = @_;
4165: return <<"LOGSFORM";
4166: <form action="/adm/coursedocs" method="post" name="docslogform">
4167: <input type="hidden" name="docslog" value="$docslog" />
4168: $formelems
4169: </form>
4170: LOGSFORM
4171: }
4172:
4173: sub makesimpleeditform {
4174: my ($formelems) = @_;
4175: return <<"SIMPFORM";
4176: <form name="simpleedit" method="post" action="/adm/coursedocs">
4177: <input type="hidden" name="importdetail" value="" />
4178: $formelems
4179: </form>
4180: SIMPFORM
4181: }
4182:
4183: 1;
4184: __END__
4185:
4186:
4187: =head1 NAME
4188:
4189: Apache::londocs.pm
4190:
4191: =head1 SYNOPSIS
4192:
4193: This is part of the LearningOnline Network with CAPA project
4194: described at http://www.lon-capa.org.
4195:
4196: =head1 SUBROUTINES
4197:
4198: =over
4199:
4200: =item %help=()
4201:
4202: Available help topics
4203:
4204: =item mapread()
4205:
4206: Mapread read maps into LONCAPA::map:: global arrays
4207: @order and @resources, determines status
4208: sets @order - pointer to resources in right order
4209: sets @resources - array with the resources with correct idx
4210:
4211: =item authorhosts()
4212:
4213: Return hash with valid author names
4214:
4215: =item clean()
4216:
4217: =item dumpcourse()
4218:
4219: Actually dump course
4220:
4221: =item group_import()
4222:
4223: Imports the given (name, url) resources into the course
4224: coursenum, coursedom, and folder must precede the list
4225:
4226: =item breadcrumbs()
4227:
4228: =item log_docs()
4229:
4230: =item docs_change_log()
4231:
4232: =item update_paste_buffer()
4233:
4234: =item print_paste_buffer()
4235:
4236: =item do_paste_from_buffer()
4237:
4238: =item update_parameter()
4239:
4240: =item handle_edit_cmd()
4241:
4242: =item editor()
4243:
4244: =item process_file_upload()
4245:
4246: =item process_secondary_uploads()
4247:
4248: =item is_supplemental_title()
4249:
4250: =item entryline()
4251:
4252: =item tiehash()
4253:
4254: =item untiehash()
4255:
4256: =item checkonthis()
4257:
4258: check on this
4259:
4260: =item verifycontent()
4261:
4262: Verify Content
4263:
4264: =item devalidateversioncache() & checkversions()
4265:
4266: Check Versions
4267:
4268: =item mark_hash_old()
4269:
4270: =item is_hash_old()
4271:
4272: =item changewarning()
4273:
4274: =item init_breadcrumbs()
4275:
4276: Breadcrumbs for special functions
4277:
4278: =item create_list_elements()
4279:
4280: =item create_form_ul()
4281:
4282: =item startContentScreen()
4283:
4284: =item endContentScreen()
4285:
4286: =item supplemental_base()
4287:
4288: =item embedded_form_elems()
4289:
4290: =item embedded_destination()
4291:
4292: =item return_to_editor()
4293:
4294: =item decompression_info()
4295:
4296: =item decompression_phase_one()
4297:
4298: =item decompression_phase_two()
4299:
4300: =item remove_archive()
4301:
4302: =item generate_admin_menu()
4303:
4304: =item generate_edit_table()
4305:
4306: =item editing_js()
4307:
4308: =item history_tab_js()
4309:
4310: =item inject_data_js()
4311:
4312: =item dump_switchserver_js()
4313:
4314: =item resize_scrollbox_js()
4315:
4316: =item makedocslogform()
4317:
4318: =item makesimpleeditform()
4319:
4320: =back
4321:
4322: =cut
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>