Annotation of loncom/publisher/lonpubdir.pm, revision 1.175

1.1       www         1: # The LearningOnline Network with CAPA
1.145     raeburn     2: # Authoring Space Directory Lister
1.16      albertel    3: #
1.175   ! raeburn     4: # $Id: lonpubdir.pm,v 1.174 2022/05/27 04:24:55 raeburn Exp $
1.16      albertel    5: #
                      6: # Copyright Michigan State University Board of Trustees
                      7: #
                      8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                      9: #
                     10: # LON-CAPA is free software; you can redistribute it and/or modify
                     11: # it under the terms of the GNU General Public License as published by
                     12: # the Free Software Foundation; either version 2 of the License, or
                     13: # (at your option) any later version.
                     14: #
                     15: # LON-CAPA is distributed in the hope that it will be useful,
                     16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     18: # GNU General Public License for more details.
                     19: #
                     20: # You should have received a copy of the GNU General Public License
                     21: # along with LON-CAPA; if not, write to the Free Software
                     22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     23: #
                     24: # /home/httpd/html/adm/gpl.txt
                     25: #
                     26: # http://www.lon-capa.org/
1.1       www        27: #
1.17      harris41   28: ###
1.1       www        29: 
                     30: package Apache::lonpubdir;
                     31: 
                     32: use strict;
                     33: use Apache::File;
                     34: use File::Copy;
                     35: use Apache::Constants qw(:common :http :methods);
1.17      harris41   36: use Apache::loncommon();
1.48      www        37: use Apache::lonhtmlcommon();
1.91      www        38: use Apache::londiff();
1.39      www        39: use Apache::lonlocal;
1.50      www        40: use Apache::lonmsg;
1.64      raeburn    41: use Apache::lonmenu;
                     42: use Apache::lonnet;
