Annotation of loncom/interface/londocs.pm, revision 1.313

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>