Annotation of loncom/interface/londocs.pm, revision 1.282
1.1 www 1: # The LearningOnline Network
1.2 www 2: # Documents
1.1 www 3: #
1.282 ! albertel 4: # $Id: londocs.pm,v 1.281 2007/06/29 23:25:30 albertel Exp $
1.1 www 5: #
1.3 www 6: # Copyright Michigan State University Board of Trustees
1.1 www 7: #
1.3 www 8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
1.1 www 9: #
1.3 www 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.
1.1 www 14: #
1.3 www 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:
1.2 www 29: package Apache::londocs;
1.1 www 30:
31: use strict;
1.28 www 32: use Apache::Constants qw(:common :http);
1.158 raeburn 33: use Apache::imsexport;
1.4 www 34: use Apache::lonnet;
35: use Apache::loncommon;
1.245 albertel 36: use LONCAPA::map();
37: use Apache::lonratedt();
1.15 www 38: use Apache::lonxml;
1.244 albertel 39: use Apache::lonclonecourse;
1.138 raeburn 40: use Apache::lonnavmaps;
1.38 www 41: use HTML::Entities;
1.27 www 42: use GDBM_File;
1.81 www 43: use Apache::lonlocal;
1.143 raeburn 44: use Cwd;
1.264 albertel 45: use LONCAPA qw(:DEFAULT :match);
1.7 www 46:
1.8 www 47: my $iconpath;
1.7 www 48:
1.27 www 49: my %hash;
50:
51: my $hashtied;
1.29 www 52: my %alreadyseen=();
1.27 www 53:
1.40 www 54: my $hadchanges;
55:
1.47 www 56: # Available help topics
57:
58: my %help=();
59:
1.245 albertel 60: # Mapread read maps into LONCAPA::map:: global arrays
1.10 www 61: # @order and @resources, determines status
1.7 www 62: # sets @order - pointer to resources in right order
63: # sets @resources - array with the resources with correct idx
64: #
65:
66: sub mapread {
67: my ($coursenum,$coursedom,$map)=@_;
68: return
1.245 albertel 69: &LONCAPA::map::mapread('/uploaded/'.$coursedom.'/'.$coursenum.'/'.
70: $map);
1.7 www 71: }
72:
73: sub storemap {
74: my ($coursenum,$coursedom,$map)=@_;
1.104 albertel 75: my ($outtext,$errtext)=
1.245 albertel 76: &LONCAPA::map::storemap('/uploaded/'.$coursedom.'/'.$coursenum.'/'.
77: $map,1);
1.104 albertel 78: if ($errtext) { return ($errtext,2); }
79:
80: $hadchanges=1;
81: return ($errtext,0);
1.7 www 82: }
83:
1.74 www 84: # ----------------------------------------- Return hash with valid author names
85:
86: sub authorhosts {
87: my %outhash=();
88: my $home=0;
89: my $other=0;
1.174 albertel 90: foreach (keys %env) {
1.74 www 91: if ($_=~/^user\.role\.(au|ca)\.(.+)$/) {
92: my $role=$1;
93: my $realm=$2;
1.174 albertel 94: my ($start,$end)=split(/\./,$env{$_});
1.74 www 95: if (($start) && ($start>time)) { next; }
96: if (($end) && (time>$end)) { next; }
97: my $ca; my $cd;
98: if ($1 eq 'au') {
1.174 albertel 99: $ca=$env{'user.name'};
100: $cd=$env{'user.domain'};
1.74 www 101: } else {
1.264 albertel 102: ($cd,$ca)=($realm=~/^\/($match_domain)\/($match_username)$/);
1.74 www 103: }
1.107 albertel 104: my $allowed=0;
105: my $myhome=&Apache::lonnet::homeserver($ca,$cd);
106: my @ids=&Apache::lonnet::current_machine_ids();
107: foreach my $id (@ids) { if ($id eq $myhome) { $allowed=1; } }
108: if ($allowed) {
1.74 www 109: $home++;
110: $outhash{'home_'.$ca.'@'.$cd}=1;
111: } else {
1.107 albertel 112: $outhash{'otherhome_'.$ca.'@'.$cd}=$myhome;
1.74 www 113: $other++;
114: }
115: }
116: }
117: return ($home,$other,%outhash);
118: }
119: # ------------------------------------------------------ Generate "dump" button
120:
121: sub dumpbutton {
122: my ($home,$other,%outhash)=&authorhosts();
1.230 albertel 123: my $type = &Apache::loncommon::course_type();
1.74 www 124: if ($home+$other==0) { return ''; }
125: my $output='</td><td bgcolor="#DDDDCC">';
126: if ($home) {
127: return '</td><td bgcolor="#DDDDCC">'.
1.81 www 128: '<input type="submit" name="dumpcourse" value="'.
1.230 albertel 129: &mt('Dump '.$type.' DOCS to Construction Space').'" />'.
1.130 www 130: &Apache::loncommon::help_open_topic('Docs_Dump_Course_Docs');
1.74 www 131: } else {
132: return'</td><td bgcolor="#DDDDCC">'.
1.230 albertel 133: &mt('Dump '.$type.
134: ' DOCS to Construction Space: available on other servers');
1.74 www 135: }
136: }
137:
1.164 albertel 138: sub clean {
139: my ($title)=@_;
140: $title=~s/[^\w\/\!\$\%\^\*\-\_\=\+\;\:\,\\\|\`\~]+/\_/gs;
141: return $title;
142: }
1.74 www 143: # -------------------------------------------------------- Actually dump course
144:
145: sub dumpcourse {
1.224 albertel 146: my ($r) = @_;
1.230 albertel 147: my $type = &Apache::loncommon::course_type();
148: $r->print(&Apache::loncommon::start_page('Dump '.$type.' DOCS to Construction Space').
149: '<form name="dumpdoc" method="post">');
1.257 www 150: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Dump '.$type.' DOCS to Construction Space'));
1.74 www 151: my ($home,$other,%outhash)=&authorhosts();
1.75 www 152: unless ($home) { return ''; }
1.174 albertel 153: my $origcrsid=$env{'request.course.id'};
1.76 www 154: my %origcrsdata=&Apache::lonnet::coursedescription($origcrsid);
1.174 albertel 155: if (($env{'form.authorspace'}) && ($env{'form.authorfolder'}=~/\w/)) {
1.76 www 156: # Do the dumping
1.174 albertel 157: unless ($outhash{'home_'.$env{'form.authorspace'}}) { return ''; }
158: my ($ca,$cd)=split(/\@/,$env{'form.authorspace'});
1.87 www 159: $r->print('<h3>'.&mt('Copying Files').'</h3>');
1.174 albertel 160: my $title=$env{'form.authorfolder'};
1.164 albertel 161: $title=&clean($title);
1.79 www 162: my %replacehash=();
1.174 albertel 163: foreach (keys %env) {
1.79 www 164: if ($_=~/^form\.namefor\_(.+)/) {
1.174 albertel 165: $replacehash{$1}=$env{$_};
1.79 www 166: }
167: }
1.174 albertel 168: my $crs='/uploaded/'.$env{'request.course.id'}.'/';
1.79 www 169: $crs=~s/\_/\//g;
170: foreach (keys %replacehash) {
171: my $newfilename=$title.'/'.$replacehash{$_};
1.205 albertel 172: $newfilename=~s/\.(\w+)$//;
173: my $ext=$1;
1.164 albertel 174: $newfilename=&clean($newfilename);
1.205 albertel 175: $newfilename.='.'.$ext;
1.79 www 176: my @dirs=split(/\//,$newfilename);
177: my $path='/home/'.$ca.'/public_html';
178: my $makepath=$path;
179: my $fail=0;
180: for (my $i=0;$i<$#dirs;$i++) {
181: $makepath.='/'.$dirs[$i];
182: unless (-e $makepath) {
183: unless(mkdir($makepath,0777)) { $fail=1; }
184: }
185: }
186: $r->print('<br /><tt>'.$_.'</tt> => <tt>'.$newfilename.'</tt>: ');
187: if (my $fh=Apache::File->new('>'.$path.'/'.$newfilename)) {
188: if ($_=~/\.(sequence|page|html|htm|xml|xhtml)$/) {
1.244 albertel 189: print $fh &Apache::lonclonecourse::rewritefile(
190: &Apache::lonclonecourse::readfile($env{'request.course.id'},$_),
1.79 www 191: (%replacehash,$crs => '')
192: );
193: } else {
194: print $fh
1.244 albertel 195: &Apache::lonclonecourse::readfile($env{'request.course.id'},$_);
1.79 www 196: }
197: $fh->close();
198: } else {
199: $fail=1;
200: }
201: if ($fail) {
202: $r->print('<font color="red">fail</font>');
203: } else {
204: $r->print('<font color="green">ok</font>');
205: }
206: }
1.76 www 207: } else {
208: # Input form
209: unless ($home==1) {
210: $r->print(
1.81 www 211: '<h3>'.&mt('Select the Construction Space').'</h3><select name="authorspace">');
1.76 www 212: }
213: foreach (sort keys %outhash) {
214: if ($_=~/^home_(.+)$/) {
215: if ($home==1) {
216: $r->print(
217: '<input type="hidden" name="authorspace" value="'.$1.'" />');
218: } else {
1.133 www 219: $r->print('<option value="'.$1.'">'.$1.' - '.
220: &Apache::loncommon::plainname(split(/\@/,$1)).'</option>');
1.76 www 221: }
222: }
223: }
224: unless ($home==1) {
225: $r->print('</select>');
226: }
227: my $title=$origcrsdata{'description'};
1.227 albertel 228: $title=~s/[\/\s]+/\_/gs;
1.164 albertel 229: $title=&clean($title);
1.81 www 230: $r->print('<h3>'.&mt('Folder in Construction Space').'</h3><input type="text" size="50" name="authorfolder" value="'.$title.'" /><br />');
1.76 www 231: &tiehash();
1.81 www 232: $r->print('<h3>'.&mt('Filenames in Construction Space').'</h3><table border="2"><tr><th>'.&mt('Internal Filename').'</th><th>'.&mt('Title').'</th><th>'.&mt('Save as ...').'</th></tr>');
1.244 albertel 233: foreach (&Apache::lonclonecourse::crsdirlist($origcrsid,'userfiles')) {
1.78 www 234: $r->print('<tr><td>'.$_.'</td>');
235: my ($ext)=($_=~/\.(\w+)$/);
236: my $title=$hash{'title_'.$hash{
237: 'ids_/uploaded/'.$origcrsdata{'domain'}.'/'.$origcrsdata{'num'}.'/'.$_}};
238: $r->print('<td>'.($title?$title:' ').'</td>');
1.235 albertel 239: if (!$title) {
1.78 www 240: $title=$_;
1.235 albertel 241: } else {
242: $title=~s|/|_|g;
1.78 www 243: }
244: $title=~s/\.(\w+)$//;
1.164 albertel 245: $title=&clean($title);
1.78 www 246: $title.='.'.$ext;
1.79 www 247: $r->print("\n<td><input type='text' size='60' name='namefor_".$_."' value='".$title."' /></td></tr>\n");
1.76 www 248: }
1.78 www 249: $r->print("</table>\n");
1.76 www 250: &untiehash();
251: $r->print(
1.229 raeburn 252: '<p><input type="submit" name="dumpcourse" value="'.&mt('Dump [_1] DOCS',$type).'" /></p></form>');
1.75 www 253: }
1.74 www 254: }
1.76 www 255:
1.138 raeburn 256: # ------------------------------------------------------ Generate "export" button
257:
258: sub exportbutton {
1.230 albertel 259: my $type = &Apache::loncommon::course_type();
1.138 raeburn 260: return '</td><td bgcolor="#DDDDCC">'.
261: '<input type="submit" name="exportcourse" value="'.
1.230 albertel 262: &mt('Export '.$type.' to IMS').'" />'.
1.203 raeburn 263: &Apache::loncommon::help_open_topic('Docs_Export_Course_Docs');
1.138 raeburn 264: }
265:
266: sub exportcourse {
267: my $r=shift;
1.230 albertel 268: my $type = &Apache::loncommon::course_type();
1.138 raeburn 269: my %discussiontime = &Apache::lonnet::dump('discussiontimes',
1.174 albertel 270: $env{'course.'.$env{'request.course.id'}.'.domain'}, $env{'course.'.$env{'request.course.id'}.'.num'});
1.138 raeburn 271: my $numdisc = keys %discussiontime;
272: my $navmap = Apache::lonnavmaps::navmap->new();
273: my $it=$navmap->getIterator(undef,undef,undef,1,undef,undef);
274: my $curRes;
1.143 raeburn 275: my $outcome;
1.138 raeburn 276:
277: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
278: ['finishexport']);
1.174 albertel 279: if ($env{'form.finishexport'}) {
1.138 raeburn 280: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
281: ['archive','discussion']);
282:
1.175 albertel 283: my @exportitems = &Apache::loncommon::get_env_multiple('form.archive');
284: my @discussions = &Apache::loncommon::get_env_multiple('form.discussion');
1.143 raeburn 285: if (@exportitems == 0 && @discussions == 0) {
286: $outcome = '<br />As you did not select any content items or discussions for export, an IMS package has not been created. Please <a href="javascript:history.go(-1)">go back</a> to select either content items or discussions for export';
287: } else {
288: my $now = time;
289: my %symbs;
290: my $manifestok = 0;
291: my $imsresources;
292: my $tempexport;
293: my $copyresult;
294: my $ims_manifest = &create_ims_store($now,\$manifestok,\$outcome,\$tempexport);
295: if ($manifestok) {
1.157 raeburn 296: &build_package($now,$navmap,\@exportitems,\@discussions,\$outcome,$tempexport,\$copyresult,$ims_manifest);
1.143 raeburn 297: close($ims_manifest);
298:
299: #Create zip file in prtspool
300: my $imszipfile = '/prtspool/'.
1.174 albertel 301: $env{'user.name'}.'_'.$env{'user.domain'}.'_'.
1.143 raeburn 302: time.'_'.rand(1000000000).'.zip';
303: my $cwd = &Cwd::getcwd();
304: my $imszip = '/home/httpd/'.$imszipfile;
305: chdir $tempexport;
306: open(OUTPUT, "zip -r $imszip * 2> /dev/null |");
307: close(OUTPUT);
308: chdir $cwd;
1.230 albertel 309: $outcome .= &mt('Download the zip file from <a href="[_1]">IMS '.lc($type).' archive</a><br />',$imszipfile,);
1.143 raeburn 310: if ($copyresult) {
311: $outcome .= 'The following errors occurred during export - '.$copyresult;
1.138 raeburn 312: }
1.143 raeburn 313: } else {
314: $outcome = '<br />Unfortunately you will not be able to retrieve an IMS archive of this posts at this time, because there was a problem creating a manifest file.<br />';
1.138 raeburn 315: }
316: }
1.229 raeburn 317: $r->print(&Apache::loncommon::start_page('Export '.lc($type).' to IMS content package'));
1.257 www 318: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Export '.lc($type).' to IMS content package'));
1.143 raeburn 319: $r->print($outcome);
1.224 albertel 320: $r->print(&Apache::loncommon::end_page());
1.138 raeburn 321: } else {
322: my $display;
323: $display = '<form name="exportdoc" method="post">'."\n";
1.230 albertel 324: $display .= &mt('Choose which items you wish to export from your '.$type.'.<br /><br />');
1.138 raeburn 325: $display .= '<table border="0" cellspacing="0" cellpadding="3">'.
326: '<tr><td><fieldset><legend> <b>Content items</b></legend>'.
327: '<input type="button" value="check all" '.
328: 'onclick="javascript:checkAll(document.exportdoc.archive)" />'.
329: ' <input type="button" value="uncheck all"'.
330: ' onclick="javascript:uncheckAll(document.exportdoc.archive)" /></fieldset></td>'.
331: '<td> </td><td> </td>'.
332: '<td align="right"><fieldset><legend> <b>Discussion posts'.
333: '</b></legend><input type="button" value="check all"'.
334: ' onclick="javascript:checkAll(document.exportdoc.discussion)" />'.
335: ' <input type="button" value="uncheck all"'.
336: ' onclick="javascript:uncheckAll(document.exportdoc.discussion)" /></fieldset></td>'.
337: '</tr></table>';
338: my $curRes;
339: my $depth = 0;
340: my $count = 0;
341: my $boards = 0;
342: my $startcount = 5;
343: my %parent = ();
344: my %children = ();
345: my $lastcontainer = $startcount;
346: my @bgcolors = ('#F6F6F6','#FFFFFF');
347: $display .= '<table cellspacing="0"><tr>'.
348: '<td><b>Export content item?<br /></b></td><td> </td><td align="right">'."\n";
349: if ($numdisc > 0) {
350: $display.='<b>Export discussion posts?</b>'."\n";
351: }
352: $display.=' </td></tr>';
353: while ($curRes = $it->next()) {
354: if (ref($curRes)) {
355: $count ++;
356: }
357: if ($curRes == $it->BEGIN_MAP()) {
358: $depth++;
359: $parent{$depth} = $lastcontainer;
360: }
361: if ($curRes == $it->END_MAP()) {
362: $depth--;
363: $lastcontainer = $parent{$depth};
364: }
365: if (ref($curRes)) {
366: my $symb = $curRes->symb();
1.158 raeburn 367: my $ressymb = $symb;
1.264 albertel 368: if ($ressymb =~ m|adm/($match_domain)/($match_username)/(\d+)/bulletinboard$|) {
1.158 raeburn 369: unless ($ressymb =~ m|adm/wrapper/adm|) {
370: $ressymb = 'bulletin___'.$3.'___adm/wrapper/adm/'.$1.'/'.$2.'/'.$3.'/bulletinboard';
371: }
372: }
1.138 raeburn 373: my $color = $count%2;
374: $display .='<tr bgcolor='.$bgcolors[$color].'><td>'."\n".
375: '<input type="checkbox" name="archive" value="'.$count.'" ';
376: if (($curRes->is_sequence()) || ($curRes->is_page())) {
377: my $checkitem = $count + $boards + $startcount;
378: $display .= 'onClick="javascript:propagateCheck('."'$checkitem'".')"';
379: }
380: $display .= ' />'."\n";
381: for (my $i=0; $i<$depth; $i++) {
1.282 ! albertel 382: $display .= '<img src="/adm/lonIcons/whitespace1.gif" class="LC_docs_spacer" /><img src="/adm/lonIcons/whitespace1.gif" class="LC_docs_spacer" />'."\n";
1.138 raeburn 383: }
384: if ($curRes->is_sequence()) {
385: $display .= '<img src="/adm/lonIcons/navmap.folder.open.gif"> '."\n";
386: $lastcontainer = $count + $startcount + $boards;
387: } elsif ($curRes->is_page()) {
388: $display .= '<img src="/adm/lonIcons/navmap.page.open.gif"> '."\n";
389: $lastcontainer = $count + $startcount + $boards;
390: }
391: my $currelem = $count+$boards+$startcount;
392: $children{$parent{$depth}} .= $currelem.':';
393: $display .= ' '.$curRes->title().'</td>';
1.158 raeburn 394: if ($discussiontime{$ressymb} > 0) {
1.138 raeburn 395: $boards ++;
396: $currelem = $count+$boards+$startcount;
397: $display .= '<td> </td><td align="right"><input type="checkbox" name="discussion" value="'.$count.'" /> </td>'."\n";
398: } else {
399: $display .= '<td colspan="2"> </td>'."\n";
400: }
401: }
402: }
403: my $scripttag = qq|
404: <script>
405:
406: function checkAll(field) {
1.158 raeburn 407: if (field.length > 0) {
408: for (i = 0; i < field.length; i++) {
409: field[i].checked = true ;
410: }
411: } else {
412: field.checked = true
413: }
1.138 raeburn 414: }
1.158 raeburn 415:
1.138 raeburn 416: function uncheckAll(field) {
1.158 raeburn 417: if (field.length > 0) {
418: for (i = 0; i < field.length; i++) {
419: field[i].checked = false ;
420: }
421: } else {
422: field.checked = false ;
423: }
1.138 raeburn 424: }
425:
426: function propagateCheck(item) {
427: if (document.exportdoc.elements[item].checked == true) {
428: containerCheck(item)
429: }
430: }
431:
432: function containerCheck(item) {
433: document.exportdoc.elements[item].checked = true
434: var numitems = $count + $boards + $startcount
435: var parents = new Array(numitems)
436: for (var i=$startcount; i<numitems; i++) {
437: parents[i] = new Array
438: }
439: |;
440:
441: foreach my $container (sort { $a <=> $b } keys %children) {
442: my @contents = split/:/,$children{$container};
443: for (my $i=0; $i<@contents; $i ++) {
444: $scripttag .= ' parents['.$container.']['.$i.'] = '.$contents[$i]."\n";
445: }
446: }
447:
448: $scripttag .= qq|
449: if (parents[item].length > 0) {
450: for (var j=0; j<parents[item].length; j++) {
451: containerCheck(parents[item][j])
452: }
453: }
454: }
455:
456: </script>
457: |;
1.229 raeburn 458: $r->print(&Apache::loncommon::start_page('Export '.lc($type).' to IMS content package',
1.224 albertel 459: $scripttag));
1.257 www 460: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Export '.lc($type).' to IMS content package'));
1.224 albertel 461: $r->print($display.'</table>'.
1.138 raeburn 462: '<p><input type="hidden" name="finishexport" value="1">'.
463: '<input type="submit" name="exportcourse" value="'.
1.230 albertel 464: &mt('Export '.$type.' DOCS').'" /></p></form>'.
1.224 albertel 465: &Apache::loncommon::end_page());
1.138 raeburn 466: }
467: }
468:
1.143 raeburn 469: sub create_ims_store {
470: my ($now,$manifestok,$outcome,$tempexport) = @_;
471: $$tempexport = $Apache::lonnet::perlvar{'lonDaemons'}.'/tmp/ims_exports';
472: my $ims_manifest;
473: if (!-e $$tempexport) {
474: mkdir($$tempexport,0700);
475: }
476: $$tempexport .= '/'.$now;
477: if (!-e $$tempexport) {
478: mkdir($$tempexport,0700);
479: }
1.174 albertel 480: $$tempexport .= '/'.$env{'user.domain'}.'_'.$env{'user.name'};
1.143 raeburn 481: if (!-e $$tempexport) {
482: mkdir($$tempexport,0700);
483: }
1.159 raeburn 484: if (!-e "$$tempexport/resources") {
485: mkdir("$$tempexport/resources",0700);
486: }
1.143 raeburn 487: # open manifest file
488: my $manifest = '/imsmanifest.xml';
489: my $manifestfilename = $$tempexport.$manifest;
490: if ($ims_manifest = Apache::File->new('>'.$manifestfilename)) {
491: $$manifestok=1;
492: print $ims_manifest
493: '<?xml version="1.0" encoding="UTF-8"?>'."\n".
494: '<manifest xmlns="http://www.imsglobal.org/xsd/imscp_v1p1"'.
495: ' xmlns:imsmd="http://www.imsglobal.org/xsd/imsmd_v1p2"'.
496: ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'.
1.174 albertel 497: ' identifier="MANIFEST-'.$env{'request.course.id'}.'-'.$now.'"'.
1.143 raeburn 498: ' xsi:schemaLocation="http://www.imsglobal.org/xsd/imscp_v1p1imscp_v1p1.xsd'.
499: ' http://www.imsglobal.org/xsd/imsmd_v1p2 imsmd_v1p2p2.xsd">'."\n".
1.199 raeburn 500: ' <metadata>
501: <schema></schema>
502: <imsmd:lom>
503: <imsmd:general>
504: <imsmd:identifier>'.$env{'request.course.id'}.'</imsmd:identifier>
505: <imsmd:title>
506: <imsmd:langstring xml:lang="en">'.$env{'course.'.$env{'request.course.id'}.'.description'}.'</imsmd:langstring>
507: </imsmd:title>
508: </imsmd:general>
509: </imsmd:lom>
510: </metadata>'."\n".
1.174 albertel 511: ' <organizations default="ORG-'.$env{'request.course.id'}.'-'.$now.'">'."\n".
512: ' <organization identifier="ORG-'.$env{'request.course.id'}.'-'.$now.'"'.
1.143 raeburn 513: ' structure="hierarchical">'."\n".
1.199 raeburn 514: ' <title>'.$env{'course.'.$env{'request.course.id'}.'.description'}.'</title>'
1.143 raeburn 515: } else {
516: $$outcome .= 'An error occurred opening the IMS manifest file.<br />'
517: ;
518: }
519: return $ims_manifest;
520: }
521:
522: sub build_package {
523: my ($now,$navmap,$exportitems,$discussions,$outcome,$tempexport,$copyresult,$ims_manifest) = @_;
524: # first iterator to look for dependencies
525: my $it = $navmap->getIterator(undef,undef,undef,1,undef,undef);
526: my $curRes;
527: my $count = 0;
528: my $depth = 0;
529: my $lastcontainer = 0;
530: my %parent = ();
531: my @dependencies = ();
1.174 albertel 532: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
533: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1.143 raeburn 534: while ($curRes = $it->next()) {
535: if (ref($curRes)) {
536: $count ++;
537: }
538: if ($curRes == $it->BEGIN_MAP()) {
539: $depth++;
540: $parent{$depth} = $lastcontainer;
541: }
542: if ($curRes == $it->END_MAP()) {
543: $depth--;
544: $lastcontainer = $parent{$depth};
545: }
546: if (ref($curRes)) {
547: if ($curRes->is_sequence() || $curRes->is_page()) {
548: $lastcontainer = $count;
549: }
550: if (grep/^$count$/,@$exportitems) {
551: &get_dependencies($exportitems,\%parent,$depth,\@dependencies);
552: }
553: }
554: }
555: # second iterator to build manifest and store resources
556: $it = $navmap->getIterator(undef,undef,undef,1,undef,undef);
557: $depth = 0;
558: my $prevdepth;
559: $count = 0;
560: my $imsresources;
561: my $pkgdepth;
1.157 raeburn 562: while ($curRes = $it->next()) {
563: if ($curRes == $it->BEGIN_MAP()) {
564: $prevdepth = $depth;
565: $depth++;
566: }
567: if ($curRes == $it->END_MAP()) {
1.143 raeburn 568: $prevdepth = $depth;
1.157 raeburn 569: $depth--;
570: }
571:
572: if (ref($curRes)) {
573: $count ++;
574: if ((grep/^$count$/,@$exportitems) || (grep/^$count$/,@dependencies)) {
575: my $symb = $curRes->symb();
576: my $isvisible = 'true';
577: my $resourceref;
578: if ($curRes->randomout()) {
579: $isvisible = 'false';
580: }
581: unless ($curRes->is_sequence()) {
1.174 albertel 582: $resourceref = 'identifierref="RES-'.$env{'request.course.id'}.'-'.$count.'"';
1.157 raeburn 583: }
1.199 raeburn 584: my $step = $prevdepth - $depth;
585: if (($step >= 0) && ($count > 1)) {
586: while ($step >= 0) {
587: print $ims_manifest "\n".' </item>'."\n";
588: $step --;
589: }
1.157 raeburn 590: }
591: $prevdepth = $depth;
1.143 raeburn 592:
1.157 raeburn 593: my $itementry =
1.174 albertel 594: '<item identifier="ITEM-'.$env{'request.course.id'}.'-'.$count.
1.143 raeburn 595: '" isvisible="'.$isvisible.'" '.$resourceref.'>'.
596: '<title>'.$curRes->title().'</title>';
1.157 raeburn 597: print $ims_manifest "\n".$itementry;
1.143 raeburn 598:
1.157 raeburn 599: unless ($curRes->is_sequence()) {
600: my $content_file;
601: my @hrefs = ();
602: &process_content($count,$curRes,$cdom,$cnum,$symb,\$content_file,\@hrefs,$copyresult,$tempexport);
603: if ($content_file) {
604: $imsresources .= "\n".
1.174 albertel 605: ' <resource identifier="RES-'.$env{'request.course.id'}.'-'.$count.
1.143 raeburn 606: '" type="webcontent" href="'.$content_file.'">'."\n".
607: ' <file href="'.$content_file.'" />'."\n";
1.157 raeburn 608: foreach (@hrefs) {
609: $imsresources .=
1.143 raeburn 610: ' <file href="'.$_.'" />'."\n";
1.157 raeburn 611: }
1.158 raeburn 612: if (grep/^$count$/,@$discussions) {
613: my $ressymb = $symb;
614: my $mode;
1.264 albertel 615: if ($ressymb =~ m|adm/($match_domain)/($match_username)/(\d+)/bulletinboard$|) {
1.158 raeburn 616: unless ($ressymb =~ m|adm/wrapper/adm|) {
617: $ressymb = 'bulletin___'.$3.'___adm/wrapper/adm/'.$1.'/'.$2.'/'.$3.'/bulletinboard';
618: }
619: $mode = 'board';
620: }
621: my %extras = (
622: caller => 'imsexport',
1.159 raeburn 623: tempexport => $tempexport.'/resources',
1.158 raeburn 624: count => $count
625: );
626: my $discresult = &Apache::lonfeedback::list_discussion($mode,undef,$ressymb,\%extras);
627: }
1.157 raeburn 628: $imsresources .= ' </resource>'."\n";
1.143 raeburn 629: }
630: }
1.157 raeburn 631: $pkgdepth = $depth;
1.143 raeburn 632: }
633: }
634: }
1.157 raeburn 635: while ($pkgdepth > 0) {
1.143 raeburn 636: print $ims_manifest " </item>\n";
637: $pkgdepth --;
638: }
639: my $resource_text = qq|
640: </organization>
641: </organizations>
642: <resources>
643: $imsresources
644: </resources>
645: </manifest>
646: |;
647: print $ims_manifest $resource_text;
648: }
649:
650: sub get_dependencies {
651: my ($exportitems,$parent,$depth,$dependencies) = @_;
652: if ($depth > 1) {
1.157 raeburn 653: if ((!grep/^$$parent{$depth}$/,@$exportitems) && (!grep/^$$parent{$depth}$/,@$dependencies)) {
1.143 raeburn 654: push @$dependencies, $$parent{$depth};
655: if ($depth > 2) {
656: &get_dependencies($exportitems,$parent,$depth-1,$dependencies);
657: }
658: }
659: }
660: }
661:
662: sub process_content {
663: my ($count,$curRes,$cdom,$cnum,$symb,$content_file,$href,$copyresult,$tempexport) = @_;
664: my $content_type;
665: my $message;
1.158 raeburn 666: my @uploads = ();
1.157 raeburn 667: if ($curRes->is_sequence()) {
668: $content_type = 'sequence';
669: } elsif ($curRes->is_page()) {
670: $content_type = 'page'; # need to handle individual items in pages.
1.143 raeburn 671: } elsif ($symb =~ m-public/$cdom/$cnum/syllabus$-) {
672: $content_type = 'syllabus';
1.158 raeburn 673: my $contents = &Apache::imsexport::templatedpage($content_type);
674: if ($contents) {
675: $$content_file = &store_template($contents,$tempexport,$count,$content_type);
676: }
1.157 raeburn 677: } elsif ($symb =~ m-\.sequence___\d+___ext-) {
1.143 raeburn 678: $content_type = 'external';
1.158 raeburn 679: my $title = $curRes->title;
680: my $contents = &Apache::imsexport::external($symb,$title);
681: if ($contents) {
682: $$content_file = &store_template($contents,$tempexport,$count,$content_type);
683: }
1.143 raeburn 684: } elsif ($symb =~ m-adm/navmaps$-) {
685: $content_type = 'navmap';
1.158 raeburn 686: } elsif ($symb =~ m-adm/[^/]+/[^/]+/(\d+)/smppg$-) {
1.143 raeburn 687: $content_type = 'simplepage';
1.158 raeburn 688: my $contents = &Apache::imsexport::templatedpage($content_type,$1,$count,\@uploads);
689: if ($contents) {
690: $$content_file = &store_template($contents,$tempexport,$count,$content_type);
691: }
692: } elsif ($symb =~ m-lib/templates/simpleproblem\.problem$-) {
1.143 raeburn 693: $content_type = 'simpleproblem';
1.158 raeburn 694: my $contents = &Apache::imsexport::simpleproblem($symb);
695: if ($contents) {
696: $$content_file = &store_template($contents,$tempexport,$count,$content_type);
697: }
1.188 raeburn 698: } elsif ($symb =~ m-lib/templates/examupload\.problem$-) {
1.158 raeburn 699: $content_type = 'examupload';
1.264 albertel 700: } elsif ($symb =~ m-adm/($match_domain)/($match_username)/(\d+)/bulletinboard$-) {
1.143 raeburn 701: $content_type = 'bulletinboard';
1.158 raeburn 702: my $contents = &Apache::imsexport::templatedpage($content_type,$3,$count,\@uploads,$1,$2);
703: if ($contents) {
704: $$content_file = &store_template($contents,$tempexport,$count,$content_type);
705: }
706: } elsif ($symb =~ m-adm/([^/]+)/([^/]+)/aboutme$-) {
1.143 raeburn 707: $content_type = 'aboutme';
1.158 raeburn 708: my $contents = &Apache::imsexport::templatedpage($content_type,undef,$count,\@uploads,$1,$2);
709: if ($contents) {
710: $$content_file = &store_template($contents,$tempexport,$count,$content_type);
711: }
1.157 raeburn 712: } elsif ($symb =~ m-\.(sequence|page)___\d+___uploaded/$cdom/$cnum/-) {
713: $$content_file = &replicate_content($cdom,$cnum,$tempexport,$symb,$count,\$message,$href,'uploaded');
1.162 raeburn 714: } elsif ($symb =~ m-\.(sequence|page)___\d+___([^/]+)/([^/]+)-) {
1.143 raeburn 715: my $canedit = 0;
1.174 albertel 716: if ($2 eq $env{'user.domain'} && $3 eq $env{'user.name'}) {
1.143 raeburn 717: $canedit= 1;
718: }
1.200 raeburn 719: # only include problem code where current user is author
1.143 raeburn 720: if ($canedit) {
1.157 raeburn 721: $$content_file = &replicate_content($cdom,$cnum,$tempexport,$symb,$count,\$message,$href,'resource');
1.143 raeburn 722: } else {
1.157 raeburn 723: $$content_file = &replicate_content($cdom,$cnum,$tempexport,$symb,$count,\$message,$href,'noedit');
1.143 raeburn 724: }
1.162 raeburn 725: } elsif ($symb =~ m-uploaded/$cdom/$cnum-) {
726: $$content_file = &replicate_content($cdom,$cnum,$tempexport,$symb,$count,\$message,$href,'uploaded');
1.143 raeburn 727: }
1.158 raeburn 728: if (@uploads > 0) {
729: foreach my $item (@uploads) {
730: my $uploadmsg = '';
1.159 raeburn 731: &replicate_content($cdom,$cnum,$tempexport,$item,$count,\$uploadmsg,$href,'templateupload');
1.158 raeburn 732: if ($uploadmsg) {
733: $$copyresult .= $uploadmsg."\n";
734: }
735: }
736: }
1.157 raeburn 737: if ($message) {
738: $$copyresult .= $message."\n";
739: }
1.143 raeburn 740: }
741:
742: sub replicate_content {
1.157 raeburn 743: my ($cdom,$cnum,$tempexport,$symb,$count,$message,$href,$caller) = @_;
1.159 raeburn 744: my ($map,$ind,$url);
745: if ($caller eq 'templateupload') {
746: $url = $symb;
747: $url =~ s#//#/#g;
748: } else {
749: ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);
750: }
1.143 raeburn 751: my $content;
752: my $filename;
753: my $repstatus;
1.157 raeburn 754: my $content_name;
755: if ($url =~ m-/([^/]+)$-) {
1.143 raeburn 756: $filename = $1;
757: if (!-e $tempexport.'/resources') {
758: mkdir($tempexport.'/resources',0700);
759: }
1.157 raeburn 760: if (!-e $tempexport.'/resources/'.$count) {
1.143 raeburn 761: mkdir($tempexport.'/resources/'.$count,0700);
762: }
1.157 raeburn 763: my $destination = $tempexport.'/resources/'.$count.'/'.$filename;
1.143 raeburn 764: my $copiedfile;
765: if ($copiedfile = Apache::File->new('>'.$destination)) {
766: my $content;
1.157 raeburn 767: if ($caller eq 'resource') {
1.197 raeburn 768: my $respath = $Apache::lonnet::perlvar{'lonDocRoot'}.'/res';
769: my $filepath = &Apache::lonnet::filelocation($respath,$url);
770: $content = &Apache::lonnet::getfile($filepath);
1.143 raeburn 771: if ($content eq -1) {
772: $$message = 'Could not copy file '.$filename;
773: } else {
1.197 raeburn 774: &extract_media($url,$cdom,$cnum,\$content,$count,$tempexport,$href,$message,'resource');
1.143 raeburn 775: $repstatus = 'ok';
776: }
1.162 raeburn 777: } elsif ($caller eq 'uploaded' || $caller eq 'templateupload') {
1.143 raeburn 778: my $rtncode;
1.157 raeburn 779: $repstatus = &Apache::lonnet::getuploaded('GET',$url,$cdom,$cnum,\$content,$rtncode);
780: if ($repstatus eq 'ok') {
781: if ($url =~ /\.html?$/i) {
1.197 raeburn 782: &extract_media($url,$cdom,$cnum,\$content,$count,$tempexport,$href,$message,'uploaded');
1.157 raeburn 783: }
784: } else {
1.197 raeburn 785: $$message = 'Could not render '.$url.' server message - '.$rtncode."<br />\n";
1.143 raeburn 786: }
1.162 raeburn 787: } elsif ($caller eq 'noedit') {
788: # Need to render the resource without the LON-CAPA Internal header and the Post discussion footer, and then set $content equal to this.
789: $repstatus = 'ok';
790: $content = 'Not the owner of this resource';
1.143 raeburn 791: }
792: if ($repstatus eq 'ok') {
793: print $copiedfile $content;
794: }
795: close($copiedfile);
796: } else {
1.197 raeburn 797: $$message = 'Could not open destination file for '.$filename."<br />\n";
1.143 raeburn 798: }
799: } else {
1.197 raeburn 800: $$message = 'Could not determine name of file for '.$symb."<br />\n";
1.143 raeburn 801: }
1.157 raeburn 802: if ($repstatus eq 'ok') {
1.198 raeburn 803: $content_name = 'resources/'.$count.'/'.$filename;
1.157 raeburn 804: }
805: return $content_name;
806: }
807:
808: sub extract_media {
1.197 raeburn 809: my ($url,$cdom,$cnum,$content,$count,$tempexport,$href,$message,$caller) = @_;
1.198 raeburn 810: my ($dirpath,$container);
1.197 raeburn 811: my %allfiles = ();
812: my %codebase = ();
1.198 raeburn 813: if ($url =~ m-(.*/)([^/]+)$-) {
814: $dirpath = $1;
815: $container = $2;
816: } else {
817: $dirpath = $url;
818: $container = '';
819: }
1.197 raeburn 820: &Apache::lonnet::extract_embedded_items(undef,undef,\%allfiles,\%codebase,$content);
821: foreach my $embed_file (keys(%allfiles)) {
822: my $filename;
823: if ($embed_file =~ m#([^/]+)$#) {
824: $filename = $1;
825: } else {
826: $filename = $embed_file;
827: }
828: my $newname = 'res/'.$filename;
829: my ($rtncode,$embed_content,$repstatus);
830: my $embed_url;
831: if ($embed_file =~ m-^/-) {
832: $embed_url = $embed_file; # points to absolute path
833: } else {
834: if ($embed_file =~ m-https?://-) {
835: next; # points to url
836: } else {
1.198 raeburn 837: $embed_url = $dirpath.$embed_file; # points to relative path
1.197 raeburn 838: }
839: }
840: if ($caller eq 'resource') {
841: my $respath = $Apache::lonnet::perlvar{'lonDocRoot'}.'/res';
842: my $embed_path = &Apache::lonnet::filelocation($respath,$embed_url);
843: $embed_content = &Apache::lonnet::getfile($embed_path);
844: unless ($embed_content eq -1) {
845: $repstatus = 'ok';
846: }
847: } elsif ($caller eq 'uploaded') {
848:
849: $repstatus = &Apache::lonnet::getuploaded('GET',$embed_url,$cdom,$cnum,\$embed_content,$rtncode);
850: }
851: if ($repstatus eq 'ok') {
852: my $destination = $tempexport.'/resources/'.$count.'/res';
853: if (!-e "$destination") {
854: mkdir($destination,0755);
855: }
856: $destination .= '/'.$filename;
857: my $copiedfile;
858: if ($copiedfile = Apache::File->new('>'.$destination)) {
859: print $copiedfile $embed_content;
1.198 raeburn 860: push @{$href}, 'resources/'.$count.'/res/'.$filename;
1.197 raeburn 861: my $attrib_regexp = '';
862: if (@{$allfiles{$embed_file}} > 1) {
863: $attrib_regexp = join('|',@{$allfiles{$embed_file}});
864: } else {
865: $attrib_regexp = $allfiles{$embed_file}[0];
866: }
867: $$content =~ s#($attrib_regexp\s*=\s*['"]?)\Q$embed_file\E(['"]?)#$1$newname$2#gi;
1.198 raeburn 868: if ($caller eq 'resource' && $container =~ /\.(problem|library)$/) {
1.197 raeburn 869: $$content =~ s#\Q$embed_file\E#$newname#gi;
870: }
871: }
872: } else {
873: $$message .= 'replication of embedded file - '.$embed_file.' in '.$url.' failed, reason -'.$rtncode."<br />\n";
874: }
875: }
1.157 raeburn 876: return;
1.143 raeburn 877: }
1.74 www 878:
1.158 raeburn 879: sub store_template {
880: my ($contents,$tempexport,$count,$content_type) = @_;
881: if ($contents) {
1.159 raeburn 882: if ($tempexport) {
883: if (!-e $tempexport.'/resources') {
884: mkdir($tempexport.'/resources',0700);
885: }
886: if (!-e $tempexport.'/resources/'.$count) {
887: mkdir($tempexport.'/resources/'.$count,0700);
888: }
889: my $destination = $tempexport.'/resources/'.$count.'/'.$content_type.'.xml';
890: my $storetemplate;
891: if ($storetemplate = Apache::File->new('>'.$destination)) {
892: print $storetemplate $contents;
893: close($storetemplate);
894: }
895: if ($content_type eq 'external') {
1.198 raeburn 896: return 'resources/'.$count.'/'.$content_type.'.html';
1.159 raeburn 897: } else {
1.198 raeburn 898: return 'resources/'.$count.'/'.$content_type.'.xml';
1.159 raeburn 899: }
1.158 raeburn 900: }
901: }
902: }
903:
1.73 bowersj2 904: # Imports the given (name, url) resources into the course
905: # coursenum, coursedom, and folder must precede the list
906: sub group_import {
1.277 albertel 907: my ($coursenum, $coursedom, $folder, $container, $caller, @files) = @_;
908:
909: while (@files) {
910: my $name = shift(@files);
911: my $url = shift(@files);
912: #FIXME check if file exists before overwriting, might be restoring it
913: if (($url =~ m{^/uploaded/\Q$coursedom\E/\Q$coursenum\E/(default_\d+\.)(page|sequence)$})
914: && ($caller eq 'londocs')
915: && (!&Apache::lonnet::stat_file($url))) {
916:
1.142 raeburn 917: my $errtext = '';
918: my $fatal = 0;
919: my $newmapstr = '<map>'."\n".
920: '<resource id="1" src="" type="start"></resource>'."\n".
921: '<link from="1" to="2" index="1"></link>'."\n".
922: '<resource id="2" src="" type="finish"></resource>'."\n".
923: '</map>';
1.174 albertel 924: $env{'form.output'}=$newmapstr;
1.189 albertel 925: my $result=&Apache::lonnet::finishuserfileupload($coursenum,$coursedom,
1.142 raeburn 926: 'output',$1.$2);
927: if ($result != m|^/uploaded/|) {
928: $errtext.='Map not saved: A network error occured when trying to save the new map. ';
929: $fatal = 2;
930: }
931: if ($fatal) {
932: return ($errtext,$fatal);
933: }
934: }
1.73 bowersj2 935: if ($url) {
1.245 albertel 936: my $idx = &LONCAPA::map::getresidx($url);
937: $LONCAPA::map::order[$#LONCAPA::map::order+1]=$idx;
1.73 bowersj2 938: my $ext = 'false';
1.263 albertel 939: if ($url=~m{^http://} || $url=~m{^https://}) { $ext = 'true'; }
1.273 albertel 940: $url = &LONCAPA::map::qtunescape($url);
941: $name = &LONCAPA::map::qtunescape($name);
1.245 albertel 942: $LONCAPA::map::resources[$idx] =
1.73 bowersj2 943: join ':', ($name, $url, $ext, 'normal', 'res');
944: }
945: }
1.142 raeburn 946: return &storemap($coursenum, $coursedom, $folder.'.'.$container);
1.73 bowersj2 947: }
948:
1.114 albertel 949: sub breadcrumbs {
950: my ($where)=@_;
951: &Apache::lonhtmlcommon::clear_breadcrumbs();
1.142 raeburn 952: my (@folders);
1.174 albertel 953: if ($env{'form.pagepath'}) {
954: @folders = split('&',$env{'form.pagepath'});
1.142 raeburn 955: } else {
1.174 albertel 956: @folders=split('&',$env{'form.folderpath'});
1.142 raeburn 957: }
1.116 albertel 958: my $folderpath;
1.168 www 959: my $cpinfo='';
1.251 www 960: my $plain='';
1.242 www 961: my $randompick=-1;
962: my $isencrypted=0;
963: my $ishidden=0;
1.116 albertel 964: while (@folders) {
965: my $folder=shift(@folders);
966: my $foldername=shift(@folders);
967: if ($folderpath) {$folderpath.='&';}
968: $folderpath.=$folder.'&'.$foldername;
969: my $url='/adm/coursedocs?folderpath='.
1.228 www 970: &escape($folderpath);
1.242 www 971: my $name=&unescape($foldername);
972: # randompick number, hidden, encrypted is appended with ":"s to the foldername
973: $name=~s/\:(\d*)\:(\w*)\:(\w*)$//;
974: if ($1 ne '') {
975: $randompick=$1;
976: } else {
977: $randompick=-1;
978: }
979: if ($2) { $ishidden=1; }
980: if ($3) { $isencrypted=1; }
1.114 albertel 981: &Apache::lonhtmlcommon::add_breadcrumb(
1.168 www 982: {'href'=>$url.$cpinfo,
1.242 www 983: 'title'=>$name,
1.117 albertel 984: 'text'=>'<font size="+1">'.
1.266 albertel 985: $name.'</font>',
986: 'no_mt'=>1,
1.117 albertel 987: });
1.251 www 988: $plain.=$name.' > ';
1.114 albertel 989: }
1.251 www 990: $plain=~s/\>\;\s*$//;
1.242 www 991: return (&Apache::lonhtmlcommon::breadcrumbs(undef,undef,0,'nohelp',
1.251 www 992: 'LC_docs_path'),$randompick,$ishidden,$isencrypted,$plain);
1.114 albertel 993: }
994:
1.247 www 995: sub log_docs {
996: return &Apache::lonnet::instructor_log('docslog',@_);
997: }
998:
999: {
1000: my @oldresources=();
1001: my @oldorder=();
1002: my $parmidx;
1003: my %parmaction=();
1004: my %parmvalue=();
1.249 www 1005: my $changedflag;
1.247 www 1006:
1007: sub snapshotbefore {
1.248 albertel 1008: @oldresources=@LONCAPA::map::resources;
1009: @oldorder=@LONCAPA::map::order;
1.247 www 1010: $parmidx=undef;
1011: %parmaction=();
1012: %parmvalue=();
1.249 www 1013: $changedflag=0;
1.247 www 1014: }
1015:
1016: sub remember_parms {
1017: my ($idx,$parameter,$action,$value)=@_;
1018: $parmidx=$idx;
1019: $parmaction{$parameter}=$action;
1020: $parmvalue{$parameter}=$value;
1.249 www 1021: $changedflag=1;
1.247 www 1022: }
1023:
1024: sub log_differences {
1.251 www 1025: my ($plain)=@_;
1.260 www 1026: my %storehash=('folder' => $plain,
1027: 'currentfolder' => $env{'form.folder'});
1.247 www 1028: if ($parmidx) {
1029: $storehash{'parameter_res'}=$oldresources[$parmidx];
1030: foreach my $parm (keys %parmaction) {
1031: $storehash{'parameter_action_'.$parm}=$parmaction{$parm};
1032: $storehash{'parameter_value_'.$parm}=$parmvalue{$parm};
1033: }
1034: }
1035: my $maxidx=$#oldresources;
1.248 albertel 1036: if ($#LONCAPA::map::resources>$#oldresources) {
1037: $maxidx=$#LONCAPA::map::resources;
1.247 www 1038: }
1039: for (my $idx=0; $idx<=$maxidx; $idx++) {
1040: if ($LONCAPA::map::resources[$idx] ne $oldresources[$idx]) {
1041: $storehash{'before_resources_'.$idx}=$oldresources[$idx];
1042: $storehash{'after_resources_'.$idx}=$LONCAPA::map::resources[$idx];
1.249 www 1043: $changedflag=1;
1.247 www 1044: }
1045: if ($LONCAPA::map::order[$idx] ne $oldorder[$idx]) {
1.252 www 1046: $storehash{'before_order_res_'.$idx}=$oldresources[$oldorder[$idx]];
1047: $storehash{'after_order_res_'.$idx}=$LONCAPA::map::resources[$LONCAPA::map::order[$idx]];
1.249 www 1048: $changedflag=1;
1.247 www 1049: }
1050: }
1.251 www 1051: $storehash{'maxidx'}=$maxidx;
1.249 www 1052: if ($changedflag) { &log_docs(\%storehash); }
1.247 www 1053: }
1054: }
1055:
1056:
1057: #
1058: # Docs Change Log
1059: #
1060: sub docs_change_log {
1061: my ($r)=@_;
1.260 www 1062: my $folder=$env{'form.folder'};
1.247 www 1063: $r->print(&Apache::loncommon::start_page('Course Document Change Log'));
1064: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Course Document Change Log'));
1065: my %docslog=&Apache::lonnet::dump('nohist_docslog',
1066: $env{'course.'.$env{'request.course.id'}.'.domain'},
1067: $env{'course.'.$env{'request.course.id'}.'.num'});
1.254 albertel 1068:
1.247 www 1069: if ((keys(%docslog))[0]=~/^error\:/) { undef(%docslog); }
1.254 albertel 1070:
1.247 www 1071: $r->print('<form action="/adm/coursedocs" method="post" name="docslog">'.
1072: '<input type="hidden" name="docslog" value="1" />');
1.254 albertel 1073:
1.247 www 1074: my %saveable_parameters = ('show' => 'scalar',);
1075: &Apache::loncommon::store_course_settings('docs_log',
1076: \%saveable_parameters);
1077: &Apache::loncommon::restore_course_settings('docs_log',
1078: \%saveable_parameters);
1079: if (!$env{'form.show'}) { $env{'form.show'}=10; }
1.254 albertel 1080: my %lt=('hiddenresource' => 'Resources hidden',
1081: 'encrypturl' => 'URL hidden',
1082: 'randompick' => 'Randomly pick',
1083: 'set' => 'set to',
1084: 'del' => 'deleted');
1.259 www 1085: $r->print(&Apache::loncommon::display_filter().
1.260 www 1086: '<input type="hidden" name="folder" value="'.$folder.'" />'.
1.247 www 1087: '<input type="submit" value="'.&mt('Display').'" /></form>');
1088: $r->print(&Apache::loncommon::start_data_table().&Apache::loncommon::start_data_table_header_row().
1.251 www 1089: '<th>'.&mt('Time').'</th><th>'.&mt('User').'</th><th>'.&mt('Folder').'</th><th>'.&mt('Before').'</th><th>'.
1090: &mt('After').'</th>'.
1.247 www 1091: &Apache::loncommon::end_data_table_header_row());
1092: my $shown=0;
1093: foreach my $id (sort { $docslog{$b}{'exe_time'}<=>$docslog{$a}{'exe_time'} } (keys(%docslog))) {
1.260 www 1094: if ($env{'form.displayfilter'} eq 'currentfolder') {
1095: if ($docslog{$id}{'logentry'}{'currentfolder'} ne $folder) { next; }
1096: }
1.247 www 1097: my @changes=keys(%{$docslog{$id}{'logentry'}});
1.261 www 1098: if ($env{'form.displayfilter'} eq 'containing') {
1099: my $wholeentry=$docslog{$id}{'exe_uname'}.':'.$docslog{$id}{'exe_udom'}.':'.
1100: &Apache::loncommon::plainname($docslog{$id}{'exe_uname'},$docslog{$id}{'exe_udom'});
1101: foreach my $key (@changes) {
1102: $wholeentry.=':'.$docslog{$id}{'logentry'}{$key};
1103: }
1104: if ($wholeentry!~/\Q$env{'form.containingphrase'}\E/i) { next; }
1105: }
1.247 www 1106: my $count = 0;
1107: my $time =
1108: &Apache::lonlocal::locallocaltime($docslog{$id}{'exe_time'});
1109: my $plainname =
1110: &Apache::loncommon::plainname($docslog{$id}{'exe_uname'},
1111: $docslog{$id}{'exe_udom'});
1112: my $about_me_link =
1113: &Apache::loncommon::aboutmewrapper($plainname,
1114: $docslog{$id}{'exe_uname'},
1115: $docslog{$id}{'exe_udom'});
1116: my $send_msg_link='';
1117: if ((($docslog{$id}{'exe_uname'} ne $env{'user.name'})
1118: || ($docslog{$id}{'exe_udom'} ne $env{'user.domain'}))) {
1119: $send_msg_link ='<br />'.
1120: &Apache::loncommon::messagewrapper(&mt('Send message'),
1121: $docslog{$id}{'exe_uname'},
1122: $docslog{$id}{'exe_udom'});
1123: }
1124: $r->print(&Apache::loncommon::start_data_table_row());
1125: $r->print('<td>'.$time.'</td>
1126: <td>'.$about_me_link.
1127: '<br /><tt>'.$docslog{$id}{'exe_uname'}.
1128: ':'.$docslog{$id}{'exe_udom'}.'</tt>'.
1.249 www 1129: $send_msg_link.'</td><td>'.
1.251 www 1130: $docslog{$id}{'logentry'}{'folder'}.'</td><td>');
1131: # Before
1132: for (my $idx=0;$idx<=$docslog{$id}{'logentry'}{'maxidx'};$idx++) {
1133: my $oldname=(split(/\:/,$docslog{$id}{'logentry'}{'before_resources_'.$idx}))[0];
1134: my $newname=(split(/\:/,$docslog{$id}{'logentry'}{'after_resources_'.$idx}))[0];
1135: if ($oldname ne $newname) {
1.252 www 1136: $r->print(&LONCAPA::map::qtescape($oldname));
1.251 www 1137: }
1138: }
1.252 www 1139: $r->print('<ul>');
1140: for (my $idx=0;$idx<=$docslog{$id}{'logentry'}{'maxidx'};$idx++) {
1141: if ($docslog{$id}{'logentry'}{'before_order_res_'.$idx}) {
1142: $r->print('<li>'.&LONCAPA::map::qtescape((split(/\:/,$docslog{$id}{'logentry'}{'before_order_res_'.$idx}))[0]).'</li>');
1143: }
1144: }
1145: $r->print('</ul>');
1.251 www 1146: # After
1147: $r->print('</td><td>');
1148:
1149: for (my $idx=0;$idx<=$docslog{$id}{'logentry'}{'maxidx'};$idx++) {
1150: my $oldname=(split(/\:/,$docslog{$id}{'logentry'}{'before_resources_'.$idx}))[0];
1151: my $newname=(split(/\:/,$docslog{$id}{'logentry'}{'after_resources_'.$idx}))[0];
1.279 albertel 1152: if ($oldname ne '' && $oldname ne $newname) {
1.252 www 1153: $r->print(&LONCAPA::map::qtescape($newname));
1.251 www 1154: }
1155: }
1.252 www 1156: $r->print('<ul>');
1157: for (my $idx=0;$idx<=$docslog{$id}{'logentry'}{'maxidx'};$idx++) {
1158: if ($docslog{$id}{'logentry'}{'after_order_res_'.$idx}) {
1159: $r->print('<li>'.&LONCAPA::map::qtescape((split(/\:/,$docslog{$id}{'logentry'}{'after_order_res_'.$idx}))[0]).'</li>');
1160: }
1161: }
1162: $r->print('</ul>');
1163: if ($docslog{$id}{'logentry'}{'parameter_res'}) {
1164: $r->print(&LONCAPA::map::qtescape((split(/\:/,$docslog{$id}{'logentry'}{'parameter_res'}))[0]).':<ul>');
1.253 www 1165: foreach my $parameter ('randompick','hiddenresource','encrypturl') {
1.252 www 1166: if ($docslog{$id}{'logentry'}{'parameter_action_'.$parameter}) {
1.254 albertel 1167: $r->print('<li>'.
1168: &mt($lt{$parameter}.' '.$lt{$docslog{$id}{'logentry'}{'parameter_action_'.$parameter}}.' [_1]',
1169: $docslog{$id}{'logentry'}{'parameter_value_'.$parameter})
1170: .'</li>');
1.252 www 1171: }
1172: }
1173: $r->print('</ul>');
1174: }
1.251 www 1175: # End
1176: $r->print('</td>'.&Apache::loncommon::end_data_table_row());
1.247 www 1177: $shown++;
1178: if (!($env{'form.show'} eq &mt('all')
1179: || $shown<=$env{'form.show'})) { last; }
1180: }
1181: $r->print(&Apache::loncommon::end_data_table());
1182: }
1183:
1.281 albertel 1184: sub update_paste_buffer {
1185: my ($coursenum,$coursedom) = @_;
1186:
1187: return if (!defined($env{'form.markcopy'}));
1188: return if (!defined($env{'form.copyfolder'}));
1189: return if ($env{'form.markcopy'} < 0);
1190:
1191: my ($errtext,$fatal) = &mapread($coursenum,$coursedom,
1192: $env{'form.copyfolder'});
1193:
1194: return if ($fatal);
1195:
1196: # Mark for copying
1197: my ($title,$url)=split(':',$LONCAPA::map::resources[$LONCAPA::map::order[$env{'form.markcopy'}]]);
1198: if (&is_supplemental_title($title)) {
1199: ($title) = &parse_supplemental_title($title);
1200: }
1201: &Apache::lonnet::appenv('docs.markedcopy_title' => $title,
1202: 'docs.markedcopy_url' => $url);
1203: delete($env{'form.markcopy'});
1204: }
1205:
1206: sub print_paste_buffer {
1207: my ($r,$container) = @_;
1208: return if (!defined($env{'docs.markedcopy_url'}));
1209:
1210: $r->print(<<ENDPASTE);
1211: <p><form name="pasteform" action="/adm/coursedocs" method="post">
1212: ENDPASTE
1213: $r->print('<input type="submit" name="pastemarked" value="'.&mt('Paste').'" /> ');
1214:
1215: my $type;
1216: if ($env{'docs.markedcopy_url'} =~ m{^/adm/wrapper/ext}) {
1217: $type = &mt('External Resource');
1218: $r->print($type.': '.&Apache::map::qtescape($env{'docs.markedcopy_title'}));
1219: } else {
1220: my $extension = (split(/\./,$env{'docs.markedcopy_url'}))[-1];
1221: my $type = &Apache::loncommon::filedescription($extension);
1222: my $icon = '<img src="'.&Apache::loncommon::icon($extension).
1223: '" class="LC_icon" />';
1224: $r->print($icon.$type.': '. &parse_supplemental_title($env{'docs.markedcopy_title'}));
1225: }
1226: if ($container eq 'page') {
1227: $r->print(<<PAGEINFO);
1228: <input type="hidden" name="pagepath" value="$env{'form.pagepath'}" />
1229: <input type="hidden" name="pagesymb" value="$env{'form.pagesymb'}" />
1230: PAGEINFO
1231: } else {
1232: $r->print(<<FOLDERINFO);
1233: <input type="hidden" name="folderpath" value="$env{'form.folderpath'}" />
1234: FOLDERINFO
1235: }
1236: $r->print('</form></p>');
1237: }
1238:
1.7 www 1239: sub editor {
1.281 albertel 1240: my ($r,$coursenum,$coursedom,$folder,$allowed,$upload_output,$which)=@_;
1.10 www 1241: my $errtext='';
1242: my $fatal=0;
1.142 raeburn 1243: my $container='sequence';
1.174 albertel 1244: if ($env{'form.pagepath'}) {
1.142 raeburn 1245: $container='page';
1246: }
1.281 albertel 1247: ($errtext,$fatal) = &mapread($coursenum,$coursedom,$folder.'.'.$container);
1.245 albertel 1248: if ($#LONCAPA::map::order<1) {
1249: my $idx=&LONCAPA::map::getresidx();
1.178 www 1250: if ($idx<=0) { $idx=1; }
1.245 albertel 1251: $LONCAPA::map::order[0]=$idx;
1252: $LONCAPA::map::resources[$idx]='';
1.17 www 1253: }
1.281 albertel 1254:
1.251 www 1255: my ($breadcrumbtrail,$randompick,$ishidden,$isencrypted,$plain)=&breadcrumbs($folder);
1.242 www 1256: $r->print($breadcrumbtrail);
1.7 www 1257: if ($fatal) {
1258: $r->print('<p><font color="red">'.$errtext.'</font></p>');
1259: } else {
1260: # ------------------------------------------------------------ Process commands
1.121 www 1261:
1.16 www 1262: # ---------------- if they are for this folder and user allowed to make changes
1.174 albertel 1263: if (($allowed) && ($env{'form.folder'} eq $folder)) {
1.123 www 1264: # set parameters and change order
1.247 www 1265: &snapshotbefore();
1266: if ($env{'form.changeparms'}) {
1.174 albertel 1267: my $idx=$env{'form.setparms'};
1.123 www 1268: # set parameters
1.258 www 1269: if ($env{'form.changeparms'} eq 'randompick') {
1270: if ($env{'form.randpick_'.$idx}) {
1271: &LONCAPA::map::storeparameter($idx,'parameter_randompick',$env{'form.randpick_'.$idx},'int_pos');
1272: &remember_parms($idx,'randompick','set',$env{'form.randpick_'.$idx});
1273: } else {
1274: &LONCAPA::map::delparameter($idx,'parameter_randompick');
1275: &remember_parms($idx,'randompick','del');
1276: }
1277: }
1278: if ($env{'form.changeparms'} eq 'hiddenresource') {
1279: if ($env{'form.hidprs_'.$idx}) {
1280: &LONCAPA::map::storeparameter($idx,'parameter_hiddenresource','yes','string_yesno');
1281: &remember_parms($idx,'hiddenresource','set',$env{'form.hidprs_'.$idx});
1282: } else {
1283: &LONCAPA::map::delparameter($idx,'parameter_hiddenresource');
1284: &remember_parms($idx,'hiddenresource','del');
1285: }
1286: }
1287: if ($env{'form.changeparms'} eq 'encrypturl') {
1288: if ($env{'form.encprs_'.$idx}) {
1289: &LONCAPA::map::storeparameter($idx,'parameter_encrypturl','yes','string_yesno');
1290: &remember_parms($idx,'encrypturl','set',$env{'form.encprs_'.$idx});
1291: } else {
1292: &LONCAPA::map::delparameter($idx,'parameter_encrypturl');
1293: &remember_parms($idx,'encrypturl','del');
1294: }
1.121 www 1295: }
1.250 www 1296: # store the changed version
1297: ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container);
1298: if ($fatal) {
1299: $r->print('<p><font color="red">'.$errtext.'</font></p>');
1300: return;
1301: }
1.247 www 1302: }
1.121 www 1303:
1.247 www 1304: if ($env{'form.newpos'}) {
1.123 www 1305: # change order
1.247 www 1306: my $newpos=$env{'form.newpos'}-1;
1307: my $currentpos=$env{'form.currentpos'}-1;
1308: my $i;
1309: my @neworder=();
1310: if ($newpos>$currentpos) {
1.125 www 1311: # moving stuff up
1.247 www 1312: for ($i=0;$i<$currentpos;$i++) {
1313: $neworder[$i]=$LONCAPA::map::order[$i];
1314: }
1315: for ($i=$currentpos;$i<$newpos;$i++) {
1316: $neworder[$i]=$LONCAPA::map::order[$i+1];
1317: }
1318: $neworder[$newpos]=$LONCAPA::map::order[$currentpos];
1319: for ($i=$newpos+1;$i<=$#LONCAPA::map::order;$i++) {
1320: $neworder[$i]=$LONCAPA::map::order[$i];
1321: }
1322: } else {
1.125 www 1323: # moving stuff down
1.247 www 1324: for ($i=0;$i<$newpos;$i++) {
1325: $neworder[$i]=$LONCAPA::map::order[$i];
1326: }
1327: $neworder[$newpos]=$LONCAPA::map::order[$currentpos];
1328: for ($i=$newpos+1;$i<$currentpos+1;$i++) {
1329: $neworder[$i]=$LONCAPA::map::order[$i-1];
1330: }
1331: for ($i=$currentpos+1;$i<=$#LONCAPA::map::order;$i++) {
1332: $neworder[$i]=$LONCAPA::map::order[$i];
1.125 www 1333: }
1.124 www 1334: }
1.247 www 1335: @LONCAPA::map::order=@neworder;
1.124 www 1336: # store the changed version
1.142 raeburn 1337: ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container);
1.124 www 1338: if ($fatal) {
1339: $r->print('<p><font color="red">'.$errtext.'</font></p>');
1340: return;
1.123 www 1341: }
1.247 www 1342: }
1.281 albertel 1343:
1.174 albertel 1344: if ($env{'form.pastemarked'}) {
1.168 www 1345: # paste resource to end of list
1.281 albertel 1346: my $url=$env{'docs.markedcopy_url'};
1347: my $title=$env{'docs.markedcopy_title'};
1.168 www 1348: # Maps need to be copied first
1349: if (($url=~/\.(page|sequence)$/) || ($url=~/^\/uploaded\//)) {
1350: $title=&mt('Copy of').' '.$title;
1351: my $newid=$$.time;
1352: $url=~/^(.+)\.(\w+)$/;
1353: my $newurl=$1.$newid.'.'.$2;
1354: my $storefn=$newurl;
1.264 albertel 1355: $storefn=~s{^/\w+/$match_domain/$match_username/}{};
1.244 albertel 1356: &Apache::lonclonecourse::writefile
1.174 albertel 1357: ($env{'request.course.id'},$storefn,
1.168 www 1358: &Apache::lonnet::getfile($url));
1359: $url=$newurl;
1360: }
1.270 albertel 1361: $title = &LONCAPA::map::qtunescape($title);
1.168 www 1362: my $ext='false';
1363: if ($url=~/^http\:\/\//) { $ext='true'; }
1.270 albertel 1364: $url = &LONCAPA::map::qtunescape($url);
1.168 www 1365: # Now insert the URL at the bottom
1.245 albertel 1366: my $newidx=&LONCAPA::map::getresidx($url);
1367: $LONCAPA::map::resources[$newidx]=
1.168 www 1368: $title.':'.$url.':'.$ext.':normal:res';
1.245 albertel 1369: $LONCAPA::map::order[1+$#LONCAPA::map::order]=$newidx;
1.168 www 1370: # Store the result
1371: ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container);
1372: if ($fatal) {
1373: $r->print('<p><font color="red">'.$errtext.'</font></p>');
1374: return;
1375: }
1.123 www 1376:
1.168 www 1377: }
1.188 raeburn 1378: $r->print($upload_output);
1.174 albertel 1379: if ($env{'form.cmd'}) {
1380: my ($cmd,$idx)=split(/\_/,$env{'form.cmd'});
1.10 www 1381: if ($cmd eq 'del') {
1.245 albertel 1382: my (undef,$url)=split(':',$LONCAPA::map::resources[$LONCAPA::map::order[$idx]]);
1.187 www 1383: if (($url=~m|/+uploaded/\Q$coursedom\E/\Q$coursenum\E/|) &&
1.206 albertel 1384: ($url!~/\.(page|sequence|problem|exam|quiz|assess|survey|form|library|task)$/)) {
1.187 www 1385: &Apache::lonnet::removeuploadedurl($url);
1386: } else {
1.245 albertel 1387: &LONCAPA::map::makezombie($LONCAPA::map::order[$idx]);
1.128 albertel 1388: }
1.245 albertel 1389: for (my $i=$idx;$i<$#LONCAPA::map::order;$i++) {
1390: $LONCAPA::map::order[$i] = $LONCAPA::map::order[$i+1];
1.10 www 1391: }
1.245 albertel 1392: $#LONCAPA::map::order--;
1.171 www 1393: } elsif ($cmd eq 'cut') {
1.245 albertel 1394: my (undef,$url)=split(':',$LONCAPA::map::resources[$LONCAPA::map::order[$idx]]);
1395: &LONCAPA::map::makezombie($LONCAPA::map::order[$idx]);
1396: for (my $i=$idx;$i<$#LONCAPA::map::order;$i++) {
1397: $LONCAPA::map::order[$i] = $LONCAPA::map::order[$i+1];
1.171 www 1398: }
1.245 albertel 1399: $#LONCAPA::map::order--;
1.10 www 1400: } elsif ($cmd eq 'up') {
1.245 albertel 1401: if (($idx) && (defined($LONCAPA::map::order[$idx-1]))) {
1402: my $i=$LONCAPA::map::order[$idx-1];
1403: $LONCAPA::map::order[$idx-1] = $LONCAPA::map::order[$idx];
1404: $LONCAPA::map::order[$idx] = $i;
1.38 www 1405: }
1.10 www 1406: } elsif ($cmd eq 'down') {
1.245 albertel 1407: if (defined($LONCAPA::map::order[$idx+1])) {
1408: my $i=$LONCAPA::map::order[$idx+1];
1409: $LONCAPA::map::order[$idx+1] = $LONCAPA::map::order[$idx];
1410: $LONCAPA::map::order[$idx] = $i;
1.38 www 1411: }
1.36 www 1412: } elsif ($cmd eq 'rename') {
1.245 albertel 1413: my $ratstr = $LONCAPA::map::resources[$LONCAPA::map::order[$idx]];
1.36 www 1414: my ($rtitle,@rrest)=split(/\:/,
1.245 albertel 1415: $LONCAPA::map::resources[$LONCAPA::map::order[$idx]]);
1.270 albertel 1416: my $comment=$env{'form.title'};
1417: $comment = &LONCAPA::map::qtunescape($comment);
1.144 albertel 1418: if ($comment=~/\S/) {
1.245 albertel 1419: $LONCAPA::map::resources[$LONCAPA::map::order[$idx]]=
1420: $comment.':'.join(':',@rrest);
1.144 albertel 1421: }
1.238 www 1422: # Devalidate title cache
1.270 albertel 1423: my $renamed_url=&LONCAPA::map::qtescape($rrest[0]);
1.240 www 1424: &Apache::lonnet::devalidate_title_cache($renamed_url);
1.10 www 1425: }
1426: # Store the changed version
1.104 albertel 1427: ($errtext,$fatal)=&storemap($coursenum,$coursedom,
1.142 raeburn 1428: $folder.'.'.$container);
1.104 albertel 1429: if ($fatal) {
1430: $r->print('<p><font color="red">'.$errtext.'</font></p>');
1431: return;
1432: }
1.8 www 1433: }
1.11 www 1434: # Group import/search
1.174 albertel 1435: if ($env{'form.importdetail'}) {
1.73 bowersj2 1436: my @imports;
1.243 www 1437: # &Apache::lonnet::logthis("imp detail ".$env{'form.importdetail'});
1.174 albertel 1438: foreach (split(/\&/,$env{'form.importdetail'})) {
1.73 bowersj2 1439: if (defined($_)) {
1440: my ($name,$url)=split(/\=/,$_);
1.228 www 1441: $name=&unescape($name);
1442: $url=&unescape($url);
1.73 bowersj2 1443: push @imports, $name, $url;
1444: }
1445: }
1.11 www 1446: # Store the changed version
1.249 www 1447: ($errtext,$fatal)=&group_import($coursenum, $coursedom, $folder,
1.142 raeburn 1448: $container,'londocs',@imports);
1.104 albertel 1449: if ($fatal) {
1450: $r->print('<p><font color="red">'.$errtext.'</font></p>');
1451: return;
1452: }
1.11 www 1453: }
1.53 www 1454: # Loading a complete map
1.223 www 1455: if ($env{'form.loadmap'}) {
1456: if ($env{'form.importmap'}=~/\w/) {
1457: foreach (&Apache::lonsequence::attemptread(&Apache::lonnet::filelocation('',$env{'form.importmap'}))) {
1458: my ($title,$url,$ext,$type)=split(/\:/,$_);
1.245 albertel 1459: my $idx=&LONCAPA::map::getresidx($url);
1460: $LONCAPA::map::resources[$idx]=$_;
1461: $LONCAPA::map::order[$#LONCAPA::map::order+1]=$idx;
1.223 www 1462: }
1.53 www 1463: # Store the changed version
1.223 www 1464: ($errtext,$fatal)=&storemap($coursenum,$coursedom,
1.142 raeburn 1465: $folder.'.'.$container);
1.223 www 1466: if ($fatal) {
1467: $r->print('<p><font color="red">'.$errtext.'</font></p>');
1468: return;
1469: }
1470: } else {
1471: $r->print('<p><font color="red">'.&mt('No map selected.').'</font></p>');
1472: }
1.53 www 1473: }
1.251 www 1474: &log_differences($plain);
1.281 albertel 1475: }
1.16 www 1476: # ---------------------------------------------------------------- End commands
1.7 www 1477: # ---------------------------------------------------------------- Print screen
1.10 www 1478: my $idx=0;
1.148 www 1479: my $shown=0;
1.242 www 1480: if (($ishidden) || ($isencrypted) || ($randompick>=0)) {
1481: $r->print('<p>'.&mt('Parameters').':<ul>'.
1482: ($randompick>=0?'<li>'.&mt('randomly pick [_1] resources',$randompick).'</li>':'').
1483: ($ishidden?'<li>'.&mt('contents hidden').'</li>':'').
1484: ($isencrypted?'<li>'.&mt('URLs hidden').'</li>':'').
1485: '</ul></p>');
1486: }
1487: if ($randompick>=0) {
1488: $r->print('<p>'.&mt('Caution: this folder is set to randomly pick a subset of resources. Adding or removing resources from this folder will change the set of resources that the students see, resulting in spurious or missing credit for completed problems, not limited to ones you modify. Do not modify the contents of this folder if it is in active student use.').'</p>');
1489: }
1.10 www 1490: $r->print('<table>');
1.278 albertel 1491: foreach my $res (@LONCAPA::map::order) {
1492: my ($name,$url)=split(/\:/,$LONCAPA::map::resources[$res]);
1.246 raeburn 1493: $name=&LONCAPA::map::qtescape($name);
1.271 albertel 1494: $url=&LONCAPA::map::qtescape($url);
1.10 www 1495: unless ($name) { $name=(split(/\//,$url))[-1]; }
1.148 www 1496: unless ($name) { $idx++; next; }
1.278 albertel 1497: $r->print(&entryline($idx,$name,$url,$folder,$allowed,$res,
1498: $coursenum));
1.10 www 1499: $idx++;
1.148 www 1500: $shown++;
1.10 www 1501: }
1.148 www 1502: unless ($shown) {
1.131 www 1503: $r->print('<tr><td>'.&mt('Currently no documents.').'</td></tr>');
1504: }
1.168 www 1505: $r->print("\n</table>\n");
1.278 albertel 1506:
1.281 albertel 1507: &print_paste_buffer($r,$container);
1508:
1.7 www 1509: }
1510: }
1.1 www 1511:
1.188 raeburn 1512: sub process_file_upload {
1.194 raeburn 1513: my ($upload_output,$coursenum,$coursedom,$allfiles,$codebase,$uploadcmd) = @_;
1.188 raeburn 1514: # upload a file, if present
1515: my $parseaction;
1.190 albertel 1516: if ($env{'form.parserflag'}) {
1.188 raeburn 1517: $parseaction = 'parse';
1518: }
1519: my $phase_status;
1520: my $folder=$env{'form.folder'};
1.194 raeburn 1521: if ($folder eq '') {
1.188 raeburn 1522: $folder='default';
1523: }
1.194 raeburn 1524: if ( ($folder=~/^$uploadcmd/) || ($uploadcmd eq 'default') ) {
1.188 raeburn 1525: my $errtext='';
1526: my $fatal=0;
1527: my $container='sequence';
1528: if ($env{'form.pagepath'}) {
1529: $container='page';
1530: }
1531: ($errtext,$fatal)=
1532: &mapread($coursenum,$coursedom,$folder.'.'.$container);
1.245 albertel 1533: if ($#LONCAPA::map::order<1) {
1534: $LONCAPA::map::order[0]=1;
1535: $LONCAPA::map::resources[1]='';
1.188 raeburn 1536: }
1537: if ($fatal) {
1538: return 'failed';
1539: }
1540: my $destination = 'docs/';
1.194 raeburn 1541: if ($folder =~ /^supplemental/) {
1542: $destination = 'supplemental/';
1543: }
1544: if (($folder eq 'default') || ($folder eq 'supplemental')) {
1.188 raeburn 1545: $destination .= 'default/';
1.194 raeburn 1546: } elsif ($folder =~ /^(default|supplemental)_(\d+)$/) {
1547: $destination .= $2.'/';
1.188 raeburn 1548: }
1549: # this is for a course, not a user, so set coursedoc flag
1550: # probably the only place in the system where this should be "1"
1.245 albertel 1551: my $newidx=&LONCAPA::map::getresidx();
1.188 raeburn 1552: $destination .= $newidx;
1.190 albertel 1553: my $url=&Apache::lonnet::userfileupload('uploaddoc',1,$destination,
1554: $parseaction,$allfiles,
1555: $codebase);
1.188 raeburn 1556: my $ext='false';
1557: if ($url=~/^http\:\/\//) { $ext='true'; }
1.270 albertel 1558: $url = &LONCAPA::map::qtunescape($url);
1.188 raeburn 1559: my $comment=$env{'form.comment'};
1.270 albertel 1560: $comment = &LONCAPA::map::qtunescape($comment);
1.188 raeburn 1561: if ($folder=~/^supplemental/) {
1562: $comment=time.'___&&&___'.$env{'user.name'}.'___&&&___'.
1563: $env{'user.domain'}.'___&&&___'.$comment;
1564: }
1565:
1.245 albertel 1566: $LONCAPA::map::resources[$newidx]=
1567: $comment.':'.$url.':'.$ext.':normal:res';
1568: $LONCAPA::map::order[$#LONCAPA::map::order+1]= $newidx;
1.190 albertel 1569: ($errtext,$fatal)=&storemap($coursenum,$coursedom,
1570: $folder.'.'.$container);
1.188 raeburn 1571: if ($fatal) {
1572: $$upload_output .= '<p><font color="red">'.$errtext.'</font></p>';
1573: return 'failed';
1574: } else {
1575: if ($parseaction eq 'parse') {
1.190 albertel 1576: my $total_embedded = keys(%{$allfiles});
1.188 raeburn 1577: if ($total_embedded > 0) {
1578: my $num = 0;
1.269 albertel 1579: my $state = '
1.282 ! albertel 1580: <input type="hidden" name="folderpath" value="'.&HTML::Entities::encode($env{'form.folderpath'},'<>&"').'" />
1.269 albertel 1581: <input type="hidden" name="cmd" value="upload_embedded" />
1.188 raeburn 1582: <input type="hidden" name="newidx" value="'.$newidx.'" />
1.228 www 1583: <input type="hidden" name="primaryurl" value="'.&escape($url).'" />
1.188 raeburn 1584: <input type="hidden" name="phasetwo" value="'.$total_embedded.'" />';
1.269 albertel 1585: $phase_status = 'phasetwo';
1586:
1587: $$upload_output .=
1588: 'This file contains embedded multimedia objects, which need to be uploaded to LON-CAPA.<br />'.
1589: &ask_for_embedded_content('/adm/coursedocs',
1590: $state,$allfiles,$codebase);
1.188 raeburn 1591: } else {
1592: $$upload_output .= 'No embedded items identified<br />';
1593: }
1594: }
1595: }
1596: }
1597: return $phase_status;
1598: }
1599:
1.269 albertel 1600: sub ask_for_embedded_content {
1.271 albertel 1601: my ($actionurl,$state,$allfiles,$codebase,$args)=@_;
1.269 albertel 1602: my $upload_output = '
1603: <form name="upload_embedded" action="'.$actionurl.'"
1604: method="post" enctype="multipart/form-data">';
1605: $upload_output .= $state;
1.271 albertel 1606: $upload_output .= '<b>Upload embedded files</b>:<br />'.
1607: &Apache::loncommon::start_data_table();
1.269 albertel 1608:
1609: my $num = 0;
1.276 albertel 1610: foreach my $embed_file (sort {lc($a) cmp lc($b)} keys(%{$allfiles})) {
1.271 albertel 1611: $upload_output .= &Apache::loncommon::start_data_table_row().
1612: '<td>'.$embed_file.'</td><td>';
1.274 albertel 1613: if ($args->{'ignore_remote_references'}
1614: && $embed_file =~ m{^\w+://}) {
1615: $upload_output.='<span class="LC_warning">'.&mt("URL points to other server.").'</span>';
1616: } elsif ($args->{'error_on_invalid_names'}
1.271 albertel 1617: && $embed_file ne &Apache::lonnet::clean_filename($embed_file,{'keep_path' => 1,})) {
1618:
1619: $upload_output.='<span class="LC_warning">'.&mt("Invalid characters").'</span>';
1.274 albertel 1620:
1.271 albertel 1621: } else {
1.274 albertel 1622:
1.271 albertel 1623: $upload_output .='
1.269 albertel 1624: <input name="embedded_item_'.$num.'" type="file" value="bob" />
1625: <input name="embedded_orig_'.$num.'" type="hidden" value="'.&escape($embed_file).'" />';
1.271 albertel 1626: my $attrib = join(':',@{$$allfiles{$embed_file}});
1627: $upload_output .=
1.269 albertel 1628: "\n\t\t".
1.271 albertel 1629: '<input name="embedded_attrib_'.$num.'" type="hidden" value="'.
1630: $attrib.'" />';
1631: if (exists($$codebase{$embed_file})) {
1632: $upload_output .=
1633: "\n\t\t".
1634: '<input name="codebase_'.$num.'" type="hidden" value="'.
1635: &escape($$codebase{$embed_file}).'" />';
1636: }
1.269 albertel 1637: }
1.271 albertel 1638: $upload_output .= '</td>'.&Apache::loncommon::end_data_table_row();
1.269 albertel 1639: $num++;
1640: }
1.271 albertel 1641: $upload_output .= &Apache::loncommon::end_data_table().'<br />
1.269 albertel 1642: <input type ="hidden" name="number_embedded_items" value="'.$num.'" />
1.275 albertel 1643: <input type ="submit" value="'.&mt('Upload Listed Files').'" />
1644: '.&mt('(only files for which a location has been provided will be uploaded)').'
1.269 albertel 1645: </form>';
1646: return $upload_output;
1647: }
1648:
1.188 raeburn 1649: sub process_secondary_uploads {
1650: my ($upload_output,$coursedom,$coursenum,$formname,$num,$newidx) = @_;
1651: my $folder=$env{'form.folder'};
1652: my $destination = 'docs/';
1.195 raeburn 1653: if ($folder =~ /^supplemental/) {
1654: $destination = 'supplemental/';
1655: }
1656: if (($folder eq 'default') || ($folder eq 'supplemental')) {
1.188 raeburn 1657: $destination .= 'default/';
1.195 raeburn 1658: } elsif ($folder =~ /^(default|supplemental)_(\d+)$/) {
1.217 raeburn 1659: $destination .= $2.'/';
1.188 raeburn 1660: }
1661: $destination .= $newidx;
1662: my ($url,$filename);
1663: $url=&Apache::lonnet::userfileupload($formname.$num,1,$destination);
1.265 albertel 1664: ($filename) = ($url =~ m{^/uploaded/\Q$coursedom\E/\Q$coursenum\E/\Q$destination\E/(.+)$});
1.188 raeburn 1665: return $filename;
1666: }
1667:
1.281 albertel 1668: sub is_supplemental_title {
1669: my ($title) = @_;
1670: return scalar($title =~ m/^(\d+)___&&&___($match_username)___&&&___($match_domain)___&&&___(.*)$/);
1671: }
1672:
1673: sub parse_supplemental_title {
1674: my ($title) = @_;
1675:
1676: my ($foldertitle,$renametitle);
1677: if ($title =~ /&&&/) {
1678: $title = &HTML::Entites::decode($title);
1679: }
1680: if ($title =~ m/^(\d+)___&&&___($match_username)___&&&___($match_domain)___&&&___(.*)$/) {
1681: $renametitle=$4;
1682: my ($time,$uname,$udom) = ($1,$2,$3);
1683: $foldertitle=&Apache::lontexconvert::msgtexconverted($4);
1684: my $name = &Apache::loncommon::plainname($uname,$udom);
1685: $name = &HTML::Entities::encode($name,'"<>&\'');
1686: $title='<i>'.&Apache::lonlocal::locallocaltime($time).'</i> '.
1687: $name.': <br />'.$foldertitle;
1688: }
1689: if (wantarray) {
1690: return ($title,$foldertitle,$renametitle);
1691: }
1692: return $title;
1693: }
1694:
1.8 www 1695: # --------------------------------------------------------------- An entry line
1696:
1697: sub entryline {
1.112 raeburn 1698: my ($index,$title,$url,$folder,$allowed,$residx,$coursenum)=@_;
1.281 albertel 1699:
1700: my ($foldertitle,$pagetitle,$renametitle);
1701: if (&is_supplemental_title($title)) {
1702: ($title,$foldertitle,$renametitle) = &parse_supplemental_title($title);
1703: $pagetitle = $foldertitle;
1704: } else {
1705: $title=&HTML::Entities::encode($title,'"<>&\'');
1706: $renametitle=$title;
1707: $foldertitle=$title;
1708: $pagetitle=$title;
1709: }
1710:
1.245 albertel 1711: my $orderidx=$LONCAPA::map::order[$index];
1.281 albertel 1712:
1713:
1.222 albertel 1714: $renametitle=~s/\\/\\\\/g;
1.38 www 1715: $renametitle=~s/\"\;/\\\"/g;
1.8 www 1716: my $line='<tr>';
1717: # Edit commands
1.142 raeburn 1718: my $container;
1.280 albertel 1719: my ($container, $type, $esc_path, $path, $symb);
1.174 albertel 1720: if ($env{'form.folderpath'}) {
1.280 albertel 1721: $type = 'folder';
1.142 raeburn 1722: $container = 'sequence';
1.282 ! albertel 1723: $esc_path=&escape($env{'form.folderpath'});
! 1724: $path = &HTML::Entities::encode($env{'form.folderpath'},'<>&"');
1.174 albertel 1725: # $htmlfoldername=&HTML::Entities::encode($env{'form.foldername'},'<>&"');
1.120 www 1726: }
1.174 albertel 1727: if ($env{'form.pagepath'}) {
1.280 albertel 1728: $type = $container = 'page';
1729: $esc_path=&escape($path = $env{'form.pagepath'});
1.282 ! albertel 1730: $path = &HTML::Entities::encode($env{'form.pagepath'},'<>&"');
1.280 albertel 1731: $symb=&escape($env{'form.pagesymb'});
1.142 raeburn 1732: }
1.168 www 1733: my $cpinfo='';
1.109 albertel 1734: if ($allowed) {
1.123 www 1735: my $incindex=$index+1;
1736: my $selectbox='';
1.168 www 1737: if (($folder!~/^supplemental/) &&
1.245 albertel 1738: ($#LONCAPA::map::order>0) &&
1.168 www 1739: ((split(/\:/,
1.245 albertel 1740: $LONCAPA::map::resources[$LONCAPA::map::order[0]]))[1]
1.168 www 1741: ne '') &&
1742: ((split(/\:/,
1.245 albertel 1743: $LONCAPA::map::resources[$LONCAPA::map::order[1]]))[1]
1.168 www 1744: ne '')) {
1.123 www 1745: $selectbox=
1.124 www 1746: '<input type="hidden" name="currentpos" value="'.$incindex.'" />'.
1.123 www 1747: '<select name="newpos" onChange="this.form.submit()">';
1.245 albertel 1748: for (my $i=1;$i<=$#LONCAPA::map::order+1;$i++) {
1.123 www 1749: if ($i==$incindex) {
1750: $selectbox.='<option value="" selected="1">('.$i.')</option>';
1751: } else {
1752: $selectbox.='<option value="'.$i.'">'.$i.'</option>';
1753: }
1754: }
1755: $selectbox.='</select>';
1756: }
1.119 www 1757: my %lt=&Apache::lonlocal::texthash(
1758: 'up' => 'Move Up',
1.109 albertel 1759: 'dw' => 'Move Down',
1760: 'rm' => 'Remove',
1.171 www 1761: 'ct' => 'Cut',
1.168 www 1762: 'rn' => 'Rename',
1763: 'cp' => 'Copy');
1.211 www 1764: my $nocopy=0;
1.268 www 1765: my $nocut=0;
1.211 www 1766: if ($url=~/\.(page|sequence)$/) {
1767: foreach (&Apache::lonsequence::attemptread(&Apache::lonnet::filelocation('',$url))) {
1768: my ($title,$url,$ext,$type)=split(/\:/,$_);
1769: if (($url=~/\.(page|sequence)/) && ($type ne 'zombie')) {
1770: $nocopy=1;
1771: last;
1772: }
1773: }
1774: }
1.268 www 1775: if ($url=~/^\/res\/lib\/templates\//) {
1776: $nocopy=1;
1777: $nocut=1;
1778: }
1.211 www 1779: my $copylink=' ';
1.267 www 1780: my $cutlink=' ';
1.280 albertel 1781:
1782: if (!$nocopy) {
1783: $copylink=(<<ENDCOPY);
1.281 albertel 1784: <a href='javascript:markcopy("$esc_path","$index","$renametitle","$container","$symb","$folder");'>
1.280 albertel 1785: <font size="-2" color="#000099">$lt{'cp'}</font></a>
1.211 www 1786: ENDCOPY
1.280 albertel 1787: }
1788: if (!$nocut) {
1789: $cutlink=(<<ENDCUT);
1.281 albertel 1790: <a href='javascript:cutres("$esc_path","$index","$renametitle","$container","$symb","$folder");'>
1.267 www 1791: <font size="-2" color="#550044">$lt{'ct'}</font></a>
1792: ENDCUT
1.280 albertel 1793: }
1794: $line.=(<<END);
1795: <form name="entry_$index" action="/adm/coursedocs" method="post">
1796: <input type="hidden" name="${type}path" value="$path" />
1797: <input type="hidden" name="${type}symb" value="$symb" />
1798: <input type="hidden" name="setparms" value="$orderidx" />
1799: <input type="hidden" name="changeparms" value="0" />
1800: <td>
1801: <table border='0' cellspacing='2' cellpadding='0'>
1802: <tr>
1803: <td bgcolor="#DDDDDD">
1.282 ! albertel 1804: <a href='/adm/coursedocs?cmd=up_$index&${type}path=$esc_path&${type}symb=$symb$cpinfo'><img src="${iconpath}move_up.gif" alt='$lt{'up'}' class="LC_icon" /></a>
1.280 albertel 1805: </td>
1806: </tr>
1807: <tr>
1808: <td bgcolor="#DDDDDD">
1.282 ! albertel 1809: <a href='/adm/coursedocs?cmd=down_$index&${type}path=$esc_path&${type}symb=$symb$cpinfo'><img src="${iconpath}move_down.gif" alt='$lt{'dw'}' class="LC_icon" /></a>
1.280 albertel 1810: </td>
1811: </tr>
1812: </table>
1813: </td>
1814: <td>
1815: $selectbox
1816: </td>
1817: <td bgcolor="#DDDDDD">
1818: <a href='javascript:removeres("$esc_path","$index","$renametitle","$container","$symb");'><font size="-2" color="#990000">$lt{'rm'}</font></a>
1.267 www 1819: $cutlink
1.280 albertel 1820: <a href='javascript:changename("$esc_path","$index","$renametitle","$container","$symb");'><font size="-2" color="#009900">$lt{'rn'}</font></a>
1.211 www 1821: $copylink
1.280 albertel 1822: </td>
1.142 raeburn 1823: END
1.280 albertel 1824:
1.8 www 1825: }
1.16 www 1826: # Figure out what kind of a resource this is
1827: my ($extension)=($url=~/\.(\w+)$/);
1828: my $uploaded=($url=~/^\/*uploaded\//);
1.97 albertel 1829: my $icon=&Apache::loncommon::icon($url);
1.17 www 1830: my $isfolder=0;
1.142 raeburn 1831: my $ispage=0;
1.114 albertel 1832: my $folderarg;
1.142 raeburn 1833: my $pagearg;
1834: my $pagefile;
1.16 www 1835: if ($uploaded) {
1.135 albertel 1836: if ($extension eq 'sequence') {
1837: $icon=$iconpath.'/folder_closed.gif';
1.264 albertel 1838: $url=~/\Q$coursenum\E\/([\/\w]+)\.sequence$/;
1.135 albertel 1839: $url='/adm/coursedocs?';
1840: $folderarg=$1;
1841: $isfolder=1;
1.142 raeburn 1842: } elsif ($extension eq 'page') {
1843: $icon=$iconpath.'/page.gif';
1.264 albertel 1844: $url=~/\Q$coursenum\E\/([\/\w]+)\.page$/;
1.142 raeburn 1845: $pagearg=$1;
1846: $url='/adm/coursedocs?';
1847: $ispage=1;
1.135 albertel 1848: } else {
1849: &Apache::lonnet::allowuploaded('/adm/coursedoc',$url);
1850: }
1.16 www 1851: }
1.215 albertel 1852: $url=~s-^http(\&colon\;|:)//-/adm/wrapper/ext/-;
1.142 raeburn 1853: if ((!$isfolder) && ($residx) && ($folder!~/supplemental/) && (!$ispage)) {
1.113 albertel 1854: my $symb=&Apache::lonnet::symbclean(
1.50 www 1855: &Apache::lonnet::declutter('uploaded/'.
1.174 albertel 1856: $env{'course.'.$env{'request.course.id'}.'.domain'}.'/'.
1857: $env{'course.'.$env{'request.course.id'}.'.num'}.'/'.$folder.
1.50 www 1858: '.sequence').
1859: '___'.$residx.'___'.
1.113 albertel 1860: &Apache::lonnet::declutter($url));
1861: (undef,undef,$url)=&Apache::lonnet::decode_symb($symb);
1862: $url=&Apache::lonnet::clutter($url);
1.127 albertel 1863: if ($url=~/^\/*uploaded\//) {
1864: $url=~/\.(\w+)$/;
1865: my $embstyle=&Apache::loncommon::fileembstyle($1);
1866: if (($embstyle eq 'img') || ($embstyle eq 'emb')) {
1867: $url='/adm/wrapper'.$url;
1868: } elsif ($embstyle eq 'ssi') {
1869: #do nothing with these
1870: } elsif ($url!~/\.(sequence|page)$/) {
1871: $url='/adm/coursedocs/showdoc'.$url;
1872: }
1.145 albertel 1873: } elsif ($url=~m|^/ext/|) {
1874: $url='/adm/wrapper'.$url;
1.127 albertel 1875: }
1.241 www 1876: if (&Apache::lonnet::symbverify($symb,$url)) {
1877: $url.=(($url=~/\?/)?'&':'?').'symb='.&escape($symb);
1878: } else {
1879: $url='';
1880: }
1.152 albertel 1881: if ($container eq 'page') {
1.174 albertel 1882: my $symb=$env{'form.pagesymb'};
1.152 albertel 1883:
1884: $url=&Apache::lonnet::clutter((&Apache::lonnet::decode_symb($symb))[2]);
1.228 www 1885: $url.=(($url=~/\?/)?'&':'?').'symb='.&escape($symb);
1.152 albertel 1886: }
1.50 www 1887: }
1.120 www 1888: my $parameterset=' ';
1.216 albertel 1889: if ($isfolder || $extension eq 'sequence') {
1.228 www 1890: my $foldername=&escape($foldertitle);
1.174 albertel 1891: my $folderpath=$env{'form.folderpath'};
1.114 albertel 1892: if ($folderpath) { $folderpath.='&' };
1.242 www 1893: # Append randompick number, hidden, and encrypted with ":" to foldername,
1894: # so it gets transferred between levels
1.245 albertel 1895: $folderpath.=$folderarg.'&'.$foldername.':'.(&LONCAPA::map::getparameter($orderidx,
1.242 www 1896: 'parameter_randompick'))[0]
1.245 albertel 1897: .':'.((&LONCAPA::map::getparameter($orderidx,
1.242 www 1898: 'parameter_hiddenresource'))[0]=~/^yes$/i)
1.245 albertel 1899: .':'.((&LONCAPA::map::getparameter($orderidx,
1.242 www 1900: 'parameter_encrypturl'))[0]=~/^yes$/i);
1.228 www 1901: $url.='folderpath='.&escape($folderpath).$cpinfo;
1.147 matthew 1902: $parameterset='<label>'.&mt('Randomly Pick: ').
1.258 www 1903: '<input type="text" size="4" onChange="this.form.changeparms.value='."'randompick'".';this.form.submit()" name="randpick_'.$orderidx.'" value="'.
1.245 albertel 1904: (&LONCAPA::map::getparameter($orderidx,
1.147 matthew 1905: 'parameter_randompick'))[0].
1.165 www 1906: '" />'.
1.272 albertel 1907: '<font size="-2"><a href="javascript:void(0)">'.&mt('Save').'</a></font></label>';
1.147 matthew 1908:
1.114 albertel 1909: }
1.142 raeburn 1910: if ($ispage) {
1.228 www 1911: my $pagename=&escape($pagetitle);
1.142 raeburn 1912: my $pagepath;
1.174 albertel 1913: my $folderpath=$env{'form.folderpath'};
1.142 raeburn 1914: if ($folderpath) { $pagepath = $folderpath.'&' };
1915: $pagepath.=$pagearg.'&'.$pagename;
1.174 albertel 1916: my $symb=$env{'form.pagesymb'};
1.152 albertel 1917: if (!$symb) {
1918: my $path='uploaded/'.
1.174 albertel 1919: $env{'course.'.$env{'request.course.id'}.'.domain'}.'/'.
1920: $env{'course.'.$env{'request.course.id'}.'.num'}.'/';
1.152 albertel 1921: $symb=&Apache::lonnet::encode_symb($path.$folder.'.sequence',
1922: $residx,
1923: $path.$pagearg.'.page');
1924: }
1.228 www 1925: $url.='pagepath='.&escape($pagepath).
1.282 ! albertel 1926: '&pagesymb='.&escape($symb).$cpinfo;
1.142 raeburn 1927: }
1.113 albertel 1928: $line.='<td bgcolor="#FFFFBB"><a href="'.$url.'"><img src="'.$icon.
1.282 ! albertel 1929: '" class="LC_icon" /></a></td>'.
1.241 www 1930: "<td bgcolor='#FFFFBB'>".($url?"<a href=\"$url\">":'').$title.
1931: ($url?'</a>':' <font size="-2">'.&mt('(re-initialize course to access)').'</font>')."</td>";
1.120 www 1932: if (($allowed) && ($folder!~/^supplemental/)) {
1933: my %lt=&Apache::lonlocal::texthash(
1934: 'hd' => 'Hidden',
1.165 www 1935: 'ec' => 'URL hidden');
1.122 www 1936: my $enctext=
1.245 albertel 1937: ((&LONCAPA::map::getparameter($orderidx,'parameter_encrypturl'))[0]=~/^yes$/i?' checked="1"':'');
1.122 www 1938: my $hidtext=
1.245 albertel 1939: ((&LONCAPA::map::getparameter($orderidx,'parameter_hiddenresource'))[0]=~/^yes$/i?' checked="1"':'');
1.120 www 1940: $line.=(<<ENDPARMS);
1941: <td bgcolor="#BBBBFF"><font size='-2'>
1.258 www 1942: <nobr><label><input type="checkbox" name="hidprs_$orderidx" onClick="this.form.changeparms.value='hiddenresource';this.form.submit()" $hidtext /> $lt{'hd'}</label></nobr></td>
1.149 albertel 1943: <td bgcolor="#BBBBFF"><font size='-2'>
1.258 www 1944: <nobr><label><input type="checkbox" name="encprs_$orderidx" onClick="this.form.changeparms.value='encrypturl';this.form.submit()" $enctext /> $lt{'ec'}</label></nobr></td>
1.120 www 1945: <td bgcolor="#BBBBFF"><font size="-2">$parameterset</font></td>
1946: ENDPARMS
1.119 www 1947: }
1.120 www 1948: $line.="</form></tr>";
1.8 www 1949: return $line;
1950: }
1951:
1.27 www 1952: # ---------------------------------------------------------------- tie the hash
1953:
1954: sub tiehash {
1.136 albertel 1955: my ($mode)=@_;
1.27 www 1956: $hashtied=0;
1.174 albertel 1957: if ($env{'request.course.fn'}) {
1.136 albertel 1958: if ($mode eq 'write') {
1.174 albertel 1959: if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.".db",
1.136 albertel 1960: &GDBM_WRCREAT(),0640)) {
1961: $hashtied=2;
1962: }
1963: } else {
1.174 albertel 1964: if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.".db",
1.136 albertel 1965: &GDBM_READER(),0640)) {
1.27 www 1966: $hashtied=1;
1.136 albertel 1967: }
1968: }
1.27 www 1969: }
1970: }
1971:
1972: sub untiehash {
1973: if ($hashtied) { untie %hash; }
1974: $hashtied=0;
1.221 albertel 1975: return OK;
1.27 www 1976: }
1977:
1.29 www 1978: # --------------------------------------------------------------- check on this
1979:
1980: sub checkonthis {
1981: my ($r,$url,$level,$title)=@_;
1.228 www 1982: $url=&unescape($url);
1.29 www 1983: $alreadyseen{$url}=1;
1984: $r->rflush();
1.41 www 1985: if (($url) && ($url!~/^\/uploaded\//) && ($url!~/\*$/)) {
1.108 albertel 1986: $r->print("\n<br />");
1.29 www 1987: for (my $i=0;$i<=$level*5;$i++) {
1988: $r->print(' ');
1989: }
1990: $r->print('<a href="'.$url.'" target="cat">'.
1991: ($title?$title:$url).'</a> ');
1992: if ($url=~/^\/res\//) {
1993: my $result=&Apache::lonnet::repcopy(
1994: &Apache::lonnet::filelocation('',$url));
1.172 raeburn 1995: if ($result eq 'ok') {
1.87 www 1996: $r->print('<font color="green">'.&mt('ok').'</font>');
1.29 www 1997: $r->rflush();
1.34 www 1998: &Apache::lonnet::countacc($url);
1999: $url=~/\.(\w+)$/;
2000: if (&Apache::loncommon::fileembstyle($1) eq 'ssi') {
2001: $r->print('<br />');
2002: $r->rflush();
2003: for (my $i=0;$i<=$level*5;$i++) {
2004: $r->print(' ');
2005: }
1.84 www 2006: $r->print('- '.&mt('Rendering').': ');
1.170 www 2007: my ($errorcount,$warningcount)=split(/:/,
2008: &Apache::lonnet::ssi_body($url,
1.173 albertel 2009: ('grade_target'=>'web',
2010: 'return_only_error_and_warning_counts' => 1)));
1.170 www 2011: if (($errorcount) ||
2012: ($warningcount)) {
2013: if ($errorcount) {
1.98 www 2014: $r->print('<img src="/adm/lonMisc/bomb.gif" /><font color="red"><b>'.
1.170 www 2015: $errorcount.' '.
1.87 www 2016: &mt('error(s)').'</b></font> ');
1.34 www 2017: }
1.170 www 2018: if ($warningcount) {
1.34 www 2019: $r->print('<font color="blue">'.
1.170 www 2020: $warningcount.' '.
1.84 www 2021: &mt('warning(s)').'</font>');
1.34 www 2022: }
2023: } else {
1.87 www 2024: $r->print('<font color="green">'.&mt('ok').'</font>');
1.34 www 2025: }
2026: $r->rflush();
2027: }
1.29 www 2028: my $dependencies=
2029: &Apache::lonnet::metadata($url,'dependencies');
2030: foreach (split(/\,/,$dependencies)) {
2031: if (($_=~/^\/res\//) && (!$alreadyseen{$_})) {
2032: &checkonthis($r,$_,$level+1);
2033: }
2034: }
1.172 raeburn 2035: } elsif ($result eq 'unavailable') {
1.84 www 2036: $r->print('<font color="red"><b>'.&mt('connection down').'</b></font>');
1.172 raeburn 2037: } elsif ($result eq 'not_found') {
1.100 www 2038: unless ($url=~/\$/) {
2039: $r->print('<font color="red"><b>'.&mt('not found').'</b></font>');
2040: } else {
2041: $r->print('<font color="yellow"><b>'.&mt('unable to verify variable URL').'</b></font>');
2042: }
1.29 www 2043: } else {
1.84 www 2044: $r->print('<font color="red"><b>'.&mt('access denied').'</b></font>');
1.29 www 2045: }
2046: }
2047: }
2048: }
2049:
1.1 www 2050:
1.75 www 2051: #
1.208 albertel 2052: # ----------------------------------------------------------------- List Symbs
2053: #
2054: sub list_symbs {
1.224 albertel 2055: my ($r) = @_;
2056:
2057: $r->print(&Apache::loncommon::start_page('Symb List'));
1.257 www 2058: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Symb List'));
1.224 albertel 2059: my $navmap = Apache::lonnavmaps::navmap->new();
2060: $r->print("<pre>\n");
2061: foreach my $res ($navmap->retrieveResources()) {
2062: $r->print($res->compTitle()."\t".$res->symb()."\n");
2063: }
2064: $r->print("\n</pre>\n");
2065: $r->print('<a href="/adm/coursedocs">'.&mt('Return to DOCS').'</a>');
1.208 albertel 2066: }
2067:
2068:
2069: #
1.75 www 2070: # -------------------------------------------------------------- Verify Content
2071: #
2072: sub verifycontent {
1.224 albertel 2073: my ($r) = @_;
1.230 albertel 2074: my $type = &Apache::loncommon::course_type();
1.26 www 2075: my $loaderror=&Apache::lonnet::overloaderror($r);
2076: if ($loaderror) { return $loaderror; }
1.229 raeburn 2077: $r->print(&Apache::loncommon::start_page('Verify '.$type.' Documents'));
1.257 www 2078: $r->print(&Apache::lonhtmlcommon::breadcrumbs('Verify '.$type.' Documents'));
1.27 www 2079: $hashtied=0;
1.30 www 2080: undef %alreadyseen;
2081: %alreadyseen=();
1.27 www 2082: &tiehash();
2083: foreach (keys %hash) {
1.140 www 2084: if ($hash{$_}=~/\.(page|sequence)$/) {
1.228 www 2085: if (($_=~/^src_/) && ($alreadyseen{&unescape($hash{$_})})) {
1.140 www 2086: $r->print('<hr /><font color="red">'.
1.230 albertel 2087: &mt('The following sequence or page is included more than once in your '.$type.': ').
1.228 www 2088: &unescape($hash{$_}).'</font><br />'.
1.140 www 2089: &mt('Note that grading records for problems included in this sequence or folder will overlap.<hr />'));
2090: }
2091: }
1.228 www 2092: if (($_=~/^src\_(.+)$/) && (!$alreadyseen{&unescape($hash{$_})})) {
1.29 www 2093: &checkonthis($r,$hash{$_},0,$hash{'title_'.$1});
1.27 www 2094: }
2095: }
2096: &untiehash();
1.108 albertel 2097: $r->print('<h1>'.&mt('Done').'.</h1>'.'<a href="/adm/coursedocs">'.
2098: &mt('Return to DOCS').'</a>');
1.75 www 2099: }
2100:
1.192 www 2101:
1.75 www 2102: # -------------------------------------------------------------- Check Versions
2103:
1.192 www 2104: sub devalidateversioncache {
2105: my $src=shift;
2106: &Apache::lonnet::devalidate_cache_new('courseresversion',$env{'request.course.id'}.'_'.
2107: &Apache::lonnet::clutter($src));
2108: }
2109:
1.75 www 2110: sub checkversions {
1.224 albertel 2111: my ($r) = @_;
1.230 albertel 2112: my $type = &Apache::loncommon::course_type();
1.229 raeburn 2113: $r->print(&Apache::loncommon::start_page("Check $type Document Versions"));
1.257 www 2114: $r->print(&Apache::lonhtmlcommon::breadcrumbs("Check $type Document Versions"));
1.89 www 2115: my $header='';
2116: my $startsel='';
2117: my $monthsel='';
2118: my $weeksel='';
2119: my $daysel='';
2120: my $allsel='';
2121: my %changes=();
2122: my $starttime=0;
1.91 www 2123: my $haschanged=0;
1.92 www 2124: my %setversions=&Apache::lonnet::dump('resourceversions',
1.174 albertel 2125: $env{'course.'.$env{'request.course.id'}.'.domain'},
2126: $env{'course.'.$env{'request.course.id'}.'.num'});
1.92 www 2127:
2128: $hashtied=0;
2129: &tiehash();
2130: my %newsetversions=();
1.174 albertel 2131: if ($env{'form.setmostrecent'}) {
1.91 www 2132: $haschanged=1;
1.92 www 2133: foreach (keys %hash) {
2134: if ($_=~/^ids\_(\/res\/.+)$/) {
1.93 www 2135: $newsetversions{$1}='mostrecent';
1.192 www 2136: &devalidateversioncache($1);
1.92 www 2137: }
2138: }
1.174 albertel 2139: } elsif ($env{'form.setcurrent'}) {
1.91 www 2140: $haschanged=1;
1.92 www 2141: foreach (keys %hash) {
2142: if ($_=~/^ids\_(\/res\/.+)$/) {
1.93 www 2143: my $getvers=&Apache::lonnet::getversion($1);
2144: if ($getvers>0) {
2145: $newsetversions{$1}=$getvers;
1.192 www 2146: &devalidateversioncache($1);
1.93 www 2147: }
1.92 www 2148: }
2149: }
1.174 albertel 2150: } elsif ($env{'form.setversions'}) {
1.91 www 2151: $haschanged=1;
1.174 albertel 2152: foreach (keys %env) {
1.92 www 2153: if ($_=~/^form\.set_version_(.+)$/) {
2154: my $src=$1;
1.174 albertel 2155: if (($env{$_}) && ($env{$_} ne $setversions{$src})) {
2156: $newsetversions{$src}=$env{$_};
1.192 www 2157: &devalidateversioncache($src);
1.92 www 2158: }
2159: }
2160: }
1.91 www 2161: }
2162: if ($haschanged) {
1.92 www 2163: if (&Apache::lonnet::put('resourceversions',\%newsetversions,
1.174 albertel 2164: $env{'course.'.$env{'request.course.id'}.'.domain'},
2165: $env{'course.'.$env{'request.course.id'}.'.num'}) eq 'ok') {
1.272 albertel 2166: $r->print('<h1>'.&mt('Your Version Settings have been Saved').'</h1>');
1.92 www 2167: } else {
1.272 albertel 2168: $r->print('<h1><font color="red">'.&mt('An Error Occured while Attempting to Save your Version Settings').'</font></h1>');
1.92 www 2169: }
1.136 albertel 2170: &mark_hash_old();
1.91 www 2171: }
1.136 albertel 2172: &changewarning($r,'');
1.174 albertel 2173: if ($env{'form.timerange'} eq 'all') {
1.89 www 2174: # show all documents
1.230 albertel 2175: $header=&mt('All Documents in '.$type);
1.91 www 2176: $allsel=1;
1.90 www 2177: foreach (keys %hash) {
2178: if ($_=~/^ids\_(\/res\/.+)$/) {
2179: my $src=$1;
2180: $changes{$src}=1;
2181: }
2182: }
1.89 www 2183: } else {
2184: # show documents which changed
2185: %changes=&Apache::lonnet::dump
1.174 albertel 2186: ('versionupdate',$env{'course.'.$env{'request.course.id'}.'.domain'},
2187: $env{'course.'.$env{'request.course.id'}.'.num'});
1.89 www 2188: my $firstkey=(keys %changes)[0];
2189: unless ($firstkey=~/^error\:/) {
1.174 albertel 2190: unless ($env{'form.timerange'}) {
2191: $env{'form.timerange'}=604800;
1.89 www 2192: }
1.174 albertel 2193: my $seltext=&mt('during the last').' '.$env{'form.timerange'}.' '
1.89 www 2194: .&mt('seconds');
1.174 albertel 2195: if ($env{'form.timerange'}==-1) {
1.89 www 2196: $seltext='since start of course';
2197: $startsel='selected';
1.174 albertel 2198: $env{'form.timerange'}=time;
1.89 www 2199: }
1.174 albertel 2200: $starttime=time-$env{'form.timerange'};
2201: if ($env{'form.timerange'}==2592000) {
1.89 www 2202: $seltext=&mt('during the last month').' ('.&Apache::lonlocal::locallocaltime($starttime).')';
2203: $monthsel='selected';
1.174 albertel 2204: } elsif ($env{'form.timerange'}==604800) {
1.89 www 2205: $seltext=&mt('during the last week').' ('.&Apache::lonlocal::locallocaltime($starttime).')';
2206: $weeksel='selected';
1.174 albertel 2207: } elsif ($env{'form.timerange'}==86400) {
1.89 www 2208: $seltext=&mt('since yesterday').' ('.&Apache::lonlocal::locallocaltime($starttime).')';
2209: $daysel='selected';
2210: }
2211: $header=&mt('Content changed').' '.$seltext;
2212: } else {
2213: $header=&mt('No content modifications yet.');
2214: }
2215: }
1.92 www 2216: %setversions=&Apache::lonnet::dump('resourceversions',
1.174 albertel 2217: $env{'course.'.$env{'request.course.id'}.'.domain'},
2218: $env{'course.'.$env{'request.course.id'}.'.num'});
1.89 www 2219: my %lt=&Apache::lonlocal::texthash
1.229 raeburn 2220: ('st' => 'Version changes since start of '.$type,
1.88 www 2221: 'lm' => 'Version changes since last Month',
2222: 'lw' => 'Version changes since last Week',
2223: 'sy' => 'Version changes since Yesterday',
1.91 www 2224: 'al' => 'All Resources (possibly large output)',
1.88 www 2225: 'sd' => 'Display',
1.84 www 2226: 'fi' => 'File',
2227: 'md' => 'Modification Date',
1.87 www 2228: 'mr' => 'Most recently published Version',
1.229 raeburn 2229: 've' => 'Version used in '.$type,
2230: 'vu' => 'Set Version to be used in '.$type,
2231: 'sv' => 'Set Versions to be used in '.$type.' according to Selections below',
1.91 www 2232: 'sm' => 'Keep all Resources up-to-date with most recent Versions (default)',
2233: 'sc' => 'Set all Resource Versions to current Version (Fix Versions)',
1.84 www 2234: 'di' => 'Differences');
1.89 www 2235: $r->print(<<ENDHEADERS);
1.31 www 2236: <form action="/adm/coursedocs" method="post">
1.91 www 2237: <input type="hidden" name="versions" value="1" />
2238: <input type="submit" name="setmostrecent" value="$lt{'sm'}" />
2239: <input type="submit" name="setcurrent" value="$lt{'sc'}" /><hr />
1.31 www 2240: <select name="timerange">
1.88 www 2241: <option value='all' $allsel>$lt{'al'}</option>
1.84 www 2242: <option value="-1" $startsel>$lt{'st'}</option>
2243: <option value="2592000" $monthsel>$lt{'lm'}</option>
2244: <option value="604800" $weeksel>$lt{'lw'}</option>
2245: <option value="86400" $daysel>$lt{'sy'}</option>
1.31 www 2246: </select>
1.91 www 2247: <input type="submit" name="display" value="$lt{'sd'}" />
1.89 www 2248: <h3>$header</h3>
1.91 www 2249: <input type="submit" name="setversions" value="$lt{'sv'}" />
1.103 matthew 2250: <table border="0">
1.31 www 2251: ENDHEADERS
1.91 www 2252: foreach (sort keys %changes) {
1.89 www 2253: if ($changes{$_}>$starttime) {
2254: my ($root,$extension)=($_=~/^(.*)\.(\w+)$/);
2255: my $currentversion=&Apache::lonnet::getversion($_);
1.93 www 2256: if ($currentversion<0) {
2257: $currentversion=&mt('Could not be determined.');
2258: }
1.89 www 2259: my $linkurl=&Apache::lonnet::clutter($_);
2260: $r->print(
1.103 matthew 2261: '<tr><td colspan="5"><br /><br /><font size="+1"><b>'.
1.91 www 2262: &Apache::lonnet::gettitle($linkurl).
1.103 matthew 2263: '</b></font></td></tr>'.
2264: '<tr><td> </td>'.
2265: '<td colspan="4">'.
2266: '<a href="'.$linkurl.'" target="cat">'.$linkurl.
2267: '</a></td></tr>'.
2268: '<tr><td></td>'.
2269: '<td title="'.$lt{'md'}.'">'.
1.102 matthew 2270: &Apache::lonlocal::locallocaltime(
2271: &Apache::lonnet::metadata($root.'.'.$extension,
2272: 'lastrevisiondate')
2273: ).
1.103 matthew 2274: '</td>'.
2275: '<td title="'.$lt{'mr'}.'"><nobr>Most Recent: '.
2276: '<font size="+1">'.$currentversion.'</font>'.
2277: '</nobr></td>'.
1.229 raeburn 2278: '<td title="'.$lt{'ve'}.'"><nobr>In '.$type.': '.
1.103 matthew 2279: '<font size="+1">');
1.87 www 2280: # Used in course
1.89 www 2281: my $usedversion=$hash{'version_'.$linkurl};
1.93 www 2282: if (($usedversion) && ($usedversion ne 'mostrecent')) {
1.89 www 2283: $r->print($usedversion);
2284: } else {
2285: $r->print($currentversion);
2286: }
1.103 matthew 2287: $r->print('</font></nobr></td><td title="'.$lt{'vu'}.'">'.
2288: '<nobr>Use: ');
1.87 www 2289: # Set version
1.92 www 2290: $r->print(&Apache::loncommon::select_form($setversions{$linkurl},
1.89 www 2291: 'set_version_'.$linkurl,
1.136 albertel 2292: ('select_form_order' =>
2293: ['',1..$currentversion,'mostrecent'],
2294: '' => '',
1.93 www 2295: 'mostrecent' => 'most recent',
1.89 www 2296: map {$_,$_} (1..$currentversion))));
1.103 matthew 2297: $r->print('</nobr></td></tr><tr><td></td>');
1.89 www 2298: my $lastold=1;
2299: for (my $prevvers=1;$prevvers<$currentversion;$prevvers++) {
2300: my $url=$root.'.'.$prevvers.'.'.$extension;
2301: if (&Apache::lonnet::metadata($url,'lastrevisiondate')<
2302: $starttime) {
2303: $lastold=$prevvers;
2304: }
2305: }
1.103 matthew 2306: #
2307: # Code to figure out how many version entries should go in
2308: # each of the four columns
2309: my $entries_per_col = 0;
2310: my $num_entries = ($currentversion-$lastold);
2311: if ($num_entries % 4 == 0) {
2312: $entries_per_col = $num_entries/4;
2313: } else {
2314: $entries_per_col = $num_entries/4 + 1;
2315: }
2316: my $entries_count = 0;
2317: $r->print('<td valign="top"><font size="-2">');
2318: my $cols_output = 1;
1.32 www 2319: for (my $prevvers=$lastold;$prevvers<$currentversion;$prevvers++) {
1.89 www 2320: my $url=$root.'.'.$prevvers.'.'.$extension;
1.103 matthew 2321: $r->print('<nobr><a href="'.&Apache::lonnet::clutter($url).
1.91 www 2322: '">'.&mt('Version').' '.$prevvers.'</a> ('.
1.103 matthew 2323: &Apache::lonlocal::locallocaltime(
2324: &Apache::lonnet::metadata($url,
2325: 'lastrevisiondate')
2326: ).
1.91 www 2327: ')');
1.89 www 2328: if (&Apache::loncommon::fileembstyle($extension) eq 'ssi') {
1.33 www 2329: $r->print(' <a href="/adm/diff?filename='.
1.89 www 2330: &Apache::lonnet::clutter($root.'.'.$extension).
2331: '&versionone='.$prevvers.
2332: '">'.&mt('Diffs').'</a>');
2333: }
1.103 matthew 2334: $r->print('</nobr><br />');
2335: if (++$entries_count % $entries_per_col == 0) {
2336: $r->print('</font></td>');
2337: if ($cols_output != 4) {
2338: $r->print('<td valign="top"><font size="-2">');
2339: $cols_output++;
2340: }
2341: }
1.89 www 2342: }
1.103 matthew 2343: while($cols_output++ < 4) {
2344: $r->print('</font></td><td><font>')
2345: }
2346: $r->print('</font></td></tr>'."\n");
1.89 www 2347: }
2348: }
1.92 www 2349: $r->print('</table></form>');
1.89 www 2350: $r->print('<h1>'.&mt('Done').'.</h1>');
2351:
2352: &untiehash();
1.75 www 2353: }
2354:
1.136 albertel 2355: sub mark_hash_old {
2356: my $retie_hash=0;
2357: if ($hashtied) {
2358: $retie_hash=1;
2359: &untiehash();
2360: }
2361: &tiehash('write');
2362: $hash{'old'}=1;
2363: &untiehash();
2364: if ($retie_hash) { &tiehash(); }
2365: }
2366:
2367: sub is_hash_old {
2368: my $untie_hash=0;
2369: if (!$hashtied) {
2370: $untie_hash=1;
2371: &tiehash();
2372: }
2373: my $return=$hash{'old'};
2374: if ($untie_hash) { &untiehash(); }
2375: return $return;
2376: }
2377:
1.91 www 2378: sub changewarning {
1.177 albertel 2379: my ($r,$postexec,$message,$url)=@_;
1.136 albertel 2380: if (!&is_hash_old()) { return; }
1.150 albertel 2381: my $pathvar='folderpath';
1.228 www 2382: my $path=&escape($env{'form.folderpath'});
1.177 albertel 2383: if (!defined($url)) {
2384: if (defined($env{'form.pagepath'})) {
2385: $pathvar='pagepath';
1.228 www 2386: $path=&escape($env{'form.pagepath'});
2387: $path.='&pagesymb='.&escape($env{'form.pagesymb'});
1.177 albertel 2388: }
2389: $url='/adm/coursedocs?'.$pathvar.'='.$path;
2390: }
1.230 albertel 2391: my $course_type = &Apache::loncommon::course_type();
1.177 albertel 2392: if (!defined($message)) {
2393: $message='Changes will become active for your current session after [_1], or the next time you log in.';
1.150 albertel 2394: }
1.185 www 2395: $r->print("\n\n".
2396: '<script>function reinit(tf) { tf.submit();'.$postexec.' }</script>'."\n".
2397: '<form name="reinitform" method="post" action="/adm/roles" target="loncapaclient">'.
1.177 albertel 2398: '<input type="hidden" name="orgurl" value="'.$url.
1.117 albertel 2399: '" /><input type="hidden" name="selectrole" value="1" /><h3><font color="red">'.
1.177 albertel 2400: &mt($message,' <input type="hidden" name="'.
2401: $env{'request.role'}.'" value="1" /><input type="button" value="'.
1.230 albertel 2402: &mt('re-initializing '.$course_type).'" onClick="reinit(this.form)" />').
1.185 www 2403: $help{'Caching'}.'</font></h3></form>'."\n\n");
1.91 www 2404: }
2405:
1.257 www 2406: # =========================================== Breadcrumbs for special functions
2407:
2408: sub init_breadcrumbs {
2409: my ($form,$text)=@_;
2410: &Apache::lonhtmlcommon::clear_breadcrumbs();
2411: &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/coursedocs",
2412: text=>&Apache::loncommon::course_type()." Documents",
2413: faq=>273,
2414: bug=>'Instructor Interface',
2415: help => 'Docs_Adding_Course_Doc'});
2416: &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/coursedocs?".$form.'=1',
2417: text=>$text,
2418: faq=>273,
2419: bug=>'Instructor Interface'});
2420: }
2421:
1.75 www 2422: # ================================================================ Main Handler
2423: sub handler {
2424: my $r = shift;
1.82 www 2425: &Apache::loncommon::content_type($r,'text/html');
1.75 www 2426: $r->send_http_header;
2427: return OK if $r->header_only;
1.230 albertel 2428: my $type = &Apache::loncommon::course_type();
1.75 www 2429:
2430: # --------------------------------------------- Initialize help topics for this
1.209 albertel 2431: foreach ('Adding_Course_Doc','Main_Course_Documents',
2432: 'Adding_External_Resource','Navigate_Content',
2433: 'Adding_Folders','Docs_Overview', 'Load_Map',
2434: 'Supplemental','Score_Upload_Form','Adding_Pages',
2435: 'Importing_LON-CAPA_Resource','Uploading_From_Harddrive',
2436: 'Check_Resource_Versions','Verify_Content') {
2437: $help{$_}=&Apache::loncommon::help_open_topic('Docs_'.$_);
2438: }
1.75 www 2439: # Composite help files
2440: $help{'Syllabus'} = &Apache::loncommon::help_open_topic(
2441: 'Docs_About_Syllabus,Docs_Editing_Templated_Pages');
2442: $help{'Simple Page'} = &Apache::loncommon::help_open_topic(
2443: 'Docs_About_Simple_Page,Docs_Editing_Templated_Pages');
1.86 albertel 2444: $help{'Simple Problem'} = &Apache::loncommon::help_open_topic(
2445: 'Option_Response_Simple');
1.75 www 2446: $help{'Bulletin Board'} = &Apache::loncommon::help_open_topic(
2447: 'Docs_About_Bulletin_Board,Docs_Editing_Templated_Pages');
2448: $help{'My Personal Info'} = &Apache::loncommon::help_open_topic(
2449: 'Docs_About_My_Personal_Info,Docs_Editing_Templated_Pages');
1.255 raeburn 2450: $help{'Group Files'} = &Apache::loncommon::help_open_topic('Docs_About_Group_Files');
1.75 www 2451: $help{'Caching'} = &Apache::loncommon::help_open_topic('Caching');
1.142 raeburn 2452:
1.209 albertel 2453: # does this user have privileges to modify docs
2454: my $allowed=&Apache::lonnet::allowed('mdc',$env{'request.course.id'});
2455: if ($allowed && $env{'form.verify'}) {
1.257 www 2456: &init_breadcrumbs('verify','Verify Content');
1.75 www 2457: &verifycontent($r);
1.209 albertel 2458: } elsif ($allowed && $env{'form.listsymbs'}) {
1.257 www 2459: &init_breadcrumbs('listsymbs','List Symbs');
1.208 albertel 2460: &list_symbs($r);
1.247 www 2461: } elsif ($allowed && $env{'form.docslog'}) {
1.257 www 2462: &init_breadcrumbs('docslog','Show Log');
1.247 www 2463: &docs_change_log($r);
1.209 albertel 2464: } elsif ($allowed && $env{'form.versions'}) {
1.257 www 2465: &init_breadcrumbs('versions','Check/Set Resource Versions');
1.75 www 2466: &checkversions($r);
1.209 albertel 2467: } elsif ($allowed && $env{'form.dumpcourse'}) {
1.257 www 2468: &init_breadcrumbs('dumpcourse','Dump '.&Apache::loncommon::course_type().' DOCS to Construction Space');
1.75 www 2469: &dumpcourse($r);
1.209 albertel 2470: } elsif ($allowed && $env{'form.exportcourse'}) {
1.257 www 2471: &init_breadcrumbs('exportcourse','Export '.&Apache::loncommon::course_type().' to IMS');
1.138 raeburn 2472: &exportcourse($r);
1.26 www 2473: } else {
1.7 www 2474: # is this a standard course?
2475:
1.174 albertel 2476: my $standard=($env{'request.course.uri'}=~/^\/uploaded\//);
1.155 raeburn 2477: my $forcestandard = 0;
1.15 www 2478: my $forcesupplement;
2479: my $script='';
1.19 www 2480: my $showdoc=0;
1.142 raeburn 2481: my $containertag;
2482: my $uploadtag;
1.15 www 2483: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.224 albertel 2484: ['folderpath','pagepath',
1.281 albertel 2485: 'pagesymb']);
1.174 albertel 2486: if ($env{'form.folderpath'}) {
2487: my (@folderpath)=split('&',$env{'form.folderpath'});
1.228 www 2488: $env{'form.foldername'}=&unescape(pop(@folderpath));
1.174 albertel 2489: $env{'form.folder'}=pop(@folderpath);
2490: }
2491: if ($env{'form.pagepath'}) {
2492: my (@pagepath)=split('&',$env{'form.pagepath'});
1.228 www 2493: $env{'form.pagename'}=&unescape(pop(@pagepath));
1.174 albertel 2494: $env{'form.folder'}=pop(@pagepath);
1.156 albertel 2495: $containertag = '<input type="hidden" name="pagepath" value="" />'.
2496: '<input type="hidden" name="pagesymb" value="" />';
1.282 ! albertel 2497: $uploadtag = '<input type="hidden" name="pagepath" value="'.&HTML::Entities::encode($env{'form.pagepath'},'<>&"').'" />'.
! 2498: '<input type="hidden" name="pagesymb" value="'.&HTML::Entities::encode($env{'form.pagesymb'},'<>&"').'" />';
1.142 raeburn 2499: }
1.21 www 2500: if ($r->uri=~/^\/adm\/coursedocs\/showdoc\/(.*)$/) {
1.127 albertel 2501: $showdoc='/'.$1;
1.21 www 2502: }
2503: unless ($showdoc) { # got called from remote
1.237 albertel 2504: if (($env{'form.folder'}=~/^(?:group|default)_/) ||
1.209 albertel 2505: ($env{'form.folder'} =~ m:^\d+/(pages|sequences)/:)) {
1.155 raeburn 2506: $forcestandard = 1;
2507: }
1.174 albertel 2508: $forcesupplement=($env{'form.folder'}=~/^supplemental_/);
1.7 www 2509:
1.15 www 2510: if ($allowed) {
2511: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['cmd']);
2512: $script=&Apache::lonratedt::editscript('simple');
2513: }
2514: } else { # got called in sequence from course
2515: $allowed=0;
1.3 www 2516: }
1.4 www 2517:
2518: # get course data
1.174 albertel 2519: my $coursenum=$env{'course.'.$env{'request.course.id'}.'.num'};
2520: my $coursedom=$env{'course.'.$env{'request.course.id'}.'.domain'};
1.4 www 2521:
1.225 albertel 2522: # get personal data
1.174 albertel 2523: my $uname=$env{'user.name'};
2524: my $udom=$env{'user.domain'};
1.245 albertel 2525: my $plainname=&escape(&Apache::loncommon::plainname($uname,$udom));
1.14 www 2526:
1.8 www 2527: # graphics settings
1.4 www 2528:
1.176 albertel 2529: $iconpath = &Apache::loncommon::lonhttpdurl($r->dir_config('lonIconsURL') . "/");
1.8 www 2530:
1.224 albertel 2531: if ($allowed) {
2532: $script .= &editing_js($udom,$uname);
1.171 www 2533: }
1.42 www 2534: # -------------------------------------------------------------------- Body tag
1.224 albertel 2535: $script = '<script type="text/javascript">'."\n".$script."\n".'</script>';
1.229 raeburn 2536: $r->print(&Apache::loncommon::start_page("$type Documents", $script,
1.225 albertel 2537: {'force_register' => $showdoc,}).
1.233 albertel 2538: &Apache::loncommon::help_open_menu('','',273,'RAT'));
1.224 albertel 2539:
1.188 raeburn 2540: my %allfiles = ();
2541: my %codebase = ();
2542: my ($upload_result,$upload_output);
2543: if ($allowed) {
1.264 albertel 2544: if (($env{'form.uploaddoc.filename'}) &&
2545: ($env{'form.cmd'}=~/^upload_(\w+)/)) {
1.188 raeburn 2546: # Process file upload - phase one - upload and parse primary file.
1.190 albertel 2547: $upload_result = &process_file_upload(\$upload_output,$coursenum,
2548: $coursedom,\%allfiles,
1.194 raeburn 2549: \%codebase,$1);
1.188 raeburn 2550: if ($upload_result eq 'phasetwo') {
2551: $r->print($upload_output);
2552: }
2553: } elsif ($env{'form.phasetwo'}) {
2554: my %newname = ();
2555: my %origname = ();
2556: my %attribs = ();
2557: my $updateflag = 0;
2558: my $residx = $env{'form.newidx'};
1.228 www 2559: my $primary_url = &unescape($env{'form.primaryurl'});
1.188 raeburn 2560: # Process file upload - phase two - gather secondary files.
2561: for (my $i=0; $i<$env{'form.phasetwo'}; $i++) {
2562: if ($env{'form.embedded_item_'.$i.'.filename'}) {
2563: my $javacodebase;
2564: $newname{$i} = &process_secondary_uploads(\$upload_output,$coursedom,$coursenum,'embedded_item_',$i,$residx);
1.228 www 2565: $origname{$i} = &unescape($env{'form.embedded_orig_'.$i});
1.188 raeburn 2566: if (exists($env{'form.embedded_codebase_'.$i})) {
1.228 www 2567: $javacodebase = &unescape($env{'form.embedded_codebase_'.$i});
1.188 raeburn 2568: $origname{$i} =~ s#^\Q$javacodebase\E/##;
2569: }
2570: my @attributes = ();
2571: if ($env{'form.embedded_attrib_'.$i} =~ /:/) {
2572: @attributes = split/:/,$env{'form.embedded_attrib_'.$i};
2573: } else {
2574: @attributes = ($env{'form.embedded_attrib_'.$i});
2575: }
2576: foreach (@attributes) {
1.228 www 2577: push(@{$attribs{$i}},&unescape($_));
1.188 raeburn 2578: }
2579: if ($javacodebase) {
2580: $codebase{$i} = $javacodebase;
2581: $codebase{$i} =~ s#/$##;
2582: $updateflag = 1;
2583: }
2584: }
2585: unless ($newname{$i} eq $origname{$i}) {
2586: $updateflag = 1;
2587: }
2588: }
2589: # Process file upload - phase three - modify primary file
2590: if ($updateflag) {
2591: my ($content,$rtncode);
2592: my $updateflag = 0;
2593: my $getstatus = &Apache::lonnet::getuploaded('GET',$primary_url,$coursedom,$coursenum,\$content,\$rtncode);
2594: if ($getstatus eq 'ok') {
2595: foreach my $item (keys %newname) {
2596: if ($newname{$item} ne $origname{$item}) {
2597: my $attrib_regexp = '';
2598: if (@{$attribs{$item}} > 1) {
2599: $attrib_regexp = join('|',@{$attribs{$item}});
2600: } else {
2601: $attrib_regexp = $attribs{$item}[0];
2602: }
2603: if ($content =~ m#($attrib_regexp\s*=\s*['"]?)\Q$origname{$item}\E(['"]?)#) {
2604: }
2605: $content =~ s#($attrib_regexp\s*=\s*['"]?)\Q$origname{$item}\E(['"]?)#$1$newname{$item}$2#gi;
2606: }
2607: if (exists($codebase{$item})) {
1.224 albertel 2608: $content =~ s/(codebase\s*=\s*["']?)\Q$codebase{$item}\E(["']?)/$1.$2/i; #' stupid emacs
1.188 raeburn 2609: }
2610: }
2611: # Save edited file.
2612: my $saveresult;
2613: my $docuname=$env{'course.'.$env{'request.course.id'}.'.num'};
2614: my $docudom=$env{'course.'.$env{'request.course.id'}.'.domain'};
1.191 raeburn 2615: my $url = &Apache::lonnet::store_edited_file($primary_url,$content,$docudom,$docuname,\$saveresult);
1.188 raeburn 2616: } else {
2617: &Apache::lonnet::logthis('retrieval of uploaded file - '.$primary_url.' - for editing, failed: '.$getstatus);
2618: }
2619: }
2620: }
2621: }
2622:
2623: unless ($showdoc || $upload_result eq 'phasetwo') {
1.81 www 2624: # -----------------------------------------------------------------------------
2625: my %lt=&Apache::lonlocal::texthash(
1.229 raeburn 2626: 'uplm' => 'Upload a new main '.lc($type).' document',
2627: 'upls' => 'Upload a new supplemental '.lc($type).' document',
1.168 www 2628: 'impp' => 'Import a document',
2629: 'pubd' => 'Published documents',
1.181 www 2630: 'copm' => 'All documents out of a published map into this folder',
1.81 www 2631: 'spec' => 'Special documents',
2632: 'upld' => 'Upload Document',
2633: 'srch' => 'Search',
2634: 'impo' => 'Import',
1.232 www 2635: 'book' => 'Import Bookmarks',
1.81 www 2636: 'selm' => 'Select Map',
2637: 'load' => 'Load Map',
1.186 www 2638: 'reco' => 'Recover Deleted Resources',
1.81 www 2639: 'newf' => 'New Folder',
1.142 raeburn 2640: 'newp' => 'New Composite Page',
1.81 www 2641: 'extr' => 'External Resource',
2642: 'syll' => 'Syllabus',
2643: 'navc' => 'Navigate Contents',
2644: 'sipa' => 'Simple Page',
2645: 'sipr' => 'Simple Problem',
1.219 www 2646: 'drbx' => 'Drop Box',
1.81 www 2647: 'scuf' => 'Score Upload Form',
2648: 'bull' => 'Bulletin Board',
1.96 sakharuk 2649: 'mypi' => 'My Personal Info',
1.255 raeburn 2650: 'grpo' => 'Group Files',
1.101 www 2651: 'abou' => 'About User',
1.110 raeburn 2652: 'imsf' => 'Import IMS package',
1.96 sakharuk 2653: 'file' => 'File',
2654: 'title' => 'Title',
1.188 raeburn 2655: 'comment' => 'Comment',
2656: 'parse' => 'If HTML file, upload embedded images/multimedia files'
1.81 www 2657: );
2658: # -----------------------------------------------------------------------------
1.42 www 2659: if ($allowed) {
1.281 albertel 2660: &update_paste_buffer($coursenum,$coursedom);
1.74 www 2661: my $dumpbut=&dumpbutton();
1.138 raeburn 2662: my $exportbut=&exportbutton();
1.88 www 2663: my %lt=&Apache::lonlocal::texthash(
2664: 'vc' => 'Verify Content',
2665: 'cv' => 'Check/Set Resource Versions',
1.208 albertel 2666: 'ls' => 'List Symbs',
1.247 www 2667: 'sl' => 'Show Log'
1.88 www 2668: );
1.118 albertel 2669:
1.174 albertel 2670: my $folderpath=$env{'form.folderpath'};
1.118 albertel 2671: if (!$folderpath) {
1.174 albertel 2672: if ($env{'form.folder'} eq '' ||
2673: $env{'form.folder'} eq 'supplemental') {
1.118 albertel 2674: $folderpath='default&'.
1.230 albertel 2675: &escape(&mt('Main '.$type.' Documents'));
1.118 albertel 2676: }
2677: }
1.174 albertel 2678: unless ($env{'form.pagepath'}) {
1.142 raeburn 2679: $containertag = '<input type="hidden" name="folderpath" value="" />';
1.282 ! albertel 2680: $uploadtag = '<input type="hidden" name="folderpath" value="'.&HTML::Entities::encode($folderpath,'<>&"').'" />';
1.142 raeburn 2681: }
2682:
1.42 www 2683: $r->print(<<ENDCOURSEVERIFY);
1.36 www 2684: <form name="renameform" method="post" action="/adm/coursedocs">
2685: <input type="hidden" name="title" />
2686: <input type="hidden" name="cmd" />
1.168 www 2687: <input type="hidden" name="markcopy" />
1.281 albertel 2688: <input type="hidden" name="copyfolder" />
1.142 raeburn 2689: $containertag
1.36 www 2690: </form>
1.39 www 2691: <form name="simpleedit" method="post" action="/adm/coursedocs">
1.256 albertel 2692: <input type="hidden" name="importdetail" value="" />
1.142 raeburn 2693: $uploadtag
1.39 www 2694: </form>
1.26 www 2695: <form action="/adm/coursedocs" method="post" name="courseverify">
1.74 www 2696: <table bgcolor="#AAAAAA" width="100%" cellspacing="4" cellpadding="4">
2697: <tr><td bgcolor="#DDDDCC">
1.130 www 2698: <input type="submit" name="verify" value="$lt{'vc'}" />$help{'Verify_Content'}
1.74 www 2699: </td><td bgcolor="#DDDDCC">
1.130 www 2700: <input type="submit" name="versions" value="$lt{'cv'}" />$help{'Check_Resource_Versions'}
1.74 www 2701: $dumpbut
1.138 raeburn 2702: $exportbut
1.218 albertel 2703: </td><td bgcolor="#DDDDCC">
1.208 albertel 2704: <input type="submit" name="listsymbs" value="$lt{'ls'}" />
1.247 www 2705: </td><td bgcolor="#DDDDCC">
1.260 www 2706: <input type="hidden" name="folder" value="$env{'form.folder'}" />
1.247 www 2707: <input type="submit" name="docslog" value="$lt{'sl'}" />
1.218 albertel 2708: </td></tr></table>
1.25 www 2709: </form>
2710: ENDCOURSEVERIFY
1.74 www 2711: $r->print(&Apache::loncommon::help_open_topic('Docs_Adding_Course_Doc',
1.230 albertel 2712: &mt('Editing the Table of Contents for your '.$type)));
1.25 www 2713: }
1.17 www 2714: # --------------------------------------------------------- Standard documents
1.43 www 2715: $r->print('<table border=2 cellspacing=4 cellpadding=4>');
1.7 www 2716: if (($standard) && ($allowed) && (!$forcesupplement)) {
1.116 albertel 2717: $r->print('<tr><td bgcolor="#BBBBBB">');
2718: # '<h2>'.&mt('Main Course Documents').
2719: # ($allowed?' '.$help{'Main_Course_Documents'}:'').'</h2>');
1.174 albertel 2720: my $folder=$env{'form.folder'};
1.117 albertel 2721: if ($folder eq '' || $folder eq 'supplemental') {
1.112 raeburn 2722: $folder='default';
1.230 albertel 2723: $env{'form.folderpath'}='default&'.&escape(&mt('Main '.$type.' Documents'));
1.112 raeburn 2724: }
1.51 www 2725: my $postexec='';
2726: if ($folder eq 'default') {
2727: $r->print('<script>this.window.name="loncapaclient";</script>');
2728: } else {
1.117 albertel 2729: #$postexec='self.close();';
1.51 www 2730: }
1.40 www 2731: $hadchanges=0;
1.188 raeburn 2732: &editor($r,$coursenum,$coursedom,$folder,$allowed,$upload_output);
1.40 www 2733: if ($hadchanges) {
1.136 albertel 2734: &mark_hash_old()
1.40 www 2735: }
1.136 albertel 2736: &changewarning($r,$postexec);
1.16 www 2737: my $folderseq='/uploaded/'.$coursedom.'/'.$coursenum.'/default_'.time.
2738: '.sequence';
1.142 raeburn 2739: my $pageseq = '/uploaded/'.$coursedom.'/'.$coursenum.'/default_'.time.
2740: '.page';
1.186 www 2741: my $container='sequence';
2742: if ($env{'form.pagepath'}) {
2743: $container='page';
2744: }
2745: my $readfile='/uploaded/'.$coursedom.'/'.$coursenum.'/'.$folder.'.'.$container;
1.8 www 2746: $r->print(<<ENDFORM);
1.43 www 2747: <table cellspacing=4 cellpadding=4><tr>
1.81 www 2748: <th bgcolor="#DDDDDD">$lt{'uplm'}</th>
2749: <th bgcolor="#DDDDDD">$lt{'impp'}</th>
2750: <th bgcolor="#DDDDDD">$lt{'spec'}</th>
1.11 www 2751: </tr>
1.16 www 2752: <tr><td bgcolor="#DDDDDD">
1.96 sakharuk 2753: $lt{'file'}:<br />
1.182 albertel 2754: <form name="uploaddocument" action="/adm/coursedocs" method="post" enctype="multipart/form-data">
1.59 www 2755: <input type="file" name="uploaddoc" size="40">
1.8 www 2756: <br />
1.96 sakharuk 2757: $lt{'title'}:<br />
1.11 www 2758: <input type="text" size="50" name="comment">
1.142 raeburn 2759: $uploadtag
1.10 www 2760: <input type="hidden" name="cmd" value="upload_default">
1.188 raeburn 2761: <br />
2762: <nobr>
1.190 albertel 2763: <label>$lt{'parse'}?
1.188 raeburn 2764: <input type="checkbox" name="parserflag" />
1.190 albertel 2765: </label>
1.188 raeburn 2766: </nobr>
2767: <br />
2768: <br />
1.129 albertel 2769: <nobr>
1.81 www 2770: <input type="submit" value="$lt{'upld'}">
1.60 albertel 2771: $help{'Uploading_From_Harddrive'}
1.58 albertel 2772: </nobr>
1.60 albertel 2773: </form>
1.11 www 2774: </td>
1.16 www 2775: <td bgcolor="#DDDDDD">
1.39 www 2776: <form action="/adm/coursedocs" method="post" name="simpleeditdefault">
1.168 www 2777: $lt{'pubd'}<br />
1.142 raeburn 2778: $uploadtag
1.232 www 2779: <input type=button onClick="javascript:groupsearch()" value="$lt{'srch'}" />
2780: <br />
1.58 albertel 2781: <nobr>
1.232 www 2782: <input type=button onClick="javascript:groupimport();" value="$lt{'impo'}" />
1.58 albertel 2783: $help{'Importing_LON-CAPA_Resource'}
2784: </nobr>
1.232 www 2785: <br />
2786: <input type=button onClick="javascript:groupopen(0,1,1);" value="$lt{'book'}" />
1.59 www 2787: <p>
2788: <hr />
1.181 www 2789: $lt{'copm'}<br />
1.282 ! albertel 2790: <input type="text" size="40" name="importmap" /><br />
1.68 bowersj2 2791: <nobr><input type=button
1.52 www 2792: onClick="javascript:openbrowser('simpleeditdefault','importmap','sequence,page','')"
1.282 ! albertel 2793: value="$lt{'selm'}" /> <input type="submit" name="loadmap" value="$lt{'load'}" />
1.68 bowersj2 2794: $help{'Load_Map'}</nobr>
1.59 www 2795: </p>
1.52 www 2796: </form>
1.186 www 2797: <hr />
2798: <form action="/adm/groupsort" method="post" name="recover">
1.232 www 2799: <input type="button" name="recovermap" onClick="javascript:groupopen('$readfile',1,0)" value="$lt{'reco'}" />
1.186 www 2800: </form>
1.142 raeburn 2801: ENDFORM
1.174 albertel 2802: unless ($env{'form.pagepath'}) {
1.168 www 2803: $r->print(<<ENDFORM);
2804: <hr />
2805: <form action="/adm/coursedocs" method="post" name="newext">
2806: $uploadtag
1.256 albertel 2807: <input type="hidden" name="importdetail" value="" />
1.168 www 2808: <nobr>
2809: <input name="newext" type="button" onClick="javascript:makenewext('newext');"
2810: value="$lt{'extr'}" /> $help{'Adding_External_Resource'}
2811: </nobr>
2812: </form>
1.214 www 2813: <br /><form action="/adm/imsimportdocs" method="post" name="ims">
1.168 www 2814: <input type="hidden" name="folder" value="$folder" />
2815: <input name="imsimport" type="button" value="$lt{'imsf'}" onClick="javascript:makeims();" />
2816: </form>
2817: ENDFORM
2818: }
2819: $r->print('</td><td bgcolor="#DDDDDD">');
1.174 albertel 2820: unless ($env{'form.pagepath'}) {
1.282 ! albertel 2821: my $path = &HTML::Entities::encode($env{'form.folderpath'},'<>&"');
1.142 raeburn 2822: $r->print(<<ENDFORM);
1.214 www 2823: <br /><form action="/adm/coursedocs" method="post" name="newfolder">
1.282 ! albertel 2824: <input type="hidden" name="folderpath" value="$path" />
1.256 albertel 2825: <input type="hidden" name="importdetail" value="" />
1.58 albertel 2826: <nobr>
1.16 www 2827: <input name="newfolder" type="button"
2828: onClick="javascript:makenewfolder(this.form,'$folderseq');"
1.81 www 2829: value="$lt{'newf'}" />$help{'Adding_Folders'}
1.58 albertel 2830: </nobr>
1.11 www 2831: </form>
1.214 www 2832: <br /><form action="/adm/coursedocs" method="post" name="newpage">
1.282 ! albertel 2833: <input type="hidden" name="folderpath" value="$path" />
1.256 albertel 2834: <input type="hidden" name="importdetail" value="" />
1.142 raeburn 2835: <nobr>
2836: <input name="newpage" type="button"
2837: onClick="javascript:makenewpage(this.form,'$pageseq');"
2838: value="$lt{'newp'}" />$help{'Adding_Pages'}
2839: </nobr>
2840: </form>
1.214 www 2841: <br /><form action="/adm/coursedocs" method="post" name="newsyl">
1.142 raeburn 2842: $uploadtag
1.256 albertel 2843: <input type="hidden" name="importdetail"
2844: value="Syllabus=/public/$coursedom/$coursenum/syllabus" />
1.58 albertel 2845: <nobr>
1.81 www 2846: <input name="newsyl" type="submit" value="$lt{'syll'}" />
1.65 bowersj2 2847: $help{'Syllabus'}
1.58 albertel 2848: </nobr>
2849: </form>
1.214 www 2850: <br /><form action="/adm/coursedocs" method="post" name="newnav">
1.142 raeburn 2851: $uploadtag
1.256 albertel 2852: <input type="hidden" name="importdetail"
2853: value="Navigate Content=/adm/navmaps" />
1.58 albertel 2854: <nobr>
1.81 www 2855: <input name="newnav" type="submit" value="$lt{'navc'}" />
1.47 www 2856: $help{'Navigate_Content'}
1.58 albertel 2857: </nobr>
1.22 www 2858: </form>
1.214 www 2859: <br /><form action="/adm/coursedocs" method="post" name="newsmppg">
1.142 raeburn 2860: $uploadtag
1.256 albertel 2861: <input type="hidden" name="importdetail" value="" />
1.58 albertel 2862: <nobr>
1.81 www 2863: <input name="newsmppg" type="button" value="$lt{'sipa'}"
1.65 bowersj2 2864: onClick="javascript:makesmppage();" /> $help{'Simple Page'}
1.58 albertel 2865: </nobr>
1.55 www 2866: </form>
1.214 www 2867: <br /><form action="/adm/coursedocs" method="post" name="newsmpproblem">
1.142 raeburn 2868: $uploadtag
1.256 albertel 2869: <input type="hidden" name="importdetail" value="" />
1.58 albertel 2870: <nobr>
1.81 www 2871: <input name="newsmpproblem" type="button" value="$lt{'sipr'}"
1.65 bowersj2 2872: onClick="javascript:makesmpproblem();" />$help{'Simple Problem'}
1.62 www 2873: </nobr>
2874: </form>
1.219 www 2875: <br /><form action="/adm/coursedocs" method="post" name="newdropbox">
2876: $uploadtag
1.256 albertel 2877: <input type="hidden" name="importdetail" value="" />
1.219 www 2878: <nobr>
2879: <input name="newdropbox" type="button" value="$lt{'drbx'}"
2880: onClick="javascript:makedropbox();" />
2881: </nobr>
2882: </form>
1.214 www 2883: <br /><form action="/adm/coursedocs" method="post" name="newexamupload">
1.142 raeburn 2884: $uploadtag
1.256 albertel 2885: <input type="hidden" name="importdetail" value="" />
1.62 www 2886: <nobr>
1.81 www 2887: <input name="newexamupload" type="button" value="$lt{'scuf'}"
1.62 www 2888: onClick="javascript:makeexamupload();" />
1.66 bowersj2 2889: $help{'Score_Upload_Form'}
1.58 albertel 2890: </nobr>
1.22 www 2891: </form>
1.214 www 2892: <br /><form action="/adm/coursedocs" method="post" name="newbul">
1.142 raeburn 2893: $uploadtag
1.256 albertel 2894: <input type="hidden" name="importdetail" value="" />
1.58 albertel 2895: <nobr>
1.81 www 2896: <input name="newbulletin" type="button" value="$lt{'bull'}"
1.22 www 2897: onClick="javascript:makebulboard();" />
1.65 bowersj2 2898: $help{'Bulletin Board'}
1.58 albertel 2899: </nobr>
2900: </form>
1.214 www 2901: <br /><form action="/adm/coursedocs" method="post" name="newaboutme">
1.142 raeburn 2902: $uploadtag
1.256 albertel 2903: <input type="hidden" name="importdetail"
2904: value="$plainname=/adm/$udom/$uname/aboutme" />
1.58 albertel 2905: <nobr>
1.81 www 2906: <input name="newaboutme" type="submit" value="$lt{'mypi'}" />
1.65 bowersj2 2907: $help{'My Personal Info'}
1.101 www 2908: </nobr>
2909: </form>
1.214 www 2910: <br /><form action="/adm/coursedocs" method="post" name="newaboutsomeone">
1.142 raeburn 2911: $uploadtag
1.256 albertel 2912: <input type="hidden" name="importdetail" value="" />
1.101 www 2913: <nobr>
2914: <input name="newaboutsomeone" type="button" value="$lt{'abou'}"
2915: onClick="javascript:makeabout();" />
1.110 raeburn 2916: </nobr>
1.182 albertel 2917: </form>
1.255 raeburn 2918: <br /><form action="/adm/coursedocs" method="post" name="newgroupfiles">
2919: $uploadtag
1.256 albertel 2920: <input type="hidden" name="importdetail"
2921: value="Group Files=/adm/$coursedom/$coursenum/aboutme" />
1.255 raeburn 2922: <nobr>
2923: <input name="newgroupfiles" type="submit" value="$lt{'grpo'}" />
2924: $help{'Group Files'}
2925: </nobr>
2926: </form>
1.142 raeburn 2927: ENDFORM
2928: }
1.174 albertel 2929: if ($env{'form.pagepath'}) {
1.142 raeburn 2930: $r->print(<<ENDBLOCK);
2931: <form action="/adm/coursedocs" method="post" name="newsmpproblem">
2932: $uploadtag
1.256 albertel 2933: <input type="hidden" name="importdetail" value="" />
1.142 raeburn 2934: <nobr>
2935: <input name="newsmpproblem" type="button" value="$lt{'sipr'}"
2936: onClick="javascript:makesmpproblem();" />$help{'Simple Problem'}
2937: </nobr>
2938: </form>
1.214 www 2939: <br /><form action="/adm/coursedocs" method="post" name="newexamupload">
1.142 raeburn 2940: $uploadtag
1.256 albertel 2941: <input type="hidden" name="importdetail" value="" />
1.142 raeburn 2942: <nobr>
2943: <input name="newexamupload" type="button" value="$lt{'scuf'}"
2944: onClick="javascript:makeexamupload();" />
2945: $help{'Score_Upload_Form'}
2946: </nobr>
1.182 albertel 2947: </form>
1.142 raeburn 2948: ENDBLOCK
2949: }
2950: $r->print('</td></tr>'."\n".
2951: '</table>');
1.24 www 2952: $r->print('</td></tr>');
1.7 www 2953: }
2954: # ----------------------------------------------------- Supplemental documents
2955: if (!$forcestandard) {
1.116 albertel 2956: $r->print('<tr><td bgcolor="#BBBBBB">');
2957: # '<h2>'.&mt('Supplemental Course Documents').
2958: # ($allowed?' '.$help{'Supplemental'}:'').'</h2>');
1.174 albertel 2959: my $folder=$env{'form.folder'};
1.117 albertel 2960: unless ($folder=~/^supplemental/) {
1.116 albertel 2961: $folder='supplemental';
1.117 albertel 2962: }
2963: if ($folder =~ /^supplemental$/ &&
1.174 albertel 2964: $env{'form.folderpath'} =~ /^default\&/) {
2965: $env{'form.folderpath'}='supplemental&'.
1.230 albertel 2966: &escape(&mt('Supplemental '.$type.' Documents'));
1.116 albertel 2967: }
1.7 www 2968: &editor($r,$coursenum,$coursedom,$folder,$allowed);
1.8 www 2969: if ($allowed) {
1.282 ! albertel 2970: my $folderseq=
! 2971: '/uploaded/'.$coursedom.'/'.$coursenum.'/supplemental_'.time.
! 2972: '.sequence';
1.17 www 2973:
1.282 ! albertel 2974: my $path = &HTML::Entities::encode($env{'form.folderpath'},'<>&"');
! 2975: $r->print(<<ENDSUPFORM);
1.43 www 2976: <table cellspacing=4 cellpadding=4><tr>
1.81 www 2977: <th bgcolor="#DDDDDD">$lt{'upls'}</th>
2978: <th bgcolor="#DDDDDD">$lt{'spec'}</th>
1.17 www 2979: </tr>
2980: <tr><td bgcolor="#DDDDDD">
1.10 www 2981: <form action="/adm/coursedocs" method="post" enctype="multipart/form-data">
1.59 www 2982: <input type="file" name="uploaddoc" size="40">
1.196 raeburn 2983: <br />
2984: <br />
2985: <nobr>
2986: <label>$lt{'parse'}?
2987: <input type="checkbox" name="parserflag" />
2988: </label>
2989: </nobr>
2990: <br /><br />
2991: $lt{'comment'}:<br />
1.4 www 2992: <textarea cols=50 rows=4 name='comment'>
2993: </textarea>
1.115 albertel 2994: <br />
1.282 ! albertel 2995: <input type="hidden" name="folderpath" value="$path" />
1.10 www 2996: <input type="hidden" name="cmd" value="upload_supplemental">
1.58 albertel 2997: <nobr>
1.81 www 2998: <input type="submit" value="$lt{'upld'}">
1.58 albertel 2999: $help{'Uploading_From_Harddrive'}
3000: </nobr>
3001: </form>
1.17 www 3002: </td>
3003: <td bgcolor="#DDDDDD">
1.18 www 3004: <form action="/adm/coursedocs" method="post" name="supnewfolder">
1.282 ! albertel 3005: <input type="hidden" name="folderpath" value="$path" />
1.256 albertel 3006: <input type="hidden" name="importdetail" value="" />
1.58 albertel 3007: <nobr>
1.17 www 3008: <input name="newfolder" type="button"
3009: onClick="javascript:makenewfolder(this.form,'$folderseq');"
1.81 www 3010: value="$lt{'newf'}" /> $help{'Adding_Folders'}
1.58 albertel 3011: </nobr>
1.17 www 3012: </form>
1.214 www 3013: <br /><form action="/adm/coursedocs" method="post" name="supnewext">
1.282 ! albertel 3014: <input type="hidden" name="folderpath" value="$path" />
1.256 albertel 3015: <input type="hidden" name="importdetail" value="" />
1.58 albertel 3016: <nobr>
1.18 www 3017: <input name="newext" type="button"
3018: onClick="javascript:makenewext('supnewext');"
1.81 www 3019: value="$lt{'extr'}" /> $help{'Adding_External_Resource'}
1.58 albertel 3020: </nobr>
1.17 www 3021: </form>
1.214 www 3022: <br /><form action="/adm/coursedocs" method="post" name="supnewsyl">
1.282 ! albertel 3023: <input type="hidden" name="folderpath" value="$path" />
1.256 albertel 3024: <input type="hidden" name="importdetail"
3025: value="Syllabus=/public/$coursedom/$coursenum/syllabus" />
1.58 albertel 3026: <nobr>
1.81 www 3027: <input name="newsyl" type="submit" value="$lt{'syll'}" />
1.65 bowersj2 3028: $help{'Syllabus'}
1.58 albertel 3029: </nobr>
3030: </form>
1.214 www 3031: <br /><form action="/adm/coursedocs" method="post" name="subnewaboutme">
1.282 ! albertel 3032: <input type="hidden" name="folderpath" value="$path" />
1.256 albertel 3033: <input type="hidden" name="importdetail"
3034: value="$plainname=/adm/$udom/$uname/aboutme" />
1.58 albertel 3035: <nobr>
1.81 www 3036: <input name="newaboutme" type="submit" value="$lt{'mypi'}" />
1.65 bowersj2 3037: $help{'My Personal Info'}
1.58 albertel 3038: </nobr>
3039: </form>
1.17 www 3040: </td></tr>
1.24 www 3041: </table></td></tr>
1.8 www 3042: ENDSUPFORM
3043: }
1.7 www 3044: }
1.18 www 3045: if ($allowed) {
1.182 albertel 3046: $r->print('<form method="POST" name="extimport" action="/adm/coursedocs"><input type="hidden" name="title" /><input type="hidden" name="url" /><input type="hidden" name="useform" /></form>');
1.18 www 3047: }
1.24 www 3048: $r->print('</table>');
1.19 www 3049: } else {
1.188 raeburn 3050: unless ($upload_result eq 'phasetwo') {
1.19 www 3051: # -------------------------------------------------------- This is showdoc mode
1.188 raeburn 3052: $r->print("<h1>".&mt('Uploaded Document').' - '.
1.141 albertel 3053: &Apache::lonnet::gettitle($r->uri).'</h1><p>'.
1.81 www 3054: &mt('It is recommended that you use an up-to-date virus scanner before handling this file.')."</p><p><table>".
1.188 raeburn 3055: &entryline(0,&mt("Click to download or use your browser's Save Link function"),$showdoc).'</table></p>');
3056: }
1.19 www 3057: }
1.26 www 3058: }
1.224 albertel 3059: $r->print(&Apache::loncommon::end_page());
1.26 www 3060: return OK;
1.1 www 3061: }
3062:
1.224 albertel 3063:
3064: sub editing_js {
3065: my ($udom,$uname) = @_;
3066: my $now = time();
3067:
3068: return <<ENDNEWSCRIPT;
3069: function makenewfolder(targetform,folderseq) {
3070: var foldername=prompt('Name of New Folder','New Folder');
3071: if (foldername) {
1.236 albertel 3072: targetform.importdetail.value=escape(foldername)+"="+folderseq;
1.224 albertel 3073: targetform.submit();
3074: }
3075: }
3076:
3077: function makenewpage(targetform,folderseq) {
3078: var pagename=prompt('Name of New Page','New Page');
3079: if (pagename) {
1.236 albertel 3080: targetform.importdetail.value=escape(pagename)+"="+folderseq;
1.224 albertel 3081: targetform.submit();
3082: }
3083: }
3084:
3085: function makenewext(targetname) {
3086: this.document.forms.extimport.useform.value=targetname;
3087: window.open('/adm/rat/extpickframe.html');
3088: }
3089:
3090: function makeexamupload() {
3091: var title=prompt('Listed Title for the Uploaded Score');
3092: if (title) {
3093: this.document.forms.newexamupload.importdetail.value=
1.236 albertel 3094: escape(title)+'=/res/lib/templates/examupload.problem';
1.224 albertel 3095: this.document.forms.newexamupload.submit();
3096: }
3097: }
3098:
3099: function makesmppage() {
3100: var title=prompt('Listed Title for the Page');
3101: if (title) {
3102: this.document.forms.newsmppg.importdetail.value=
1.236 albertel 3103: escape(title)+'=/adm/$udom/$uname/$now/smppg';
1.224 albertel 3104: this.document.forms.newsmppg.submit();
3105: }
3106: }
3107:
3108: function makesmpproblem() {
3109: var title=prompt('Listed Title for the Problem');
3110: if (title) {
3111: this.document.forms.newsmpproblem.importdetail.value=
1.236 albertel 3112: escape(title)+'=/res/lib/templates/simpleproblem.problem';
1.224 albertel 3113: this.document.forms.newsmpproblem.submit();
3114: }
3115: }
3116:
3117: function makedropbox() {
3118: var title=prompt('Listed Title for the Drop Box');
3119: if (title) {
3120: this.document.forms.newdropbox.importdetail.value=
1.236 albertel 3121: escape(title)+'=/res/lib/templates/DropBox.problem';
1.224 albertel 3122: this.document.forms.newdropbox.submit();
3123: }
3124: }
3125:
3126: function makebulboard() {
3127: var title=prompt('Listed Title for the Bulletin Board');
3128: if (title) {
3129: this.document.forms.newbul.importdetail.value=
1.236 albertel 3130: escape(title)+'=/adm/$udom/$uname/$now/bulletinboard';
1.224 albertel 3131: this.document.forms.newbul.submit();
3132: }
3133: }
3134:
3135: function makeabout() {
1.236 albertel 3136: var user=prompt("Enter user:domain for User's 'About Me' Page");
1.224 albertel 3137: if (user) {
3138: var comp=new Array();
1.236 albertel 3139: comp=user.split(':');
1.224 albertel 3140: if ((typeof(comp[0])!=undefined) && (typeof(comp[1])!=undefined)) {
3141: if ((comp[0]) && (comp[1])) {
3142: this.document.forms.newaboutsomeone.importdetail.value=
1.236 albertel 3143: 'About '+escape(user)+'=/adm/'+comp[1]+'/'+comp[0]+'/aboutme';
1.224 albertel 3144: this.document.forms.newaboutsomeone.submit();
3145: } else {
1.236 albertel 3146: alert("Not a valid user:domain");
1.224 albertel 3147: }
3148: } else {
1.236 albertel 3149: alert("Please enter both user and domain in the format user:domain");
1.224 albertel 3150: }
3151: }
3152: }
3153:
3154: function makeims() {
3155: var caller = document.forms.ims.folder.value;
3156: var newlocation = "/adm/imsimportdocs?folder="+caller+"&phase=one";
3157: newWindow = window.open("","IMSimport","HEIGHT=700,WIDTH=750,scrollbars=yes");
3158: newWindow.location.href = newlocation;
3159: }
3160:
3161:
3162: function finishpick() {
3163: var title=this.document.forms.extimport.title.value;
3164: var url=this.document.forms.extimport.url.value;
3165: var form=this.document.forms.extimport.useform.value;
3166: eval
3167: ('this.document.forms.'+form+'.importdetail.value="'+title+'='+url+
3168: '";this.document.forms.'+form+'.submit();');
3169: }
3170:
3171: function changename(folderpath,index,oldtitle,container,pagesymb) {
3172: var title=prompt('New Title',oldtitle);
3173: if (title) {
1.281 albertel 3174: this.document.forms.renameform.markcopy.value=-1;
1.224 albertel 3175: this.document.forms.renameform.title.value=title;
3176: this.document.forms.renameform.cmd.value='rename_'+index;
3177: if (container == 'sequence') {
3178: this.document.forms.renameform.folderpath.value=folderpath;
3179: }
3180: if (container == 'page') {
3181: this.document.forms.renameform.pagepath.value=folderpath;
3182: this.document.forms.renameform.pagesymb.value=pagesymb;
3183: }
3184: this.document.forms.renameform.submit();
3185: }
3186: }
3187:
3188: function removeres(folderpath,index,oldtitle,container,pagesymb) {
3189: if (confirm('WARNING: Removing a resource makes associated grades and scores inaccessible!\\nRemove "'+oldtitle+'"?')) {
1.281 albertel 3190: this.document.forms.renameform.markcopy.value=-1;
1.224 albertel 3191: this.document.forms.renameform.cmd.value='del_'+index;
3192: if (container == 'sequence') {
3193: this.document.forms.renameform.folderpath.value=folderpath;
3194: }
3195: if (container == 'page') {
3196: this.document.forms.renameform.pagepath.value=folderpath;
3197: this.document.forms.renameform.pagesymb.value=pagesymb;
3198: }
3199: this.document.forms.renameform.submit();
3200: }
3201: }
3202:
1.281 albertel 3203: function cutres(folderpath,index,oldtitle,container,pagesymb,folder) {
1.224 albertel 3204: if (confirm('WARNING: Cutting a resource makes associated grades and scores inaccessible!\\nGrades remain inaccessible if resource is pasted into another folder.\\nCut "'+oldtitle+'"?')) {
3205: this.document.forms.renameform.cmd.value='cut_'+index;
3206: this.document.forms.renameform.markcopy.value=index;
1.281 albertel 3207: this.document.forms.renameform.copyfolder.value=folder+'.'+container;
1.224 albertel 3208: if (container == 'sequence') {
3209: this.document.forms.renameform.folderpath.value=folderpath;
3210: }
3211: if (container == 'page') {
3212: this.document.forms.renameform.pagepath.value=folderpath;
3213: this.document.forms.renameform.pagesymb.value=pagesymb;
3214: }
3215: this.document.forms.renameform.submit();
3216: }
3217: }
3218:
1.281 albertel 3219: function markcopy(folderpath,index,oldtitle,container,pagesymb,folder) {
1.224 albertel 3220: this.document.forms.renameform.markcopy.value=index;
1.281 albertel 3221: this.document.forms.renameform.copyfolder.value=folder+'.'+container;
1.224 albertel 3222: if (container == 'sequence') {
3223: this.document.forms.renameform.folderpath.value=folderpath;
3224: }
3225: if (container == 'page') {
3226: this.document.forms.renameform.pagepath.value=folderpath;
3227: this.document.forms.renameform.pagesymb.value=pagesymb;
3228: }
3229: this.document.forms.renameform.submit();
3230: }
3231:
3232: ENDNEWSCRIPT
3233: }
1.1 www 3234: 1;
3235: __END__
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>