1.154     raeburn    43: use LONCAPA qw(:DEFAULT :match);
1.1       www        44: 
                     45: sub handler {
                     46: 
1.152     musolffc   47:     my $r=shift;
1.1       www        48: 
1.152     musolffc   49:     # Validate access to the construction space and get username:domain.
1.6       www        50: 
1.153     raeburn    51:     my ($uname,$udom)=&Apache::lonnet::constructaccess($r->uri); 
1.152     musolffc   52:     unless (($uname) && ($udom)) {
                     53:         return HTTP_NOT_ACCEPTABLE;
                     54:     }
1.23      foxr       55: 
1.127     www        56: # ----------------------------------------------------------- Start page output
1.23      foxr       57: 
1.152     musolffc   58:     my $fn=$r->filename;
                     59:     $fn=~s/\/$//;
                     60:     my $thisdisfn=$fn;
1.1       www        61: 
1.152     musolffc   62:     my $docroot=$r->dir_config('lonDocRoot');     # Apache  londocument root.
1.155     raeburn    63:     if ($thisdisfn eq "$docroot/priv/$udom") {
                     64:         if ((-d "/home/$uname/public_html/") && (!-e "$docroot/priv/$udom/$uname")) {
                     65:             my ($version) = ($r->dir_config('lonVersion') =~ /^\'?(\d+\.\d+)\./);
                     66:             &Apache::loncommon::content_type($r,'text/html');
                     67:             $r->send_http_header;
                     68: 
                     69:             &Apache::lonhtmlcommon::clear_breadcrumbs();
1.173     raeburn    70:             $r->print(&Apache::loncommon::start_page('Authoring Space').
1.155     raeburn    71:                       '<div class="LC_error">'.
                     72:                       '<br /><p>'.
                     73:                       &mt('Your Authoring Space is currently in the location used by LON-CAPA version 2.10 and older, but your domain is using a newer LON-CAPA version ([_1]).',$version).'</p>'.
                     74:                       '<p>'.
                     75:                       &mt('Please ask your Domain Coordinator to move your Authoring Space to the new location.').
                     76:                       '</p>'.
                     77:                       '</div>'.
                     78:                       &Apache::loncommon::end_page());
                     79:             return OK;
                     80:         }
                     81:     }
1.152     musolffc   82:     $thisdisfn=~s/^\Q$docroot\E\/priv//;
1.169     raeburn    83: 
1.152     musolffc   84:     my $resdir=$docroot.'/res'.$thisdisfn; # Resource directory
                     85:     my $targetdir='/res'.$thisdisfn; # Publication target directory.
                     86:     my $linkdir='/priv'.$thisdisfn;      # Full URL name of constr space.
                     87: 
1.169     raeburn    88:     my $cstr = 'author';
                     89:     my ($crsauthor,$crstype);
                     90:     if ($env{'request.course.id'}) {
                     91:         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                     92:         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                     93:         if ($thisdisfn =~ m{^/\Q$cdom/$cnum\E}) {
                     94:             $crsauthor = 1;
                     95:             $cstr = 'course';
                     96:             $crstype = &Apache::loncommon::course_type();
                     97:         }
                     98:     }
                     99: 
1.152     musolffc  100:     my %bombs=&Apache::lonmsg::all_url_author_res_msg($uname,$udom);
                    101: 
1.164     musolffc  102:     my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'};
                    103:     my $current_disk_usage = &Apache::lonnet::diskusage($udom,$uname,
                    104:                                 "$londocroot/priv/$udom/$uname"); # expressed in kB
                    105:     my $disk_quota = &Apache::loncommon::get_user_quota($uname,$udom,
1.169     raeburn   106:                                                  $cstr,$crstype); # expressed in MB
1.164     musolffc  107: 
                    108:     # Put out the start of page.
1.173     raeburn   109:     &startpage($r, $uname, $udom, $thisdisfn, $current_disk_usage, $disk_quota, $crsauthor);
1.157     raeburn   110: 
                    111:     if (!-d $fn) {
                    112:         if (-e $fn) {
                    113:             $r->print('<p class="LC_info">'.&mt('Requested item is a file not a directory.').'</p>');
                    114:         } else {
                    115:             $r->print('<p class="LC_info">'.&mt('The requested subdirectory does not exist.').'</p>');
                    116:         }
                    117:         $r->print(&Apache::loncommon::end_page());
                    118:         return OK;
                    119:     }
                    120:     my @files;
                    121:     if (opendir(DIR,$fn)) {
1.158     raeburn   122:         @files = grep(!/^\.+$/,readdir(DIR));
1.157     raeburn   123:         closedir(DIR);
                    124:     } else {
                    125:         $r->print('<p class="LC_error">'.&mt('Could not open directory.').'</p>');
                    126:         $r->print(&Apache::loncommon::end_page());
                    127:         return OK;
                    128:     }
                    129: 
1.164     musolffc  130:     # Put out actions for directory, browse/upload + new file page.
                    131:     &dircontrols($r,$uname,$udom,$thisdisfn, $current_disk_usage, $disk_quota);
1.152     musolffc  132:     &resourceactions($r,$uname,$udom,$thisdisfn); # Put out form used for printing/deletion etc.
1.64      raeburn   133: 
1.152     musolffc  134:     my $numdir = 0;
                    135:     my $numres = 0;
1.6       www       136:   
1.160     musolffc  137:     if ((@files == 0) && ($thisdisfn =~ m{^/$match_domain/$match_username})) {
                    138:         if ($thisdisfn =~ m{^/$match_domain/$match_username$}) {
                    139:             $r->print('<p class="LC_info">'.&mt('This Authoring Space is currently empty.').'</p>');
                    140:         } else {
                    141:             $r->print('<p class="LC_info">'.&mt('This subdirectory is currently empty.').'</p>');
                    142:         }
                    143:         $r->print(&Apache::loncommon::end_page());
                    144:         return OK;
                    145:     }
                    146: 
1.152     musolffc  147:     # Retrieving value for "sortby" and "sortorder" from QUERY_STRING
                    148:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
                    149:         ['sortby','sortorder']);
                    150: 
                    151:     # Sort by name as default, not reversed
                    152:     if (! exists($env{'form.sortby'})) { $env{'form.sortby'} = 'filename' }
                    153:     if (! exists($env{'form.sortorder'})) { $env{'form.sortorder'} = '' }
                    154:     my $sortby = $env{'form.sortby'};
                    155:     my $sortorder = $env{'form.sortorder'};
                    156: 
1.160     musolffc  157:     # Order in which columns are displayed from left to right
                    158:     my @order = ('filetype','actions','filename','title',
                    159:                     'pubstatus','cmtime','size');
                    160: 
                    161:     # Up and down arrows to indicate sort order
                    162:     my @arrows = ('&nbsp;&#9650;','&nbsp;&#9660;','');
                    163: 
                    164:     # Default sort order and column title
                    165:     my %columns = (
                    166:         filetype =>     {
                    167:                             order => 'ascending',
                    168:                             text  => &mt('Type'),
                    169:                         },
                    170:         actions =>      {
                    171:                             # Not sortable
                    172:                             text  => &mt('Actions'),
                    173:                         },
                    174:         filename =>     {
                    175:                             order => 'ascending',
                    176:                             text  => &mt('Name'),
                    177:                         },
                    178:         title =>        {
                    179:                             order => 'ascending',
                    180:                             text  => &mt('Title'),
                    181:                         },
                    182:         pubstatus =>    {
                    183:                             order => 'ascending',
                    184:                             text  => &mt('Status'),
                    185:                             colspan => '2',
                    186:                         },
                    187:         cmtime =>       {
                    188:                             order => 'descending',
                    189:                             text  => &mt('Last Modified'),
                    190:                         },
                    191:         size =>         {
                    192:                             order => 'ascending',
                    193:                             text  => &mt('Size').' (kB)',
                    194:                         },
                    195:     ); 
                    196: 
                    197:     # Print column headers
                    198:     my $output = '';
                    199:     foreach my $key (@order) {
                    200:         my $idx;
                    201:         # Append an up or down arrow to sorted column
                    202:         if ($sortby eq $key) {
                    203:             $idx = ($columns{$key}{order} eq 'ascending') ? 0:1;
                    204:             if ($sortorder eq 'rev') { $idx ++; }
                    205:             $idx = $idx%2;
                    206:         } else { $idx = 2; } # No arrow if column is not sorted
                    207:         $output .= (($columns{$key}{order}) ?
                    208:             '<th'.($columns{$key}{colspan} ? ' colspan="'.$columns{$key}{colspan}.'"' : '')
1.162     golterma  209:             .'><a href="'.$linkdir.'/?sortby='.$key.'&amp;sortorder='
1.160     musolffc  210:             .((($sortby eq $key) && ($sortorder ne 'rev')) ? 'rev' : '').'">'
                    211:             .$columns{$key}{text}.$arrows[$idx].'</a></th>' :
                    212:             '<th>'.$columns{$key}{text}.'</th>');
1.154     raeburn   213:     }
1.161     golterma  214: 
1.162     golterma  215: my $result = "<script type=\"text/javascript\">
1.161     golterma  216:     sessionStorage.setItem('CSTRcache','".&prepareJsonData($uname,$udom,$thisdisfn)."');
                    217:     localStorage.setItem('CSTRtrans', '".&prepareJsonTranslations()."');
                    218: </script>";
                    219:     $r->print($result);
                    220: 
                    221:     $r->print('<div id="currentFolder">'.&Apache::loncommon::start_data_table()
1.162     golterma  222:         .'<tr><th colspan="8" id="searchtitle" style="display:none"></th></tr>'
1.160     musolffc  223:         .&Apache::loncommon::start_data_table_header_row() . $output
1.152     musolffc  224:         .&Apache::loncommon::end_data_table_header_row()
                    225:     );
                    226: 
                    227:     my $dirptr=16384;		# Mask indicating a directory in stat.cmode.
                    228:     my $filehash = {};
                    229:     foreach my $filename (@files) {
1.159     musolffc  230:         # Skip .DS_Store, .DAV and hidden files
1.152     musolffc  231:         my ($extension) = ($filename=~/\.(\w+)$/);
1.156     raeburn   232:         next if (($filename eq '.DS_Store')
1.159     musolffc  233:                 || ($filename eq '.DAV')
1.156     raeburn   234:                 || (&Apache::loncommon::fileembstyle($extension) eq 'hdn')
                    235:                 || ($filename =~ /^\._/));
1.152     musolffc  236: 
                    237:         my ($cmode,$csize,$cmtime)=(stat($fn.'/'.$filename))[2,7,9];
                    238:         my $linkfilename = &HTML::Entities::encode('/priv'.$thisdisfn.'/'.$filename,'<>&"');
                    239:         # Identify type of file according to icon used
                    240:         my ($filetype) = (&Apache::loncommon::icon($filename) =~ m{/(\w+).gif$}); 
                    241:         my $cstr_dir = $r->dir_config('lonDocRoot').'/priv'.$thisdisfn;
                    242:         my $meta_same = &isMetaSame($cstr_dir, $resdir, $filename);
                    243:         
                    244:         # Store size, title, and status for files but not directories
                    245:         my $size = (!($cmode&$dirptr)) ? $csize/1024. : 0;
                    246:         my ($status, $pubstatus, $title, $fulltitle);
                    247:         if (!($cmode&$dirptr)) {
                    248:             ($status, $pubstatus) = &getStatus($resdir, $targetdir, $cstr_dir, 
                    249:                 $filename, $linkfilename, $cmtime, $meta_same);
                    250:             ($fulltitle, $title) = &getTitle($resdir, $targetdir, $filename, 
                    251:                                         $linkfilename, $meta_same, \%bombs);
                    252:         } else {
                    253:             ($status, $pubstatus) = ('','');
                    254:             ($fulltitle, $title) = ('','');
                    255:         }
1.150     musolffc  256: 
1.152     musolffc  257:         # This hash will allow sorting
                    258:         $filehash->{ $filename } = {
                    259:             "cmtime"            => $cmtime,
                    260:             "size"              => $size,
                    261:             "cmode"             => $cmode,
                    262:             "filetype"          => $filetype,
                    263:             "title"             => $title,
                    264:             "fulltitle"         => $fulltitle,
                    265:             "status"            => $status,
                    266:             "pubstatus"         => $pubstatus,
                    267:             "linkfilename"      => $linkfilename,
                    268:         }
                    269:     }
                    270:    
                    271:     my @sorted_files;
                    272:     # Sorting by something other than "Name".  Name is the secondary key.
                    273:     if ($sortby =~ m{cmtime|size}) {    # Numeric fields
                    274:         # First check if order should be reversed
                    275:         if ($sortorder eq "rev") {
                    276:             @sorted_files = sort {
                    277:                 $filehash->{$a}->{$sortby} <=> $filehash->{$b}->{$sortby}
                    278:                     or
                    279:                 uc($a) cmp uc($b)
                    280:             } (keys(%{$filehash}));
                    281:         } else {
                    282:             @sorted_files = sort {
                    283:                 $filehash->{$b}->{$sortby} <=> $filehash->{$a}->{$sortby}
                    284:                     or
                    285:                 uc($a) cmp uc($b)
                    286:             } (keys(%{$filehash}));
                    287:         }
                    288:     } elsif ($sortby =~ m{filetype|title|status}) {     # String fields
                    289:         if ($sortorder eq "rev") {
                    290:             @sorted_files = sort {
                    291:                 $filehash->{$b}->{$sortby} cmp $filehash->{$a}->{$sortby}
                    292:                     or
                    293:                 uc($a) cmp uc($b)
                    294:             } (keys(%{$filehash}));
                    295:         } else {
                    296:             @sorted_files = sort {
                    297:                 $filehash->{$a}->{$sortby} cmp $filehash->{$b}->{$sortby}
                    298:                     or
                    299:                 uc($a) cmp uc($b)
                    300:             } (keys(%{$filehash}));
                    301:         }
                    302: 
                    303:     # Sort by "Name" is the default
                    304:     } else { 
                    305:         if ($sortorder eq "rev") {
                    306:             @sorted_files = sort {uc($b) cmp uc($a)} (keys(%{$filehash}));
                    307:         } else {
                    308:             @sorted_files = sort {uc($a) cmp uc($b)} (keys(%{$filehash}));
                    309:         }
                    310:     }
                    311: 
                    312:     # Print the sorted resources
                    313:     foreach my $filename (@sorted_files) {
                    314:         if ($filehash->{$filename}->{"cmode"}&$dirptr) {        # Directories
                    315:             &putdirectory($r, $thisdisfn, $linkdir, $filename, 
                    316:                 $filehash->{$filename}->{"cmtime"}, 
                    317:                 $targetdir, \%bombs, \$numdir);
                    318:         } else {                                                # Files
                    319:             &putresource($r, $udom, $uname, $filename, $thisdisfn, $resdir,
                    320:                 $targetdir, $linkdir, $filehash->{$filename}->{"cmtime"}, 
                    321:                 $filehash->{$filename}->{"size"}, \$numres, 
                    322:                 $filehash->{$filename}->{"linkfilename"},
                    323:                 $filehash->{$filename}->{"fulltitle"},
                    324:                 $filehash->{$filename}->{"status"},
                    325:                 $filehash->{$filename}->{"pubstatus"});
                    326:         }
                    327:     }
                    328: 
1.161     golterma  329:   $r->print(&Apache::loncommon::end_data_table()
                    330:            .'</div><div id="otherplaces" style="display:none">'
                    331:            .&Apache::loncommon::start_data_table()
1.162     golterma  332:            .'<tr><th colspan="7">'.&mt('Results in other directories:').'</th></tr>'
1.161     golterma  333:            .'<tr class="LC_header_row" id="otherplacestable">'
                    334:            .'<th>'.&mt('Type').'</th>'
                    335:            .'<th>'.&mt('Directory').'</th>'
                    336:            .'<th>'.&mt('Name').'</th>'
                    337:            .'<th>'.&mt('Title').'</th>'
                    338:            .'<th colspan="2">'.&mt('Status').'</th>'
                    339:            .'<th>'.&mt('Last Modified').'</th>'
                    340:            .'</tr>'
1.162     golterma  341:            .&Apache::loncommon::end_data_table()
1.161     golterma  342:            .'</div>'
                    343:            .&Apache::loncommon::end_page()
                    344:   );
                    345:   return OK;  
1.1       www       346: }
1.127     www       347: 
1.152     musolffc  348: 
                    349: 
1.23      foxr      350: #   Output the header of the page.  This includes:
                    351: #   - The HTML header 
                    352: #   - The H1/H3  stuff which includes the directory.
                    353: #
1.164     musolffc  354: #     startpage($r, $uame, $udom, $thisdisfn, $current_disk_usage, $disk_quota);
1.23      foxr      355: #      $r     - The apache request object.
                    356: #      $uname - User name.
                    357: #      $udom  - Domain name the user is logged in under.
                    358: #      $thisdisfn - Displayable version of the filename.
1.164     musolffc  359: #      $current_disk_usage - User's current disk usage (in kB).
                    360: #      $disk_quota - Disk quota for user's authoring space (in MB).
1.169     raeburn   361: #      $crstype - Course type, if this is for "course author"
1.26      www       362: 
1.23      foxr      363: sub startpage {
1.169     raeburn   364:     my ($r, $uname, $udom, $thisdisfn, $current_disk_usage, $disk_quota, $crsauthor) = @_;
1.39      www       365:     &Apache::loncommon::content_type($r,'text/html');
1.23      foxr      366:     $r->send_http_header;
1.64      raeburn   367: 
1.132     www       368:     my $formaction='/priv'.$thisdisfn.'/';
1.89      albertel  369:     $formaction=~s|/+|/|g;
1.169     raeburn   370: 
                    371:     my $title;
                    372:     if ($crsauthor) {
                    373:         $title = 'Course Authoring';
                    374:     } else {
                    375:         $title = 'Authoring Space';
                    376:         &Apache::lonhtmlcommon::store_recent('construct',$formaction,$formaction);
                    377:     }
1.121     bisitz    378: 
1.125     droeschl  379:     &Apache::lonhtmlcommon::clear_breadcrumbs();
                    380:     &Apache::lonhtmlcommon::add_breadcrumb({
1.169     raeburn   381:         'text'  => $title,
1.137     raeburn   382:         'href'  => &Apache::loncommon::authorspace($formaction),
1.125     droeschl  383:     });
                    384:     # breadcrumbs (and tools) will be created 
                    385:     # in start_page->bodytag->innerregister
                    386: 
1.132     www       387:     $env{'request.noversionuri'}=$formaction;
1.164     musolffc  388:     my $js = '<script type="text/javascript" 
                    389:                 src="/res/adm/includes/file_upload.js"></script>';
1.169     raeburn   390:     $r->print(&Apache::loncommon::start_page($title, $js));
1.90      albertel  391: 
1.164     musolffc  392:     $disk_quota = 1024 * $disk_quota; # convert from MB to kB
1.147     raeburn   393: 
1.121     bisitz    394:     $r->print(&Apache::loncommon::head_subbox(
1.147     raeburn   395:                      '<div style="float:right;padding-top:0;margin-top;0">'
1.168     raeburn   396:                     .&Apache::lonhtmlcommon::display_usage($current_disk_usage,
                    397:                                                            $disk_quota,'authoring')
1.147     raeburn   398:                     .'</div>'
                    399:                     .&Apache::loncommon::CSTR_pageheader()));
1.121     bisitz    400: 
1.101     albertel  401:     my $esc_thisdisfn = &Apache::loncommon::escape_single($thisdisfn);
1.169     raeburn   402:     my $doctitle = 'LON-CAPA '.&mt($title);
1.109     bisitz    403:     my $newname = &mt('New Name');
1.29      www       404:     my $pubdirscript=(<<ENDPUBDIRSCRIPT);
1.77      albertel  405: <script type="text/javascript">
1.107     bisitz    406: top.document.title = '$esc_thisdisfn/ - $doctitle';
1.37      www       407: // Store directory location for menu bar to find
                    408: 
1.132     www       409: parent.lastknownpriv='/priv$esc_thisdisfn/';
1.37      www       410: 
                    411: // Confirmation dialogues
                    412: 
1.64      raeburn   413:     function currdiract(theform) {
                    414:         if (theform.dirtask.options[theform.dirtask.selectedIndex].value == 'publish') {
1.79      www       415:             document.publishdir.filename.value = theform.filename.value;
                    416: 	    document.publishdir.submit();
1.64      raeburn   417:         }
1.113     schafran  418:         if (theform.dirtask.options[theform.dirtask.selectedIndex].value == 'editmeta') {
1.66      raeburn   419:             top.location=theform.filename.value+'default.meta'
1.64      raeburn   420:         }
                    421:         if (theform.dirtask.options[theform.dirtask.selectedIndex].value == 'printdir' ) {
                    422:             document.printdir.postdata.value=theform.filename.value
                    423:             document.printdir.submit();
                    424:         }
1.88      raeburn   425:         if (theform.dirtask.options[theform.dirtask.selectedIndex].value == "delete") {
                    426:               var delform = document.delresource
                    427:               delform.filename.value = theform.filename.value
                    428:               delform.submit()
                    429:         }
1.64      raeburn   430:     }
                    431:   
                    432:     function checkUpload(theform) {
                    433:         if (theform.file == '') {
                    434:             alert("Please use 'Browse..' to choose a file first, before uploading")
                    435:             return 
                    436:         }
                    437:         theform.submit()  
                    438:     }
                    439: 
                    440:     function SetPubDir(theform,printForm) {
                    441:         if (theform.diraction.options[theform.diraction.selectedIndex].value == "open") {
1.75      albertel  442:             top.location = theform.openname.value
1.64      raeburn   443:             return
                    444:         }
                    445:         if (theform.diraction.options[theform.diraction.selectedIndex].value == "publish") {
1.79      www       446:             theform.submit();
1.64      raeburn   447:         }
1.113     schafran  448:         if (theform.diraction.options[theform.diraction.selectedIndex].value == "editmeta") {
1.66      raeburn   449:             top.location=theform.filename.value+'default.meta'
1.64      raeburn   450:         }
1.68      raeburn   451:         if (theform.diraction.options[theform.diraction.selectedIndex].value == "printdir") {
1.64      raeburn   452:             theform.action = '/adm/printout'
                    453:             theform.postdata.value = theform.filename.value
                    454:             theform.submit()
                    455:         }
1.88      raeburn   456:         if (theform.diraction.options[theform.diraction.selectedIndex].value == "delete") {
                    457:               var delform = document.delresource
                    458:               delform.filename.value = theform.filename.value
                    459:               delform.submit()
                    460:         }
1.64      raeburn   461:         return
                    462:     }
                    463:     function SetResChoice(theform) {
                    464:       var activity = theform.reschoice.options[theform.reschoice.selectedIndex].value
                    465:       if ((activity == 'rename') || (activity == 'copy') || (activity == 'move')) {
                    466:           changename(theform,activity)
                    467:       }
                    468:       if (activity == 'publish') {
                    469:           var pubform = document.pubresource
                    470:           pubform.filename.value = theform.filename.value
                    471:           pubform.submit()
                    472:       }
                    473:       if (activity == 'delete') {
                    474:           var delform = document.delresource
                    475:           delform.filename.value = theform.filename.value
1.71      raeburn   476:           delform.submit()
1.64      raeburn   477:       }
                    478:       if (activity == 'obsolete') {
1.68      raeburn   479:           var pubform = document.pubresource
                    480:           pubform.filename.value = theform.filename.value
1.80      www       481:           pubform.makeobsolete.value=1;
1.68      raeburn   482:           pubform.submit()
1.64      raeburn   483:       }
                    484:       if (activity == 'print') {
1.68      raeburn   485:           document.printresource.postdata.value = theform.filename.value
1.64      raeburn   486:           document.printresource.submit()
                    487:       }
                    488:       if (activity == 'retrieve') {
1.68      raeburn   489:           document.retrieveres.filename.value = theform.filename.value
                    490:           document.retrieveres.submit()
1.64      raeburn   491:       }
1.82      www       492:       if (activity == 'cleanup') {
                    493:           document.cleanup.filename.value = theform.filename.value
                    494:           document.cleanup.submit()
                    495:       }
1.64      raeburn   496:       return
                    497:     }
                    498:     function changename(theform,activity) {
1.96      banghart  499:         var oldname=theform.dispfilename.value;
1.109     bisitz    500:         var newname=prompt('$newname',oldname);
1.97      banghart  501:         if (newname == "" || !newname || newname == oldname)  {
1.64      raeburn   502:             return
                    503:         }
                    504:         document.moveresource.newfilename.value = newname
                    505:         document.moveresource.filename.value = theform.filename.value
                    506:         document.moveresource.action.value = activity
                    507:         document.moveresource.submit();
                    508:     }
1.29      www       509: </script>
                    510: ENDPUBDIRSCRIPT
1.64      raeburn   511:     $r->print($pubdirscript);
                    512: }
                    513: 
                    514: sub dircontrols {
1.164     musolffc  515:     my ($r,$uname,$udom,$thisdisfn, $current_disk_usage, $disk_quota) = @_;
1.84      www       516:     my %lt=&Apache::lonlocal::texthash(
                    517:                                        cnpd => 'Cannot publish directory',
                    518:                                        cnrd => 'Cannot retrieve directory',
                    519:                                        mcdi => 'Must create new subdirectory inside a directory',
                    520:                                        pubr => 'Publish this Resource',
                    521:                                        pubd => 'Publish this Directory',
1.88      raeburn   522:                                        dedr => 'Delete Directory',
1.84      www       523:                                        rtrv => 'Retrieve Old Version',
                    524:                                        list => 'List Directory',
                    525:                                        uplo => 'Upload file',  
                    526:                                        dele => 'Delete',
1.113     schafran  527:                                        edit => 'Edit Metadata', 
1.84      www       528:                                        sela => 'Select Action',
                    529:                                        nfil => 'New file',
                    530:                                        nhtm => 'New HTML file',
                    531:                                        nprb => 'New problem',
                    532:                                        npag => 'New assembled page',
                    533:                                        nseq => 'New assembled sequence',
                    534:                                        ncrf => 'New custom rights file',
                    535:                                        nsty => 'New style file',
                    536:                                        nlib => 'New library file',
1.103     albertel  537:                                        nbt  => 'New bridgetask file',
1.84      www       538:                                        nsub => 'New subdirectory',
                    539:                                        renm => 'Rename current file to',
                    540:                                        move => 'Move current file to',
                    541:                                        copy => 'Copy current file to',
                    542:                                        type => 'Type Name Here',
1.105     albertel  543:                                        go   => 'Go',
1.84      www       544:                                        prnt => 'Print contents of directory',
                    545:                                        crea => 'Create a new directory or LON-CAPA document',
1.161     golterma  546:                                        qs   => 'Quick Search',
                    547:                                        cs   => 'Case Sensitive',
                    548:                                        re   => 'Regular Expression',
1.84      www       549: 				       acti => 'Actions for current directory',
1.105     albertel  550: 				       updc => 'Upload a new document',
                    551: 				       pick => 'Please select an action to perform using the new filename',
1.175   ! raeburn   552:                                        shcu => 'Shortcuts',
1.84      www       553:                                       );
1.175   ! raeburn   554:     my %js_lt = &Apache::lonlocal::texthash(
        !           555:                                        nanf => 'Name of New File',
        !           556:                                        nans => 'Name of New Subdirectory',
        !           557:                                        psfn => 'Please specify file name',
        !           558:     ); 
        !           559:     &js_escape(\%js_lt);
1.106     bisitz    560:     my $mytype = $lt{'type'}; # avoid conflict with " and ' in javascript
1.164     musolffc  561:     # Calculate free space in bytes.
                    562:     # $disk_quota is in MB and $current_disk_usage is in kB
                    563:     my $free_space = 1024 * ((1024 * $disk_quota) - $current_disk_usage);
1.161     golterma  564:     $r->printf(<<END,&Apache::loncommon::help_open_topic('Quicksearch'));
1.117     harmsja   565: <div class="LC_columnSection">
1.116     bisitz    566:   <div>
                    567:     <form name="curractions" method="post" action="">
                    568:       <fieldset>
                    569:         <legend>$lt{'acti'}</legend>
                    570:         <select name="dirtask" onchange="currdiract(this.form)">
1.84      www       571:             <option>$lt{'sela'}</option>
                    572:             <option value="publish">$lt{'pubd'}</option>
1.113     schafran  573:             <option value="editmeta">$lt{'edit'}</option>
1.84      www       574:             <option value="printdir">$lt{'prnt'}</option>
1.88      raeburn   575:             <option value="delete">$lt{'dedr'}</option>
1.116     bisitz    576:         </select>
1.132     www       577:         <input type="hidden" name="filename" value="/priv$thisdisfn/" />
1.116     bisitz    578:       </fieldset>
                    579:     </form>
1.174     raeburn   580:     <form name="publishdir" method="post" action="/adm/publish">
1.116     bisitz    581:       <input type="hidden" name="pubrec" value="" />
                    582:       <input type="hidden" name="filename" value="" />
                    583:     </form>
1.174     raeburn   584:     <form name="printdir" method="post" action="/adm/printout">
1.116     bisitz    585:       <input type="hidden" name="postdata" value="" />
                    586:     </form>
                    587:   </div>
                    588: 
1.170     damieng   589:   <div style="padding-bottom: 2px">
1.174     raeburn   590:     <form name="upublisher" enctype="multipart/form-data" method="post" action="/adm/upload">
1.116     bisitz    591:       <fieldset>
                    592:         <legend>$lt{'updc'}</legend>
1.132     www       593:         <input type="hidden" name="filename" value="/priv$thisdisfn/" />
1.175   ! raeburn   594:         <input type="file" name="upfile" class="LC_flUpload" />
1.173     raeburn   595:         <input type="hidden" id="LC_free_space" value="$free_space" />
1.116     bisitz    596:         <input type="button" value="$lt{'uplo'}"  onclick="checkUpload(this.form)" />
                    597:       </fieldset>
                    598:     </form>
                    599:   </div>
                    600: 
                    601:   <div>
1.174     raeburn   602:     <form name="fileaction" method="post" action="/adm/cfile">
1.116     bisitz    603:       <fieldset>
                    604:               <legend>$lt{'crea'}</legend>
                    605: 	      <span class="LC_nobreak">
1.132     www       606: 		<input type="hidden" name="filename" value="/priv$thisdisfn/" />
1.105     albertel  607:                   <script type="text/javascript">
                    608:                     function validate_go() {
                    609:                         var selected = document.fileaction.action.selectedIndex;
                    610:                         if (selected == 0) {
                    611:                             alert('$lt{'pick'}');
                    612:                         } else {
                    613:                             document.fileaction.submit();
                    614:                         }
                    615:                     }
                    616:                   </script>
                    617: 		  <select name="action">
                    618: 		    <option value="none">$lt{'sela'}</option>
                    619: 		    <option value="newfile">$lt{'nfil'}:</option>
                    620: 		    <option value="newhtmlfile">$lt{'nhtm'}:</option>
                    621: 		    <option value="newproblemfile">$lt{'nprb'}:</option>
                    622:                     <option value="newpagefile">$lt{'npag'}:</option>
                    623:                     <option value="newsequencefile">$lt{'nseq'}:</option>
                    624:                     <option value="newrightsfile">$lt{'ncrf'}:</option>
                    625:                     <option value="newstyfile">$lt{'nsty'}:</option>
                    626:                     <option value="newtaskfile">$lt{'nbt'}:</option>
                    627:                     <option value="newlibraryfile">$lt{'nlib'}:</option>
                    628: 	            <option value="newdir">$lt{'nsub'}:</option>
1.175   ! raeburn   629: 		  </select>&nbsp;<input type="text" id="newnameid" name="newfilename" placeholder="$lt{'type'}" value="" onfocus="if (this.value == is.empty()) this.value=''" />&nbsp;<input type="button" value="Go" onclick="validate_go();" />
1.163     golterma  630: 		<br />
1.175   ! raeburn   631:                 <span>$lt{'shcu'}:
1.163     golterma  632:                  <input type="hidden" name="mode"/>
                    633:                  <a href="javascript:void(0)" onclick="javascript:validate_action('blank')">
                    634: 		    <img src="/adm/lonIcons/unknown.gif" title="Create blank problem file"></a>
                    635:                  <a href="javascript:void(0)" onclick="javascript:validate_action('problemtempl')"> 
                    636:                     <img src="/adm/lonIcons/problem.gif" title="Create new problem from template"></a>
                    637:                  <a href="javascript:void(0)" onclick="javascript:validate_action('blankhtml')"> 
                    638:                     <img src="/adm/lonIcons/html.gif" title="Create new blank HTML file"></a>
                    639:                  <a href="javascript:void(0)" onclick="javascript:validate_action('folder')"> 
                    640: 		    <img src="/adm/lonIcons/navmap.folder.closed.gif" title="Create new subdirectory"></a>
                    641:                 </span>
                    642:                  <script type="text/javascript">
                    643:                      function validate_action(action){
1.175   ! raeburn   644:                          if (document.getElementById('newnameid')) {
        !           645:                              if (document.getElementById('newnameid').value == '') {
        !           646:                                  var newname;
        !           647:                                  var prompttext = "$js_lt{'nanf'}";
        !           648:                                  if (action == 'folder') {
        !           649:                                      prompttext = "$js_lt{'nans'}";
        !           650:                                  }
        !           651:                                  newname=prompt(prompttext);
        !           652:                                  if (newname != '') {
        !           653:                                      document.getElementById('newnameid').value = newname;
        !           654:                                  }
        !           655:                              }
        !           656:                              if (document.getElementById('newnameid').value != '') {
        !           657:                                  if (action == 'blank') {
        !           658: 				     document.fileaction.action.value='newproblemfile';
        !           659: 				     document.fileaction.mode.value='blank';
        !           660: 			         } else if (action == 'problemtempl') {
        !           661: 				     document.fileaction.action.value='newproblemfile';
        !           662:                                      validate_go();
        !           663:                                  } else if (action == 'blankhtml') {
        !           664:                                      document.fileaction.action.value='newhtmlfile';
        !           665:                                      validate_go();
        !           666:                                  } else if (action == 'folder') {
        !           667:                                      document.fileaction.action.value='newdir';
        !           668:                                      document.fileaction.mode.value='folder';
        !           669:                                  }
        !           670:                                  fileaction.submit();
        !           671:                              } else {
        !           672:                                  alert("$js_lt{'psfn'}");
1.163     golterma  673:                              }
                    674:                          }
                    675:                      }
                    676:                  </script>
1.92      albertel  677: 		 </span>
1.116     bisitz    678:       </fieldset>
                    679:     </form>
1.161     golterma  680:     </div>
                    681:     <div>
1.162     golterma  682:       <fieldset style="display:inline">
                    683:             <legend>$lt{'qs'}</legend>
                    684:                 <script type="text/javascript" src="/adm/quicksearch/quicksearch.js"></script>
                    685:                 <input type="text" id="quickfilter" placeholder="Enter search term" onkeyup="applyFilter()"/>
                    686:                 <input type="button" value="Clear" onclick="document.getElementById(\'quickfilter\').value=\'\'; applyFilter()" />
                    687:                 %s
                    688:                 <br />
                    689:                 <label><input type="checkbox" id="casesens" onchange="applyFilter()"/>$lt{'cs'}&nbsp;&nbsp;</label>
                    690:                 <label><input type="checkbox" id="regex" onchange="applyFilter()"/>$lt{'re'}&nbsp;&nbsp;</label>
                    691:         </fieldset>
1.116     bisitz    692:   </div>
                    693: </div>
1.64      raeburn   694: END
                    695: }
                    696: 
                    697: sub resourceactions {
                    698:     my ($r,$uname,$udom,$thisdisfn) = @_;
                    699:     $r->print(<<END);
1.174     raeburn   700:        <form name="moveresource" action="/adm/cfile" method="post">
1.64      raeburn   701:          <input type="hidden" name="filename" value="" />
                    702:          <input type="hidden" name="newfilename" value="" />
                    703:          <input type="hidden" name="action" value="" />
                    704:        </form>
1.174     raeburn   705:        <form name="delresource" action="/adm/cfile" method="post">
1.64      raeburn   706:          <input type="hidden" name="filename" value="" />
                    707:          <input type="hidden" name="action" value="delete" />
                    708:        </form>
1.174     raeburn   709:        <form name="pubresource" action="/adm/publish" method="post">
1.64      raeburn   710:          <input type="hidden" name="filename" value="" />
1.80      www       711:          <input type="hidden" name="makeobsolete" value="0" />
1.64      raeburn   712:        </form>
1.174     raeburn   713:        <form name="printresource" action="/adm/printout" method="post">
1.64      raeburn   714:            <input type="hidden" name="postdata" value="" />
                    715:        </form>
1.174     raeburn   716:        <form name="retrieveres" action="/adm/retrieve" method="post">
1.64      raeburn   717:            <input type="hidden" name="filename" value="" />
                    718:        </form>
1.174     raeburn   719:        <form name="cleanup" action="/adm/cleanup" method="post">
1.82      www       720:            <input type="hidden" name="filename" value="" />
                    721:        </form>
1.64      raeburn   722: END
1.23      foxr      723: }
                    724: 
                    725: #
                    726: #   Get the title string or "[untitled]" if the file has no title metadata:
                    727: #   Without the latter substitution, it's impossible to examine metadata for
                    728: #   untitled resources.  Resources may be legitimately untitled, to prevent
                    729: #   searches from locating them.
                    730: #
                    731: #   $str = getTitleString($fullname);
                    732: #       $fullname - Fully qualified filename to check.
                    733: #
                    734: sub getTitleString {
                    735:     my $fullname = shift;
                    736:     my $title    = &Apache::lonnet::metadata($fullname, 'title');
                    737: 
                    738:     unless ($title) {
1.40      www       739: 	$title = "[".&mt('untitled')."]";
1.23      foxr      740:     }
                    741:     return $title;
                    742: }
                    743: 
1.55      www       744: sub getCopyRightString {
                    745:     my $fullname = shift;
                    746:     return &Apache::lonnet::metadata($fullname, 'copyright');
                    747: }
1.61      www       748: 
                    749: sub getSourceRightString {
                    750:     my $fullname = shift;
                    751:     return &Apache::lonnet::metadata($fullname, 'sourceavail');
                    752: }
1.23      foxr      753: #
1.21      foxr      754: #  Put out a directory table row:
1.134     raeburn   755: #    putdirectory(r, base, here, dirname, modtime, targetdir, bombs, numdir)
                    756: #      r         - Apache request object.
                    757: #      reqfile   - File in request.
                    758: #      here      - Where we are in directory tree.
                    759: #      dirname   - Name of directory special file.
                    760: #      modtime   - Encoded modification time.
                    761: #      targetdir - Publication target directory.
                    762: #      bombs     - Reference to hash of URLs with runtime error messages.
                    763: #      numdir    - Reference to scalar used to track number of sub-directories
                    764: #                  in directory (used in form name for each "actions" dropdown).
                    765: #
1.21      foxr      766: sub putdirectory {
1.134     raeburn   767:     my ($r, $reqfile, $here, $dirname, $modtime, $targetdir, $bombs, $numdir) = @_;
1.129     www       768: 
                    769: # construct the display filename: the directory name unless ..:
1.133     www       770:    
                    771:     my $actionitem;
                    772:  
1.21      foxr      773:     my $disfilename = $dirname;
1.130     www       774: # Don't display directory itself, and there is no way up from root directory
1.133     www       775:     unless ((($dirname eq '..') && ($reqfile=~/^\/[^\/]+\/[^\/]+$/)) || ($dirname eq '.')) {
1.143     bisitz    776:         my $kaputt=0;
1.134     raeburn   777:         if (ref($bombs) eq 'HASH') {
1.143     bisitz    778:             foreach my $key (keys(%{$bombs})) {
                    779:                 my $currentdir = &Apache::lonnet::declutter("$targetdir/$disfilename");
                    780:                 if (($key) =~ m{^\Q$currentdir\E/}) { $kaputt=1; last; }
                    781:             }
1.134     raeburn   782:         }
1.129     www       783: #
                    784: # Get the metadata from that directory's default.meta to display titles
                    785: #
1.52      www       786: 	%Apache::lonpublisher::metadatafields=();
                    787: 	%Apache::lonpublisher::metadatakeys=();
1.129     www       788: 	&Apache::lonpublisher::metaeval(
                    789:                  &Apache::lonnet::getfile($r->dir_config('lonDocRoot').$here.'/'.$dirname.'/default.meta')
                    790:                                        );
1.133     www       791:         if ($dirname eq '..') {
1.109     bisitz    792:             $actionitem = &mt('Go to ...');
1.133     www       793:             $disfilename = '<i>'.&mt('Parent Directory').'</i>';
1.64      raeburn   794:         } else {
                    795:             $actionitem = 
                    796:                     '<form name="dirselect_'.$$numdir.
1.174     raeburn   797:                     '" action="/adm/publish">'.
1.85      albertel  798:                     '<select name="diraction" onchange="SetPubDir(this.form,document)">'.
1.64      raeburn   799:                       '<option selected="selected">'.&mt('Select action').'</option>'.
                    800:                       '<option value="open">'.&mt('Open').'</option>'.
                    801:                       '<option value="publish">'.&mt('Publish').'</option>'.
1.113     schafran  802:                       '<option value="editmeta">'.&mt('Edit Metadata').'</option>'.
1.77      albertel  803:                       '<option value="printdir">'.&mt('Print directory').'</option>'.
1.88      raeburn   804:                       '<option value="delete">'.&mt('Delete directory').'</option>'.
1.64      raeburn   805:                     '</select>'.
1.129     www       806:                      '<input type="hidden" name="filename" value="'.&HTML::Entities::encode($here.'/'.$dirname,'<>&"').'/" />'.
1.75      albertel  807:                      '<input type="hidden" name="openname" value="'.$here.'/'.$dirname.'/" />'.
1.64      raeburn   808:                      '<input type="hidden" name="postdata" value="" />'.
                    809:                    '</form>';
                    810:             $$numdir ++;
                    811:         }
1.92      albertel  812: 	$r->print('<tr class="LC_browser_folder">'.
1.53      www       813: 		  '<td><img src="'.
1.123     bisitz    814: 		  $Apache::lonnet::perlvar{'lonIconsURL'}.'/navmap.folder.closed.gif" alt="folder" /></td>'.
1.64      raeburn   815: 		  '<td>'.$actionitem.'</td>'.
1.174     raeburn   816: 		  '<td><span class="LC_filename"><a href="'.&HTML::Entities::encode($here.'/'.$dirname,'<>&"').'/">'.
1.92      albertel  817: 		  $disfilename.'</a></span></td>'.
1.134     raeburn   818: 		        '<td colspan="3">'.($kaputt?&Apache::lonhtmlcommon::authorbombs($targetdir.'/'.$disfilename.'/'):'').$Apache::lonpublisher::metadatafields{'title'});
1.92      albertel  819: 	if ($Apache::lonpublisher::metadatafields{'subject'} ne '') {
                    820: 	    $r->print(' <i>'.
                    821: 		      $Apache::lonpublisher::metadatafields{'subject'}.
                    822: 		      '</i> ');
                    823: 	}
                    824: 	$r->print($Apache::lonpublisher::metadatafields{'keywords'}.'</td>'.
1.42      www       825: 		  '<td>'.&Apache::lonlocal::locallocaltime($modtime).'</td>'.
1.152     musolffc  826: 	          '<td></td>'.
1.25      www       827: 		  "</tr>\n");
1.64      raeburn   828:     }
1.154     raeburn   829:     return;
1.21      foxr      830: }
1.152     musolffc  831: 
                    832: sub getTitle {
                    833:     my ($resdir, $targetdir, $filename, $linkfilename, $meta_same, $bombs) = @_;
                    834:     my $title='';
                    835:     my $titleString = &getTitleString($targetdir.'/'.$filename);
                    836:     if (-e $resdir.'/'.$filename) {
                    837: 	$title = '<a href="'.$targetdir.'/'.$filename.
                    838: 	    '.meta" target="cat">'.$titleString.'</a>';
                    839:         if (!$meta_same) {
                    840: 	    $title = &mt('Metadata Modified').'<br />'.$title.
                    841: 		'<br />'.
                    842:                 &Apache::loncommon::modal_link(
                    843:                     '/adm/diff?filename='.$linkfilename.'.meta'.'&amp;versiontwo=priv',
                    844:                     &mt('Metadata Diffs'),600,500);
                    845: 	    $title.="\n".'<br />'.
                    846:                 &Apache::loncommon::modal_link(
                    847:                     '/adm/retrieve?filename='.$linkfilename.'.meta&amp;inhibitmenu=yes&amp;add_modal=yes',
                    848:                     &mt('Retrieve Metadata'),600,500);
                    849:         } 
                    850:     }
                    851:     # Allow editing metadata of published and unpublished resources
                    852:     $title .= "\n".'<br />' if ($title);
                    853:     $title .= '<a href="'.$linkfilename.'.meta">'.
                    854:               ($$bombs{&Apache::lonnet::declutter($targetdir.'/'.$filename)}?
                    855:                   '<img src="/adm/lonMisc/bomb.gif" border="0" alt="'.&mt('bomb').'" />':
                    856:                   &mt('Edit Metadata')).
                    857:               '</a>';
                    858: 
                    859:     return ($title, $titleString);
                    860: }
                    861: 
                    862: 
                    863: sub isMetaSame {
                    864:     my ($cstr_dir, $resdir, $filename) = @_;
                    865:     my $meta_cmtime = (stat($cstr_dir.'/'.$filename.'.meta'))[9];
                    866:     my $meta_rmtime = (stat($resdir.'/'.$filename.'.meta'))[9];
                    867:     return (&Apache::londiff::are_different_files($resdir.'/'.$filename.'.meta',
                    868:             $cstr_dir.'/'.$filename.'.meta') && $meta_rmtime < $meta_cmtime) 
                    869:         ? 0 : 1;
                    870: }
                    871:     
                    872: 
                    873: sub getStatus {    
                    874:     my ($resdir, $targetdir, $cstr_dir, $filename,  
                    875:             $linkfilename, $cmtime, $meta_same) = @_;
1.64      raeburn   876:     my $pubstatus = 'unpublished';
1.152     musolffc  877:     my $status = &mt('Unpublished');
1.129     www       878: 
1.22      foxr      879:     if (-e $resdir.'/'.$filename) {
1.152     musolffc  880:         my $same = 0;
                    881:         if ((stat($resdir.'/'.$filename))[9] >= $cmtime) {
                    882:             $same = 1;
1.91      www       883:         } else {
                    884:            if (&Apache::londiff::are_different_files($resdir.'/'.$filename,
1.95      albertel  885: 						     $cstr_dir.'/'.$filename)) {
1.152     musolffc  886:               $same = 0;
1.91      www       887:            } else {
1.152     musolffc  888:               $same = 1;
1.91      www       889:            }
                    890:         }
1.124     bisitz    891: 
                    892:         my $rights_status =
                    893:             &mt(&getCopyRightString($targetdir.'/'.$filename)).', ';
                    894: 
                    895:         my %lt_SourceRight = &Apache::lonlocal::texthash(
                    896:                'open'   => 'Source: open',
                    897:                'closed' => 'Source: closed',
                    898:         );
                    899:         $rights_status .=
                    900:             $lt_SourceRight{&getSourceRightString($targetdir.'/'.$filename)};
                    901: 
1.91      www       902: 	if ($same) {
1.40      www       903: 	    if (&Apache::lonnet::metadata($targetdir.'/'.$filename,'obsolete')) {
1.64      raeburn   904:                 $pubstatus = 'obsolete';
1.41      www       905: 		$status=&mt('Obsolete');
1.95      albertel  906:             } else {
                    907: 		if (!$meta_same) {
                    908: 		    $pubstatus = 'metamodified';
                    909: 		} else {
                    910: 		    $pubstatus = 'published';
                    911: 		}
                    912: 		$status=&mt('Published').
                    913: 		    '<br />'. $rights_status;
                    914: 	    }
1.22      foxr      915: 	} else {
1.64      raeburn   916:             $pubstatus = 'modified';
1.95      albertel  917: 	    $status=&mt('Modified').
                    918: 		'<br />'. $rights_status;
1.22      foxr      919: 	    if (&Apache::loncommon::fileembstyle(($filename=~/\.(\w+)$/)) eq 'ssi') {
1.139     www       920: 		$status.='<br />'.
                    921:                          &Apache::loncommon::modal_link(
                    922:                              '/adm/diff?filename='.$linkfilename.'&amp;versiontwo=priv',
                    923:                              &mt('Diffs'),600,500);
1.22      foxr      924: 	    }
1.95      albertel  925: 	} 
1.152     musolffc  926: 
1.140     www       927: 	$status.="\n".'<br />'.
                    928:              &Apache::loncommon::modal_link(
                    929:                  '/adm/retrieve?filename='.$linkfilename.'&amp;inhibitmenu=yes&amp;add_modal=yes',&mt('Retrieve'),600,500);
1.22      foxr      930:     }
1.152     musolffc  931: 
                    932:     return ($status, $pubstatus);
                    933: }
                    934: 
                    935: 
                    936: #
                    937: #   Put a table row for a file resource.
                    938: #
                    939: sub putresource {
                    940:     my ($r, $udom, $uname, $filename, $thisdisfn, $resdir, $targetdir, 
                    941:             $linkdir, $cmtime, $size, $numres, $linkfilename, $title, 
                    942:             $status, $pubstatus) = @_;
                    943:     &Apache::lonnet::devalidate_cache_new('meta',$targetdir.'/'.$filename);
1.143     bisitz    944: 
1.33      www       945:     my $editlink='';
1.38      taceyjo1  946:     my $editlink2='';
1.36      www       947:     if ($filename=~/\.(xml|html|htm|xhtml|xhtm|sty)$/) {
1.146     raeburn   948: 	$editlink=' <br />(<a href="'.$linkdir.'/'.$filename.'?editmode=Edit&amp;problemmode=edit">'.&mt('Edit').'</a>)';
1.34      www       949:     }
1.136     www       950:     if ($filename=~/$LONCAPA::assess_re/) {
1.146     raeburn   951: 	$editlink=' (<a href="'.$linkdir.'/'.$filename.'?editmode=Edit&amp;problemmode=editxml">'.&mt('EditXML').'</a>)';
                    952: 	$editlink2=' <br />(<a href="'.$linkdir.'/'.$filename.'?editmode=Edit&amp;problemmode=edit">'.&mt('Edit').'</a>)';
1.167     damieng   953:     }
                    954:     if ($filename=~/\.(xml|html|htm|xhtml|xhtm)$/ || $filename=~/$LONCAPA::assess_re/) {
1.165     damieng   955:         if ($env{'browser.type'} ne 'explorer' || $env{'browser.version'} > 9) {
1.166     damieng   956:             my $daxeurl = '/daxepage'.$linkdir.'/'.$filename;
1.165     damieng   957:             $editlink .= ' (<a href="'.$daxeurl.'" target="_blank">Daxe</a>)';
                    958:         }
1.43      taceyjo1  959:     }
1.82      www       960:     if ($filename=~/\.(problem|exam|quiz|assess|survey|form|library|xml|html|htm|xhtml|xhtm|sty)$/) {
1.174     raeburn   961: 	$editlink.=' (<a href="/adm/cleanup?filename='.$linkfilename.'">'.&mt('Clean Up').')</a>';
1.82      www       962:     }
1.43      taceyjo1  963:     if ($filename=~/\.(zip|tar|bz2|gz|tar.gz|tar.bz2|tgz)$/) {
1.174     raeburn   964: 	$editlink=' (<a href="/adm/cfile?decompress='.$linkfilename.'">'.&mt('Decompress').'</a>)';
1.33      www       965:     }
1.152     musolffc  966:     my $publish_button = (-e $resdir.'/'.$filename) ? &mt('Re-publish') : &mt('Publish');
1.64      raeburn   967:     my $pub_select = '';
                    968:     &create_pubselect($r,\$pub_select,$udom,$uname,$thisdisfn,$filename,$resdir,$pubstatus,$publish_button,$numres);
1.115     bisitz    969:     $r->print(&Apache::loncommon::start_data_table_row().
1.53      www       970: 	      '<td>'.($filename=~/[\#\~]$/?'&nbsp;':
1.86      albertel  971: 		      '<img src="'.&Apache::loncommon::icon($filename).'" alt="" />').'</td>'.
1.64      raeburn   972:               '<td>'.$pub_select.'</td>'.
1.104     albertel  973: 	      '<td><span class="LC_filename">'.
1.174     raeburn   974: 	      '<a href="'.$linkdir.'/'.$filename.'">'.
1.92      albertel  975:                $filename.'</a></span>'.$editlink2.$editlink.
1.22      foxr      976: 	      '</td>'.
                    977: 	      '<td>'.$title.'</td>'.
1.115     bisitz    978:               '<td class="LC_browser_file_'.$pubstatus.'">&nbsp;&nbsp;</td>'. # Display publication status
                    979:               '<td>'.$status.'</td>'.
1.42      www       980: 	      '<td>'.&Apache::lonlocal::locallocaltime($cmtime).'</td>'.
1.153     raeburn   981: 	      '<td>'.sprintf("%.1f",$size).'</td>'.
1.115     bisitz    982: 	      &Apache::loncommon::end_data_table_row()
                    983:     );
1.154     raeburn   984:     return;
1.23      foxr      985: }
1.64      raeburn   986: 
                    987: sub create_pubselect {
                    988:     my ($r,$pub_select,$udom,$uname,$thisdisfn,$filename,$resdir,$pubstatus,$publish_button,$numres) = @_;
                    989:     $$pub_select = '
                    990: <form name="resselect_'.$$numres.'" action="">
1.85      albertel  991: <select name="reschoice"  onchange="SetResChoice(this.form)">
1.77      albertel  992: <option>'.&mt('Select action').'</option>'.
                    993: '<option value="copy">'.&mt('Copy').'</option>';
1.68      raeburn   994:     if ($pubstatus eq 'obsolete' || $pubstatus eq 'unpublished') {
                    995:         $$pub_select .= 
1.77      albertel  996: '<option value="rename">'.&mt('Rename').'</option>'.
                    997: '<option value="move">'.&mt('Move').'</option>'.
                    998: '<option value="delete">'.&mt('Delete').'</option>';
1.64      raeburn   999:     } else {
                   1000:         $$pub_select .= '
1.77      albertel 1001: <option value="obsolete">'.&mt('Mark obsolete').'</option>';
1.64      raeburn  1002:     }
                   1003: # check for versions
                   1004:     my $versions = &check_for_versions($r,'/'.$filename,$udom,$uname);
                   1005:     if ($versions > 0) {
                   1006:         $$pub_select .='
1.77      albertel 1007: <option value="retrieve">'.&mt('Retrieve old version').'</option>';
1.64      raeburn  1008:     }
                   1009:     $$pub_select .= '
1.77      albertel 1010: <option value="publish">'.$publish_button.'</option>'.
1.82      www      1011: '<option value="cleanup">'.&mt('Clean up').'</option>'.
1.77      albertel 1012: '<option value="print">'.&mt('Print').'</option>'.
1.68      raeburn  1013: '</select>
1.131     www      1014: <input type="hidden" name="filename" value="/priv'.
                   1015:  &HTML::Entities::encode($thisdisfn.'/'.$filename,'<>&"').'" />
1.96      banghart 1016:  <input type="hidden" name="dispfilename" value="'.
1.99      albertel 1017:  &HTML::Entities::encode($filename).'" /></form>';
1.64      raeburn  1018:     $$numres ++;
                   1019: }
                   1020: 
                   1021: sub check_for_versions {
                   1022:     my ($r,$fn,$udom,$uname) = @_;
                   1023:     my $versions = 0;
                   1024:     my $docroot=$r->dir_config('lonDocRoot');
                   1025:     my $resfn=$docroot.'/res/'.$udom.'/'.$uname.$fn;
                   1026:     my $resdir=$resfn;
                   1027:     $resdir=~s/\/[^\/]+$/\//;
                   1028:     $fn=~/\/([^\/]+)\.(\w+)$/;
                   1029:     my $main=$1;
                   1030:     my $suffix=$2;
                   1031:     opendir(DIR,$resdir);
                   1032:     while (my $filename=readdir(DIR)) {
                   1033:         if ($filename=~/^\Q$main\E\.(\d+)\.\Q$suffix\E$/) {
                   1034:             $versions ++;        
                   1035:         }
                   1036:     }
1.154     raeburn  1037:     closedir(DIR);
1.64      raeburn  1038:     return $versions;
                   1039: }
                   1040: 
1.161     golterma 1041: sub prepareJsonTranslations {
                   1042:     my $json = 
                   1043:         '{"translations":{'.
                   1044:             '"edit":"'.&mt('Edit').'",'.
                   1045:             '"editxml":"'.&mt('EditXML').'",'.
                   1046:             '"editmeta":"'.&mt('Edit Metadata').'",'.
                   1047:             '"obsolete":"'.&mt('Obsolete').'",'.
                   1048:             '"modified":"'.&mt('Modified').'",'.
                   1049:             '"published":"'.&mt('Published').'",'.
                   1050:             '"unpublished":"'.&mt('Unpublished').'",'.
                   1051:             '"diff":"'.&mt('Diff').'",'.
                   1052:             '"retrieve":"'.&mt('Retrieve').'",'.
                   1053:             '"directory":"'.&mt('Directory').'",'.
                   1054:             '"results":"'.&mt('Show results for keyword:').'"'.
                   1055:         '}}';
                   1056: }
                   1057: 
                   1058: # gathers all files in the working directory except the ones that are already on screen
                   1059: sub prepareJsonData {
                   1060:     my ($uname, $udom, $pathToSkip) = @_;
                   1061:     my $path = "/home/httpd/html/priv/$udom/$uname/";
                   1062: 
                   1063:     # maximum number of entries, to limit workload and required storage space
                   1064:     my $entries = 100;
                   1065:     my $firstfile = 1;
                   1066:     my $firstdir = 1;
                   1067: 
                   1068:     my $json = '{"resources":[';
                   1069:     $json .= &prepareJsonData_rec($path, \$entries, \$firstfile, \$firstdir, $pathToSkip);
                   1070:     $json .= ']}';
                   1071: 
                   1072:     # if the json string is invalid the whole search breaks.
                   1073:     # so we want to make sure that the string is valid in any case.
                   1074:     $json =~ s/,\s*,/,/g;
                   1075:     $json =~ s/\}\s*\{/\},\{/g;
                   1076:     $json =~ s/\}\s*,\s*\]/\}\]/g;
                   1077:     return $json;
                   1078: }
                   1079: 
                   1080: # recursive part of json file gathering
                   1081: sub prepareJsonData_rec {
                   1082:     my ($path, $entries, $firstfile, $firstdir, $pathToSkip) = @_;
                   1083:     my $json;
                   1084:     my $skipThisFolder = $path =~ m/$pathToSkip\/$/?1:0;
                   1085: 
                   1086:     my @dirs;
                   1087:     my @resources;
                   1088:     my @ignored = qw(bak log meta save . ..);
                   1089: 
                   1090: # Phase 1: Gathering
                   1091:     opendir(DIR,$path);
                   1092:     my @files=sort {uc($a) cmp uc($b)} (readdir(DIR));
                   1093:     foreach my $filename (@files) {
                   1094:         next if ($filename eq '.DS_Store');
                   1095: 
                   1096:         # gather all resources
                   1097:         if ($filename !~ /\./) {
                   1098:             # its a folder
                   1099:             push(@dirs, $filename);
                   1100:         } else {
                   1101:             # only push files we dont want to ignore
                   1102:             next if ($skipThisFolder);
                   1103: 
                   1104:             $filename =~ /\.(\w+?)$/;
                   1105:             unless (grep /$1/, @ignored) {
                   1106:                 push(@resources, $filename);
                   1107:             }
                   1108:         }
                   1109:     }
                   1110:     closedir(DIR);
                   1111:     # nothing to do here if both lists are empty
                   1112:     return unless ( @dirs || @resources );
                   1113:     
                   1114: # Phase 2: Working
                   1115:     $$firstfile = 1;
                   1116: 
                   1117:     foreach (@dirs) {
                   1118:         $json .= '{"name":"'.$_.'",'.
                   1119:                   '"path":"'.$path.$_.'",'.
                   1120:                   '"title":"",'.
                   1121:                   '"status":"",'.
                   1122:                   '"cmtime":""},';
                   1123:     }
                   1124: 
                   1125:     foreach (@resources) {
                   1126:         last if ($$entries < 1);
                   1127:         my $title = &getTitleString($path.$_);
                   1128: 
                   1129:         my $privpath = $path.$_;
                   1130:         my $respath = $privpath;
                   1131:         $respath =~ s/httpd\/html\/priv\//httpd\/html\/res\//;
                   1132: 
                   1133:         my $cmtime = (stat($privpath))[9];
                   1134:         my $rmtime = (stat($respath))[9];
                   1135: 
                   1136:         unless ($$firstfile) { $json .= ','; } else { $$firstfile = 0; }
                   1137: 
                   1138:         my $status = 'unpublished';
                   1139: 
                   1140:         # if a resource is published, the published version (/html/res/filepath) gets its own modification time
                   1141:         # this is newer or equal then the version in your authoring space (/html/priv/filepath)
                   1142:         if ($rmtime >= $cmtime) {
                   1143:             # obsolete
                   1144:             if (&Apache::lonnet::metadata($respath, 'obsolete')) {
                   1145:                 $status = 'obsolete';
                   1146:             }else{
                   1147:                 $status = 'published';
                   1148:             }
                   1149:         } else {
                   1150:             $status = 'modified';
                   1151:         }
                   1152: 
                   1153:         $json .= '{"name":"'.$_.'",'.
                   1154:                   '"path":"'.$path.'",'.
                   1155:                   '"title":"'.$title.'",'.
                   1156:                   '"status":"'.$status.'",'.
                   1157:                   '"cmtime":"'.&Apache::lonlocal::locallocaltime($cmtime).'"}';
                   1158:         $$entries--;
                   1159:     }
                   1160: 
                   1161:     foreach(@dirs) {
                   1162:         next if ($$entries < 1);
                   1163:         $json .= ',';
                   1164:         $json .= &prepareJsonData_rec
                   1165:                     ($path.$_.'/', $entries, $firstfile, $firstdir, $pathToSkip);
                   1166:     }
                   1167:     return $json;
                   1168: }
1.4       www      1169: 1;
                   1170: __END__
1.17      harris41 1171: 
                   1172: 
1.114     jms      1173: =head1 NAME
                   1174: 
1.145     raeburn  1175: Apache::lonpubdir - Authoring space directory lister
1.114     jms      1176: 
                   1177: =head1 SYNOPSIS
                   1178: 
                   1179: Invoked (for various locations) by /etc/httpd/conf/srm.conf:
                   1180: 
1.134     raeburn  1181:  <LocationMatch "^/+priv.*/$">
1.114     jms      1182:  PerlAccessHandler       Apache::loncacc
                   1183:  SetHandler perl-script
                   1184:  PerlHandler Apache::lonpubdir
                   1185:  ErrorDocument     403 /adm/login
                   1186:  ErrorDocument     404 /adm/notfound.html
                   1187:  ErrorDocument     406 /adm/unauthorized.html
                   1188:  ErrorDocument	  500 /adm/errorhandler
                   1189:  </LocationMatch>
                   1190: 
                   1191:  <Location /adm/pubdir>
                   1192:  PerlAccessHandler       Apache::lonacc
                   1193:  SetHandler perl-script
                   1194:  PerlHandler Apache::lonpubdir
                   1195:  ErrorDocument     403 /adm/login
                   1196:  ErrorDocument     404 /adm/notfound.html
                   1197:  ErrorDocument     406 /adm/unauthorized.html
                   1198:  ErrorDocument	  500 /adm/errorhandler
                   1199:  </Location>
                   1200: 
                   1201: =head1 INTRODUCTION
                   1202: 
                   1203: This module publishes a directory of files.
                   1204: 
                   1205: This is part of the LearningOnline Network with CAPA project
                   1206: described at http://www.lon-capa.org.
                   1207: 
                   1208: =head1 HANDLER SUBROUTINE
                   1209: 
                   1210: This routine is called by Apache and mod_perl.
                   1211: 
                   1212: =over 4
                   1213: 
                   1214: =item *
                   1215: 
                   1216: read in information
                   1217: 
                   1218: =item *
                   1219: 
                   1220: start page output
                   1221: 
                   1222: =item *
                   1223: 
                   1224: run through list of files and attempt to publish unhidden files
                   1225: 
                   1226: =back
                   1227: 
                   1228: =head1 SUBROUTINES:
                   1229: 
                   1230: =over
                   1231: 
                   1232: =item startpage($r, $uame, $udom, $thisdisfn)
                   1233: 
                   1234: Output the header of the page.  This includes:
                   1235:  - The HTML header 
                   1236:  - The H1/H3  stuff which includes the directory.
                   1237:  
                   1238:     startpage($r, $uame, $udom, $thisdisfn);
                   1239:         $r     - The apache request object.
                   1240:         $uname - User name.
                   1241:         $udom  - Domain name the user is logged in under.
                   1242:         $thisdisfn - Displayable version of the filename.
                   1243: 
                   1244: =item getTitleString($fullname)
                   1245: 
                   1246:     Get the title string or "[untitled]" if the file has no title metadata:
                   1247:     Without the latter substitution, it's impossible to examine metadata for
                   1248:     untitled resources.  Resources may be legitimately untitled, to prevent
                   1249:     searches from locating them.
                   1250:     
                   1251:     $str = getTitleString($fullname);
                   1252:         $fullname - Fully qualified filename to check.
                   1253: 
1.134     raeburn  1254: =item putdirectory($r, $base, $here, $dirname, $modtime, $targetdir, $bombs,
                   1255:                    $numdir)
1.114     jms      1256: 
                   1257:     Put out a directory table row:
                   1258:     
1.134     raeburn  1259:         $r        - Apache request object.
                   1260:         $reqfile  - File in request.
                   1261:         $here     - Where we are in directory tree.
                   1262:         $dirname  - Name of directory special file.
                   1263:         $modtime  - Encoded modification time.
                   1264:         targetdir - Publication target directory.
                   1265:         bombs     - Reference to hash of URLs with runtime error messages.
                   1266:         numdir    - Reference to scalar used to track number of sub-directories
                   1267:                     in directory (used in form name for each "actions" dropdown).
1.114     jms      1268: 
                   1269: =back
                   1270: 
                   1271: =cut

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>
500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.