[LON-CAPA-cvs] cvs: loncom /interface loncommon.pm londocs.pm lonindexer.pm lonmenu.pm /lonnet/perl lonnet.pm /metadata_database searchcat.pl /publisher lonpubdir.pm lonpublisher.pm lonunauthorized.pm

raeburn raeburn at source.lon-capa.org
Sun Jun 19 00:28:20 EDT 2016


raeburn		Sun Jun 19 04:28:20 2016 EDT

  Modified files:              
    /loncom/interface	londocs.pm loncommon.pm lonindexer.pm lonmenu.pm 
    /loncom/publisher	lonpublisher.pm lonpubdir.pm lonunauthorized.pm 
    /loncom/metadata_database	searchcat.pl 
    /loncom/lonnet/perl	lonnet.pm 
  Log:
  - Course Editor has "Standard Problem" item (Grading tab) for creation
    of new problem in user's Authoring Space, or in a Course "Authoring" Space.
  - Course Editor has "Import from Course Resources" item (Import tab) to 
    import published content from Course "Authoring" Space. 
  - Course "Authoring" Space
    - default.rights -- course-only access
    - quota is shared with content uploaded directly to course
    - content only browsable in course context
    - metadata not included in searchable meatdata MySQL table
  CVs: ----------------------------------------------------------------------
  
  
-------------- next part --------------
Index: loncom/interface/londocs.pm
diff -u loncom/interface/londocs.pm:1.605 loncom/interface/londocs.pm:1.606
--- loncom/interface/londocs.pm:1.605	Fri Jun 10 22:31:27 2016
+++ loncom/interface/londocs.pm	Sun Jun 19 04:27:49 2016
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # Documents
 #
-# $Id: londocs.pm,v 1.605 2016/06/10 22:31:27 raeburn Exp $
+# $Id: londocs.pm,v 1.606 2016/06/19 04:27:49 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -43,10 +43,13 @@
 use Apache::lonextresedit();
 use Apache::lontemplate();
 use Apache::lonsimplepage();
+use Apache::lonhomework();
+use Apache::lonpublisher();
 use HTML::Entities;
 use HTML::TokeParser;
 use GDBM_File;
 use File::MMagic;
+use File::Copy;
 use Apache::lonlocal;
 use Cwd;
 use LONCAPA qw(:DEFAULT :match);
@@ -879,7 +882,8 @@
     my $js = '<script type="text/javascript">'."\n".
              '// <![CDATA['."\n".
              &Apache::loncommon::display_filter_js('docslog')."\n".
-             &editing_js($env{'user.domain'},$env{'user.name'},$supplementalflag)."\n".
+             &editing_js($env{'user.domain'},$env{'user.name'},$supplementalflag,
+                         $coursedom,$coursenum)."\n".
              &history_tab_js()."\n".
              &Apache::lonratedt::editscript('simple')."\n".
              '// ]]>'."\n".
@@ -4814,6 +4818,9 @@
     my $coursenum=$env{'course.'.$env{'request.course.id'}.'.num'};
     my $coursedom=$env{'course.'.$env{'request.course.id'}.'.domain'};
 
+# get docroot
+    my $londocroot = $r->dir_config('lonDocRoot');
+
 # graphics settings
     $iconpath = &Apache::loncommon::lonhttpdurl($r->dir_config('lonIconsURL').'/');
 
@@ -4840,7 +4847,7 @@
     $help{'Group Portfolio'} = &Apache::loncommon::help_open_topic('Docs_About_Group_Files');
     $help{'Caching'} = &Apache::loncommon::help_open_topic('Caching');
  
-    my $allowed;
+    my ($allowed,$noendpage);
 # URI is /adm/supplemental when viewing supplemental docs in non-edit mode.
     unless ($r->uri eq '/adm/supplemental') {
         # does this user have privileges to modify content.  
@@ -4871,6 +4878,57 @@
       &init_breadcrumbs('exportcourse','IMS Export');
       &Apache::imsexport::exportcourse($r);
   } else {
+      if ($allowed && $env{'form.authorrole'}) {
+          $noendpage = 1;
+          my ($redirect,$error) = &makenewproblem($r,$coursedom,$coursenum);
+          if ($redirect) {
+              if (($env{'form.newresourceadd'}) && ($env{'form.folderpath'})) {
+                  my $container = 'sequence'; 
+                  my ($breadcrumbtrail,$randompick,$ishidden,$isencrypted,$plain,
+                      $is_random_order,$container) =
+                      &Apache::lonhtmlcommon::docs_breadcrumbs($allowed,$crstype,1);
+                  my (@folders)=split('&',$env{'form.folderpath'});
+                  $env{'form.foldername'}=&unescape(pop(@folders));
+                  my $folder=pop(@folders);
+                  my ($errtext,$fatal) = &mapread($coursenum,$coursedom,
+                                                  $folder.'.'.$container);
+                  my $warning;
+                  if ($fatal) {
+                      if ($container eq 'page') {
+                          $warning = &mt('An error occurred retrieving the contents of the current page.');
+                      } else {
+                          $warning = &mt('An error occurred retrieving the contents of the current folder.');
+                      }
+                  } else {
+                      my $url = $redirect;
+                      my $srcfile = $londocroot.$url;
+                      $url =~ s{^/priv/}{/res/};
+                      my $targetfile = $londocroot.$url;
+                      my $nokeyref = &Apache::lonpublisher::getnokey($r->dir_config('lonIncludes'));
+                      my $output = &Apache::lonpublisher::batchpublish($r,$srcfile,$targetfile,$nokeyref,1);
+                      $env{'form.folder'} = $folder;
+                      &snapshotbefore();
+                      my $url = $redirect;
+                      $url =~ s{^/priv/}{/res/};
+                      my $title = &LONCAPA::map::qtunescape($env{'form.newresourcetitle'});
+                      my $ext = 'false';
+                      my $newidx = &LONCAPA::map::getresidx(&LONCAPA::map::qtunescape($url));
+                      $LONCAPA::map::resources[$newidx]=$title.':'.&LONCAPA::map::qtunescape($url).
+                                                        ':'.$ext.':normal:res';
+                      push(@LONCAPA::map::order,$newidx);
+                      &LONCAPA::map::storeparameter($newidx,'parameter_hiddenresource','yes',
+                                                   'string_yesno');
+                      &remember_parms($newidx,'hiddenresource','set','yes');
+                      ($errtext,$fatal) =
+                          &storemap($coursenum, $coursedom, $folder.'.'.$container,1);
+                      &log_differences($plain);
+                      &mark_hash_old();
+                      $r->internal_redirect($redirect);
+                      return OK;
+                  }
+              }
+          }
+      }
 #
 # Done catching special calls
 # The whole rest is for course and supplemental documents and utilities menu
@@ -5049,7 +5107,8 @@
             my $tabidstr = join("','", at tabids);
             %ltitools = &Apache::lonnet::get_domain_ltitools($coursedom);
             my $posslti = keys(%ltitools);
-	    $script .= &editing_js($udom,$uname,$supplementalflag,$posslti).
+	    $script .= &editing_js($udom,$uname,$supplementalflag,$coursedom,$coursenum,$posslti,
+                                   $londocroot).
                        &history_tab_js().
                        &inject_data_js().
                        &Apache::lonhtmlcommon::resize_scrollbox_js('docs',$tabidstr,$tid).
@@ -5171,6 +5230,7 @@
                 'impo' => 'Import',
 		'lnks' => 'Import from Stored Links',
                 'impm' => 'Import from Assembled Map',
+                'imcr' => 'Import from Course Resources',   
                 'extr' => 'External Resource',
                 'extt' => 'External Tool',
                 'selm' => 'Select Map',
@@ -5182,6 +5242,9 @@
                 'sipa' => 'Simple Course Page',
                 'sipr' => 'Simple Problem',
                 'webp' => 'Blank Web Page (editable)', 
+                'stpr' => 'Standard Problem',
+                'news' => 'New sub-directory',
+                'crpr' => 'Create Problem',
                 'drbx' => 'Drop Box',
                 'scuf' => 'External Scores (handgrade, upload, clicker)',
                 'bull' => 'Discussion Board',
@@ -5195,12 +5258,21 @@
                 'se'   => 'Select',
                 'file' =>  'File',
                 'title' => 'Title',
+                'addp' => 'Add Placeholder to course?',
+                'uste' => 'Use Template?',
+                'fnam' => 'File Name:',
+                'loca' => 'Location:',
+                'dire' => 'Directory:',
+                'cate' => 'Category:',
+                'tmpl' => 'Template:',
                 'comment' => 'Comment',
                 'parse' => 'Upload embedded images/multimedia files if HTML file',
                 'bb5'      => 'Blackboard 5',
                 'bb6'      => 'Blackboard 6',
                 'angel5'   => 'ANGEL 5.5',
                 'webctce4' => 'WebCT 4 Campus Edition',
+                'yes'      => 'Yes',
+                'no'       => 'No',
         );
 # -----------------------------------------------------------------------------
 
@@ -5242,7 +5314,7 @@
         $quotainfo
 	$lt{'file'}:<br />
 	<input type="file" name="uploaddoc" class="flUpload" size="40" />
-    <input type="hidden" id="free_space" value="$free_space" />
+        <input type="hidden" id="free_space" value="$free_space" />
 FIUP
 
 	my $checkbox=(<<CHBO);
@@ -5322,12 +5394,89 @@
         </form>
 
 SEDFFORM
+        my $is_home;
+        my $crshome = $env{'course.'.$env{'request.course.id'}.'.home'};
+        my @ids=&Apache::lonnet::current_machine_ids();
+        if (grep(/^\Q$crshome\E$/, at ids)) {
+            $is_home = 1;
+        }
+        my (%subdirs,%files,%selimport_menus);
+        my $pickfile;
+        my $relpath = "/res/$coursedom/$coursenum";
+        &recursedirs($is_home,'res',$londocroot,$relpath,'',\%subdirs,\%files);
+        my $numdirs = scalar(keys(%files));
+        if ($numdirs > 1) {
+            my @order = sort { lc($a) cmp lc($b) } (keys(%files));
+            foreach my $key (@order) {
+                if (ref($files{$key}) eq 'HASH') {
+                    my $shown = $key;
+                    if ($key eq '') {
+                        $shown = '/';
+                    }
+                    $selimport_menus{$key}->{'text'} = $shown;
+                    $selimport_menus{$key}->{'default'} = '';
+                    my @ordered = ('');
+                    $selimport_menus{$key}->{'select2'}->{''} = ''; 
+                    foreach my $file (sort { lc($a) cmp lc($b) } (keys(%{$files{$key}}))) {
+                        $selimport_menus{$key}->{'select2'}->{$file} = $file;
+                        push(@ordered,$file);
+                    }
+                    $selimport_menus{$key}->{'order'} = \@ordered;
+                }
+            }
+            $pickfile = $lt{'dire'}.
+                        &Apache::loncommon::linked_select_forms('crsresimportform','<br />'.
+                                                                &mt('Filename: '),'',
+                                                                'coursepath','coursefile',
+                                                                \%selimport_menus,\@order,
+                                                                "resize_scrollbox('contentscroll','1','0');",'','res').
+                                                                '<br />';
+        } elsif ($numdirs == 1) {
+            my $singledir = (keys(%files))[0];
+            my $showdir = $singledir;
+            if ($singledir eq '') {
+                $showdir = '/';
+            }
+            $pickfile = $lt{'dire'}.
+                        '<select name="coursepath">'.
+                        '<option value="'.$singledir.'">'.$showdir.'</option>'."\n".
+                        '</select><br />'.
+                        &mt('Filename: ').'<select name="coursefile">'."\n".
+                        '<option value="" selected="selected">'.$lt{'se'}.'</option>'."\n";
+            foreach my $file (sort { lc($a) cmp lc($b) } (keys(%{$files{$singledir}}))) {
+                $pickfile .= '<option value="'.$file.'">'.$file.'</option>'."\n";
+            }
+            $pickfile .= '</select><br />'."\n";
+        }
+        my $importcrsresform;
+        if ($pickfile) {
+            $importcrsresform=(<<CRSFORM);
+        <a class="LC_menubuttons_link" href="javascript:toggleImportCrsres('res','$numdirs');">
+        $lt{'imcr'}</a>$help{'Course_Resources'}
+        <form action="/adm/coursedocs" method="post" name="crsresimportform" onsubmit="return validImportCrsRes();">
+        <fieldset id="importcrsresform" style="display: none;">
+        <legend>$lt{'imcr'}</legend>
+        <input type="hidden" name="active" value="bb" />
+        $pickfile
+        <p>
+        $lt{'title'}: <input type="textbox" name="crsrestitle" value="" />
+        </p>
+        <input type="hidden" name="importdetail" value="" />
+        <input type="submit" name="crsres" value="$lt{'impo'}" />
+        </fieldset>
+        </form>
+CRSFORM
+        }
+
 	my @importpubforma = (
 	{ '<img class="LC_noBorder LC_middle" src="/res/adm/pages/src.png" alt="'.$lt{srch}.'"  onclick="javascript:groupsearch()" />' => $pathitem."<a class='LC_menubuttons_link' href='javascript:groupsearch()'>$lt{'srch'}</a>" },
 	{ '<img class="LC_noBorder LC_middle" src="/res/adm/pages/res.png" alt="'.$lt{impo}.'"  onclick="javascript:groupimport();"/>' => "<a class='LC_menubuttons_link' href='javascript:groupimport();'>$lt{'impo'}</a>$help{'Importing_LON-CAPA_Resource'}" },
 	{ '<img class="LC_noBorder LC_middle" src="/res/adm/pages/wishlist.png" alt="'.$lt{lnks}.'" onclick="javascript:open_StoredLinks_Import();" />' => "<a class='LC_menubuttons_link' href='javascript:open_StoredLinks_Import();'>$lt{'lnks'}</a>" },
-        { '<img class="LC_noBorder LC_middle" src="/res/adm/pages/sequence.png" alt="'.$lt{impm}.'" onclick="javascript:toggleMap(\'map\');" />' => $importpubform }
-	);
+        { '<img class="LC_noBorder LC_middle" src="/res/adm/pages/sequence.png" alt="'.$lt{impm}.'" onclick="javascript:toggleMap(\'map\');" />' => $importpubform },
+        );
+        if ($pickfile) {
+            push(@importpubforma,{ '<img class="LC_noBorder LC_middle" src="/res/adm/pages/res.png" alt="'.$lt{imcr}.'"  onclick="javascript:toggleImportCrsres(\'res\','."'$numdirs'".');"/>' => $importcrsresform});
+	}
 	$importpubform = &create_form_ul(&create_list_elements(@importpubforma));
         my $extresourcesform =
             &Apache::lonextresedit::extedit_form(0,0,undef,undef,$pathitem,
@@ -5515,6 +5664,223 @@
         </form>
 NWEBFORM
 
+        my @ids=&Apache::lonnet::current_machine_ids();
+        my %select_menus;
+        my $numauthor = 0;
+        my $numcrsdirs = 0;
+        my $toppath = "/priv/$env{'user.domain'}/$env{'user.name'}"; 
+        if ($env{'user.author'}) {
+            $numauthor ++;
+            $select_menus{'author'}->{'text'} = &Apache::lonnet::plaintext('au');
+            if (grep(/^\Q$env{'user.home'}\E$/, at ids)) {
+                my $is_home = 1;
+                my %subdirs;
+                &recursedirs($is_home,'priv',$londocroot,$toppath,'',\%subdirs);
+                $select_menus{'author'}->{'default'} = '/'; 
+                $select_menus{'author'}->{'select2'}->{'/'} = '/';
+                my @ordered = ('/');
+                foreach my $relpath (sort { lc($a) cmp lc($b) } (keys(%subdirs))) {
+                    $select_menus{'author'}->{'select2'}->{$relpath} = $relpath;
+                    push(@ordered,$relpath);
+                }
+                $select_menus{'author'}->{'order'} = \@ordered;
+            } else {
+                $select_menus{'author'}->{'select2'}->{'switch'} = &mt('Switch server required');
+                $select_menus{'author'}->{'default'} = 'switch';
+                $select_menus{'author'}->{'order'} = ['switch'];
+            }
+        }
+        my %roleshash = &Apache::lonnet::get_my_roles($env{'user.name'},$env{'user.domain'},'userroles',
+                                                      ['active'],['ca','aa']);
+        my $crshome = $env{'course.'.$env{'request.course.id'}.'.home'};
+        my %by_roletype;
+        if (keys(%roleshash)) {
+            foreach my $entry (keys(%roleshash)) {
+                my ($auname,$audom,$roletype) = split(/:/,$entry);
+                my $key = $entry;
+                $key =~ s/:/___/g;
+                $by_roletype{$roletype}{$auname.'___'.$audom} = 1;
+                $select_menus{$key}->{'text'} = &Apache::lonnet::plaintext($roletype)." ($audom/$auname)";
+                my $rolehome = &Apache::lonnet::homeserver($auname,$audom);
+                if (grep(/^\Q$rolehome\E$/, at ids)) {    
+                    my $is_home = 1;
+                    my (%subdirs, at ordered);
+                    my $toppath="/priv/$audom/$auname";
+                    &recursedirs($is_home,'priv',$londocroot,$toppath,'',\%subdirs);
+                    $select_menus{$key}->{'default'} = '/';
+                    $select_menus{$key}->{'select2'}->{'/'} = '/';
+                    my @ordered = ('/');
+                    foreach my $relpath (sort { lc($a) cmp lc($b) } (keys(%subdirs))) {
+                        $select_menus{$key}->{'select2'}->{$relpath} = $relpath;
+                        push(@ordered,$relpath);
+                    }
+                    $select_menus{$key}->{'order'} = \@ordered;
+                } else {
+                    $select_menus{$key}->{'select2'}->{'switch'} = &mt('Switch server required');
+                    $select_menus{$key}->{'default'} = 'switch';
+                    $select_menus{$key}->{'order'} = ['switch'];
+                }
+                $numauthor ++;
+            }
+        }
+        my ($pickdir,$showtitle);;
+        if ($numauthor) {
+            my @order;
+            my $defrole;
+            if ($env{'user.author'}) {
+                push(@order,'author');
+                $defrole = 'author';
+            }
+            if (keys(%by_roletype)) {
+                foreach my $possrole ('ca','aa') {
+                    if (ref($by_roletype{$possrole}) eq 'HASH') {
+                        foreach my $author (sort { lc($a) cmp lc($b) } (keys(%{$by_roletype{$possrole}}))) {
+                            unless ($defrole) {
+                                $defrole = $author;
+                            }
+                            push(@order,$author.'___'.$possrole);
+                        }
+                    }
+                }
+            }
+            $select_menus{'course'}->{'text'} = &mt('Course Resource');
+            if (grep(/^\Q$crshome\E$/, at ids)) {
+                my $is_home = 1;
+                my %subdirs;
+                my $toppath="/priv/$coursedom/$coursenum";
+                &recursedirs($is_home,'priv',$londocroot,$toppath,'',\%subdirs);
+                $numcrsdirs = keys(%subdirs);
+                $select_menus{'course'}->{'default'} = '/';
+                $select_menus{'course'}->{'select2'}->{'/'} = '/';
+                my @ordered = ('/');
+                foreach my $relpath (sort { lc($a) cmp lc($b) } (keys(%subdirs))) {
+                    $select_menus{'course'}->{'select2'}->{$relpath} = $relpath;
+                    push(@ordered,$relpath);
+                }
+                $select_menus{'course'}->{'order'} = \@ordered;
+            } else {
+                $select_menus{'course'}->{'select2'}->{'switch'} = &mt('Switch server required');
+                $select_menus{'course'}->{'default'} = 'switch';
+                $select_menus{'course'}->{'order'} = ['switch'];
+            }
+            push(@order,'course');
+            $pickdir = $lt{'loca'}.
+                       &Apache::loncommon::linked_select_forms('courseresform','<br />'.$lt{'dire'},
+                                                               $defrole,'authorrole','authorpath',
+                                                               \%select_menus,\@order,'toggleCrsResTitle();',
+                                                               '','priv').'<br />';
+            $showtitle = 'none';
+        } else {
+            my $is_home;
+            $showtitle = 'inline';
+            if (grep(/^\Q$crshome\E$/, at ids)) {
+                $is_home = 1;
+                $pickdir .= '<input type="hidden" name="authorrole" value="course" />'; 
+                my $toppath="/priv/$coursedom/$coursenum'}";
+                my %subdirs;
+                &recursedirs($is_home,'priv',$londocroot,$toppath,'',\%subdirs);
+                $numcrsdirs = keys(%subdirs); 
+                if ($numcrsdirs) {
+                    $pickdir .= &mt('Directory: ').'<select name="authorpath">'."\n".
+                                 '<option value="/">/</option>'."\n";
+                    foreach my $key (sort { lc($a) cmp lc($b) } (keys(%subdirs))) {
+                        $pickdir .= '<option value="'.$relpath.'</option>'."\n";
+                    }
+                    $pickdir .= '</select>';
+                } else {
+                    $pickdir .= '<input type="hidden" name="authorpath" value="/" />'."\n";   
+                }
+            }
+        }
+
+        my %seltemplate_menus;
+        my @files = &Apache::lonhomework::get_template_list('problem');
+        my @noexamplelink = ('blank.problem','blank.library','script.library');
+        my $currentcategory = '';
+        my @ordered = ('');
+        my %templatehelp;
+        my $defcategory = '';
+        my @catorder = ($defcategory);
+        $seltemplate_menus{$defcategory}->{'order'} = [''];
+        $seltemplate_menus{$defcategory}->{'text'} = '';
+        foreach my $file (@files) {
+            if (ref($file) eq 'ARRAY') {
+                my ($path,$title,$category,$help) = @{$file};
+                next if ($title !~ /\S/);
+                if (&js_escape($category) ne $currentcategory) {
+                    $currentcategory = &js_escape($category);
+                    push(@catorder,&js_escape($currentcategory));
+                    $seltemplate_menus{$currentcategory}->{'text'} = $category;
+                    $seltemplate_menus{$currentcategory}->{'default'} = '';
+                    $seltemplate_menus{$currentcategory}->{'select2'}->{''} = '';
+                    push(@{$seltemplate_menus{$currentcategory}->{'order'}},'');
+                }
+                if ($path) {
+                    $seltemplate_menus{$currentcategory}->{'select2'}->{&js_escape($path)} = $title;
+                    push(@{$seltemplate_menus{$currentcategory}->{'order'}},&js_escape($path));
+                    if ($help) {
+                        $templatehelp{$path} = $help;
+                    }
+                }
+            }
+        }
+
+        my $templates = $lt{'cate'}.' '.
+                        &Apache::loncommon::linked_select_forms('courseresform','<br />'.$lt{'tmpl'}.' ',
+                                                                $defcategory,'tempcategory','template',
+                                                                \%seltemplate_menus,\@catorder,
+                                                                "resize_scrollbox('contentscroll','1','0');",
+                                                                "toggleExampleText();",'template').'<br />';
+        my $templatepreview =  '<a href="#" target="sample" onclick="javascript:getExample(600,420,\'yes\',true);  return false;">'.
+                               '<span id="newresexample">'.&mt('Example').'<span></a>';
+        my $crsresform=(<<RESFORM);
+        <a class="LC_menubuttons_link" href="javascript:toggleCrsRes('res','$numauthor','$numcrsdirs');">
+        $lt{'stpr'}</a>$help{'Course_Resource'}
+        <form action="/adm/coursedocs" method="post" name="courseresform">
+        <fieldset id="crsresform" style="display:none;">
+        <legend>$lt{'stpr'}</legend>
+        <input type="hidden" name="active" value="ee" />
+        <p>
+        $pickdir
+        <span class="LC_nobreak">$lt{'news'}? 
+        <label><input type="radio" name="newsubdir" value="0" onclick="toggleNewsubdir(this.form);" checked="checked" />No</label>
+         
+        <label><input type="radio" name="newsubdir" value="1" onclick="toggleNewsubdir(this.form);" />Yes</label>
+        </span><span id="newsubdir"></span>
+        <input type="hidden" name="newsubdirname" id="newsubdirname" value="" autocomplete="off" />
+        </p>
+        $lt{'fnam'}
+        <input type="text" size="20" name="newresourcename" autocomplete="off" />
+        <p>
+        <div id="newresource" style="display:$showtitle">
+        $lt{'addp'}
+        <label><input type="radio" name="newresourceadd" value="0" checked="checked" onclick="toggleNewInCourse(this.form);" />
+        $lt{'no'}</label>  
+        <label><input type="radio" name="newresourceadd" value="1" onclick="toggleNewInCourse(this.form);" />
+        $lt{'yes'}</label>
+        <span id="newrestitle"></span>
+        <input type="hidden" size="20" name="newresourcetitle" id="newresourcetitle" autocomplete="off" />
+        </div>
+        </p>
+        <p>
+        $lt{'uste'}
+        <label><input type="radio" name="newresusetemp" value="0" checked="checked" onclick="toggleWithTemplate(this.form);" />
+        $lt{'no'}</label>  
+        <label><input type="radio" name="newresusetemp" value="1" onclick="toggleWithTemplate(this.form);" />
+        $lt{'yes'}</label>
+        <div id="newrestemplate" style="display:none">
+        $templates
+        $templatepreview
+        </div>
+        </p>
+        <span class="LC_nobreak">
+        <input type="hidden" name="folderpath" value="$env{'form.folderpath'}" />
+        <input type="submit" name="newcrs" value="$lt{'crpr'}" />
+        </span>
+        </fieldset>
+        </form>
+
+RESFORM
 
 my $specialdocumentsform;
 my @specialdocumentsforma;
@@ -5601,7 +5967,7 @@
         {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/simpprob.png" alt="'.$lt{sipr}.'" onclick="javascript:makesmpproblem();" />'=>$newsmpproblemform},
         {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/dropbox.png" alt="'.$lt{drbx}.'" onclick="javascript:makedropbox();" />'=>$newdropboxform},
         {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/scoreupfrm.png" alt="'.$lt{scuf}.'" onclick="javascript:makeexamupload();" />'=>$newexuploadform},
-
+        {'<img class="LC_noBorder LC_middle" src="/res/adm/pages/simpprob.png" alt="'.$lt{stpr}.'" onclick="javascript:toggleCrsRes(\'res\','."'$numauthor','$numcrsdirs'".');" />'=>$crsresform},
         );
         $gradingform = &create_form_ul(&create_list_elements(@gradingforma));
 
@@ -5820,7 +6186,9 @@
                 &entryline(0,&mt("Click to download or use your browser's Save Link function"),$showdoc).'</table>');
   }
  }
- $r->print(&Apache::loncommon::end_page());
+ unless ($noendpage) { 
+     $r->print(&Apache::loncommon::end_page());
+ }
  return OK;
 }
 
@@ -6161,7 +6529,7 @@
 }
 
 sub editing_js {
-    my ($udom,$uname,$supplementalflag,$posslti) = @_;
+    my ($udom,$uname,$supplementalflag,$coursedom,$coursenum,$posslti,$londocroot) = @_;
     my %js_lt = &Apache::lonlocal::texthash(
                                           p_mnf => 'Name of New Folder',
                                           t_mnf => 'New Folder',
@@ -6173,6 +6541,7 @@
                                           p_mdb => 'Title for the Drop Box',
                                           p_mbb => 'Title for the Discussion Board',
                                           p_mwp => 'Title for Web Page',
+                                          p_mnr => 'Title for the Resource',
                                           p_mab => "Enter user:domain for User's Personal Information Page",
                                           p_mab2 => 'Personal Information Page of ',
                                           p_mab_alrt1 => 'Not a valid user:domain',
@@ -6201,6 +6570,9 @@
                                           noor    => 'No actions selected or changes to settings specified.',
                                           noch    => 'No changes to settings specified.',
                                           noac    => 'No actions selected.',
+                                          nofi    => 'No file selected',
+                                          tinc    => 'Title in course',
+                                          sunm    => 'Sub-directory name',
                                         );
     &js_escape(\%js_lt);
     my $crstype = &Apache::loncommon::course_type();
@@ -6391,6 +6763,186 @@
     return;
 }
 
+function toggleCrsRes(caller,numauthorrole,numcrsdirs) {
+    var disp = 'none';
+    if (document.getElementById('crsresform')) {
+        if (caller == 'res') {
+            var curr = document.getElementById('crsresform').style.display;
+            if (curr == 'none') {
+                disp='block';
+                numauthor = parseInt(numauthorrole);
+                if (numauthor > 0) {
+                    document.courseresform.authorrole.selectedIndex = 0;
+                    select1priv_changed();
+                    document.courseresform.authorpath.selectedIndex = 0;
+                    document.courseresform.newresourceadd.selectedIndex = 0;
+                    toggleNewInCourse(document.courseresform);
+                    if (document.getElementById('newresource')) {
+                        document.getElementById('newresource').style.display = 'none';
+                    }
+                } else {
+                    if (numcrsdirs) {
+                        document.courseresform.authorpath.selectedIndex = 0;
+                    }
+                }
+                if (document.courseresform.newresusetemp.length) {
+                    document.courseresform.newresusetemp[0].checked = true;
+                    toggleWithTemplate(document.courseresform);
+                }
+                document.courseresform.newresourcename.value = ''; 
+            }
+        }
+        if (document.courseresform.newsubdir.length) {
+            for (var j=0; j<document.courseresform.newsubdir.length; j++) {
+                if (document.courseresform.newsubdir[j].value == 0) {
+                    document.courseresform.newsubdir[j].checked = true;
+                }
+                break;
+            }
+            if (document.getElementById('newsubdirname')) {
+                document.getElementById('newsubdirname').type = "hidden";
+                document.getElementById('newsubdirname').value = "";
+            }
+            if (document.getElementById('newsubdir')) {
+                document.getElementById('newsubdir').innerHTML = "";
+            }
+        }
+        document.getElementById('crsresform').style.display=disp;
+        resize_scrollbox('contentscroll','1','0');
+    }
+    return;
+}
+
+function toggleNewsubdir(form) {
+    if (form.newsubdir.length) {
+        for (var j=0; j<form.newsubdir.length; j++) {
+            if (form.newsubdir[j].checked) {
+                if (document.getElementById('newsubdirname')) {
+                    if (form.newsubdir[j].value == '1') {
+                        document.getElementById('newsubdirname').type = "text"; 
+                        if (document.getElementById('newsubdir')) {
+                            document.getElementById('newsubdir').innerHTML = '<br />$js_lt{'sunm'}';
+                        }
+                    } else {
+                        document.getElementById('newsubdirname').type = "hidden";
+                        document.getElementById('newsubdirname').value = "";
+                        document.getElementById('newsubdir').innerHTML = "";
+                    }
+                }
+                break;
+            }
+        }
+    }
+}
+
+function toggleCrsResTitle() {
+    if (document.getElementById('newresource')) {
+        if (document.courseresform.authorrole.options[document.courseresform.authorrole.selectedIndex].value == 'course') {
+            document.getElementById('newresource').style.display = 'inline';
+            document.courseresform.newresourceadd[0].checked = true;
+            toggleNewInCourse(document.courseresform);
+        } else {
+            document.getElementById('newresource').style.display = 'none';
+        }
+    } 
+}
+
+function toggleNewInCourse(form) {
+    if (form.newresourceadd.length) {
+        for (var i=0; i<form.newresourceadd.length; i++) {
+            if (form.newresourceadd[i].checked) {
+                if (document.getElementById('newresourcetitle')) {
+                    if (form.newresourceadd[i].value == '1') {
+                        document.getElementById('newresourcetitle').type = 'text';
+                        if (document.getElementById('newrestitle')) {
+                            document.getElementById('newrestitle').innerHTML = "<br />$js_lt{'tinc'}";
+                        }
+                    } else {
+                        document.getElementById('newresourcetitle').type = 'hidden';
+                        document.getElementById('newresourcetitle').value = '';
+                        if (document.getElementById('newrestitle')) { 
+                            document.getElementById('newrestitle').innerHTML = '';
+                        }
+                    }
+                }
+                break;
+            }
+        }
+    }
+}
+
+function toggleWithTemplate(form) {
+    if (form.newresusetemp.length) {
+        for (var i=0; i<form.newresusetemp.length; i++) {
+            if (form.newresusetemp[i].checked) {
+                if (document.getElementById('newrestemplate')) { 
+                    if (form.newresusetemp[i].value == '1') {
+                        document.getElementById('newrestemplate').style.display = 'inline';
+                        toggleExampleText();
+                    } else {
+                        form.tempcategory.selectedIndex = 0;
+                        select1template_changed();
+                        document.getElementById('newrestemplate').style.display = 'none';
+                    }
+                }
+            }
+        }
+    }
+}
+
+function toggleExampleText() {
+    if (document.getElementById('newresexample')) {
+        var url = document.courseresform.template.options[document.courseresform.template.selectedIndex].value;
+        if (url == '') {
+            document.getElementById('newresexample').style.fontWeight = 'normal';
+        } else {
+            document.getElementById('newresexample').style.fontWeight = 'bold';
+        }
+    }
+}
+
+function getExample(width,height,scrolling,transparency) {
+    var url;
+    if (document.courseresform.newresusetemp.length) {
+        for (var i=0; i<document.courseresform.newresusetemp.length; i++) {
+            if (document.courseresform.newresusetemp[i].checked) {
+                if (document.courseresform.newresusetemp[i].value == '1') {
+                    var url = document.courseresform.template.options[document.courseresform.template.selectedIndex].value;
+                    if (url == '') {
+                        alert('Pick a category and template');
+                    } else {
+                        url = url.replace("$londocroot",""); 
+                        url += '?inhibitmenu=yes';
+                    }
+                }
+                break;
+            }
+        }
+    }
+    if (url != '') {
+        openMyModal(url,width,height,scrolling,transparency,'');
+    }
+}
+
+function toggleImportCrsres(caller,dircount) {
+    var disp = 'none';
+    if (document.getElementById('importcrsresform')) {
+        if (caller == 'res') {
+            var numdirs = parseInt(dircount);
+            var curr = document.getElementById('importcrsresform').style.display;
+            if (curr == 'none') {
+                disp='block';
+                if (numdirs > 1) {
+                    select1res_changed();
+                }
+            }
+        }
+        document.getElementById('importcrsresform').style.display=disp;
+        resize_scrollbox('contentscroll','1','0');
+    }
+    return;
+}
+
 function makeims(imsform) {
     if ((imsform.uploaddoc.value == '')  || (!imsform.uploaddoc.value)) {
         alert("$js_lt{'imsfile'}");
@@ -6752,6 +7304,8 @@
             activeTab = ''; 
             toggleUpload();
             toggleMap();
+            toggleCrsRes();
+            toggleImportCrsres();
             resize_scrollbox('contentscroll','1','0');
             return;
         } else {
@@ -6762,6 +7316,8 @@
         activeTab = pageId;
         toggleUpload();
         toggleMap();
+        toggleCrsRes();
+        toggleImportCrsres();
         if (nav == 'mainnav') {
             var storedpath = "$docs_folderpath";
             var storedpage = "$main_container_page";
@@ -7125,6 +7681,33 @@
     return;
 }
 
+function validImportCrsRes() {
+    var path =  document.crsresimportform.coursepath.options[document.crsresimportform.coursepath.selectedIndex].value;
+    var fname = document.crsresimportform.coursefile.options[document.crsresimportform.coursefile.selectedIndex].value;
+    if ((fname == '') || (fname == null)) {
+        alert("$js_lt{'nofi'}");
+        return false;
+    }
+    var url = '/res/$coursedom/$coursenum/';
+    if (path && path != '/') {
+        url += path+'/';
+    }
+    if (fname != '') {
+        url += fname;
+    }
+    var title = document.crsresimportform.crsrestitle.value;
+    document.crsresimportform.importdetail.value=escape(title)+'='+escape(url);
+    return true;
+}
+
+function validateNewRes(caller) {
+    if (caller == 'single') {
+        var role = document.courseresform.authorrole.options[document.courseresform.authorrole.selectedIndex].value; 
+        var authorpath = document.courseresform.authorpath.options[document.courseresform.authorpath.selectedIndex].value;
+        var resname = document.courseresform.newresourcename.value;
+    }
+}
+
 ENDNEWSCRIPT
 }
 
@@ -7255,6 +7838,338 @@
 SIMPFORM
 }
 
+sub recursedirs {
+    my ($is_home,$context,$docroot,$toppath,$relpath,$dirhashref,$filehashref) = @_;
+    return unless (ref($dirhashref) eq 'HASH');
+    my $currpath = $docroot.$toppath;
+    if ($relpath) {
+        $currpath .= "/$relpath";
+    }
+    my $savefile;
+    if (ref($filehashref)) {
+        $savefile = 1;
+    }
+    if ($is_home) {
+        if (opendir(my $dirh,$currpath)) {
+            foreach my $item (sort { lc($a) cmp lc($b) } grep(!/^\.+$/,readdir($dirh))) { 
+                next if ($item eq '');
+                if (-d "$currpath/$item") {
+                    my $newpath;
+                    if ($relpath) {
+                        $newpath = "$relpath/$item";
+                    } else {
+                        $newpath = $item;
+                    }
+                    $dirhashref->{&js_escape($newpath)} = 1;
+                    &recursedirs($is_home,$context,$docroot,$toppath,$newpath,$dirhashref,$filehashref);
+                } elsif ($savefile) {
+                    if ($context eq 'priv') {
+                        unless ($item =~ /\.(meta|save|log|bak|DS_Store)$/) {
+                            $filehashref->{&js_escape($relpath)}{$item} = 1;
+                        }
+                    } else {
+                        unless (($item =~ /\.meta$/) || ($item =~ /\.\d+\.\w+$/) || ($item =~ /\.rights$/)) {
+                            $filehashref->{&js_escape($relpath)}{$item} = 1;
+                        }
+                    }
+                }
+            }
+            closedir($dirh);
+        }
+    } else {
+        my ($dirlistref,$listerror) =
+            &Apache::lonnet::dirlist($toppath.$relpath);
+        my @dir_lines;
+        my $dirptr=16384;
+        if (ref($dirlistref) eq 'ARRAY') {
+            foreach my $dir_line (sort
+                              {
+                                  my ($afile)=split('&',$a,2);
+                                  my ($bfile)=split('&',$b,2);
+                                  return (lc($afile) cmp lc($bfile));
+                              } (@{$dirlistref})) {
+                my ($item,$dom,undef,$testdir,undef,undef,undef,undef,$size,undef,$mtime,undef,undef,undef,$obs,undef) =
+                    split(/\&/,$dir_line,16);
+                $item =~ s/\s+$//;
+                next if (($item =~ /^\.\.?$/) || ($obs));
+                if ($dirptr&$testdir) {
+                    my $newpath;
+                    if ($relpath) {
+                        $newpath = "$relpath/$item";
+                    } else {
+                        $relpath = '/';
+                        $newpath = $item;
+                    }
+                    $dirhashref->{&js_escape($newpath)} = 1;
+                    &recursedirs($is_home,$context,$docroot,$toppath,$newpath,$dirhashref,$filehashref);                         
+                } elsif ($savefile) {
+                    if ($context eq 'priv') {
+                        unless ($item =~ /\.(meta|save|log|bak|DS_Store)$/) {
+                            $filehashref->{$relpath}{$item} = 1;
+                        }
+                    } else {
+                        unless (($item =~ /\.meta$/) || ($item =~ /\.\d+\.\w+$/)) {
+                            $filehashref->{$relpath}{$item} = 1;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return;
+}
+
+sub makenewproblem {
+    my ($r,$coursedom,$coursenum) = @_;
+# Creating a new problem
+    my ($redirect,$error);
+    if ($env{'form.authorrole'}) {
+        my ($newsubdir,$filename);
+        if ($env{'form.newsubdir'}) {
+            if ($env{'form.newsubdirname'} ne '') {
+                $newsubdir = $env{'form.newsubdirname'};
+            }    
+        }
+        if ($env{'form.newresourcename'}) {
+            $filename = $env{'form.newresourcename'};
+            $filename =~ s/\.(\d+)(\.\w+)$/$2/;
+            $filename =~ s/`//g;
+            $filename =~ s{/\.\./}{_}g;
+            $filename =~ s/\.+/./g;
+            $filename =~ s{/+}{_}g;
+            if ($filename ne '') {
+                my ($name,$ext) = ($filename =~ /(.+)\.([^.]+)$/);
+                if (($ext) && ($ext ne '.problem')) {
+                    $filename = $name.'.problem';
+                } elsif ($ext eq '') {
+                    $filename .= '.problem';
+                }
+                my $docroot = $r->dir_config('lonDocRoot');
+                my @ids=&Apache::lonnet::current_machine_ids();
+                if ($env{'form.authorrole'} eq 'author') {
+                    if ($env{'user.author'}) {
+                        if ($env{'user.home'} && grep(/^\Q$env{'user.home'}\E$/, at ids)) {
+                            my $url = "/priv/$env{'user.domain'}/$env{'user.name'}";
+                            my $path = $docroot.$url;
+                            my $subdir = $env{'form.authorpath'};
+                            $redirect = &finishnewprob($url,$path,$subdir,$newsubdir,$filename);
+                        }
+                    }
+                } elsif ($env{'form.authorrole'} eq 'course') {
+                    my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
+                    if ($chome && grep(/^\Q$chome\E$/, at ids)) {
+                        my $url = "/priv/$coursedom/$coursenum";
+                        my $path=$docroot.$url;
+                        my $subdir = $env{'form.authorpath'};
+                        $redirect = &finishnewprob($url,$path,$subdir,$newsubdir,$filename);
+                        if ($redirect) {
+                            my $rightsfile = 'default.rights';
+                            my $sourcerights = "$path/$rightsfile";
+                            my $targetrights = $docroot."/res/$coursedom/$coursenum/$rightsfile";
+                            my $now = time;
+                            if (!-e $sourcerights) {
+                                my $cid = $coursedom.'_'.$coursenum;
+                                if (open(my $fh,">$sourcerights")) {
+                                    print $fh <<END;
+<accessrule effect="deny" realm="" type="course" role="" />
+<accessrule effect="allow" realm="$cid" type="course" role="" />
+END
+                                    close($fh);
+                                }
+                            }
+                            if (!-e "$sourcerights.meta") {
+                                if (open(my $fh,">$sourcerights.meta")) {
+                                    my $author=$env{'environment.firstname'}.' '.
+                                               $env{'environment.middlename'}.' '.
+                                               $env{'environment.lastname'}.' '.
+                                               $env{'environment.generation'};
+                                    $author =~ s/\s+$//;
+                                    print $fh <<"END";
+
+<abstract></abstract>
+<author>$author</author>
+<authorspace>$coursenum:$coursedom</authorspace>
+<copyright>private</copyright>
+<creationdate>$now</creationdate>
+<customdistributionfile></customdistributionfile>
+<dependencies></dependencies>
+<domain>$coursedom</domain>
+<highestgradelevel>0</highestgradelevel>
+<keywords></keywords>
+<language>notset </language>
+<lastrevisiondate>$now</lastrevisiondate>
+<lowestgradelevel>0</lowestgradelevel>
+<mime>rights</mime>
+<modifyinguser>$env{'user.name'}:$env{'user.domain'}</modifyinguser>
+<notes></notes>
+<obsolete></obsolete>
+<obsoletereplacement></obsoletereplacement>
+<owner>$coursenum:$coursedom</owner>
+<rule>deny:::course,allow:$cid::course</rule>
+<sourceavail></sourceavail>
+<standards></standards>
+<subject></subject>
+<title></title>
+END
+                                        close($fh);
+                                }
+                                if ((-e $sourcerights) && (-e "$sourcerights.meta")) {
+                                    if (!-e "$docroot/res/$coursedom") {
+                                        mkdir("$docroot/res/$coursedom",0755);
+                                    }
+                                    if (!-e "$docroot/res/$coursedom/$coursenum") {
+                                        mkdir("$docroot/res/$coursedom/$coursenum",0755);
+                                    }
+                                    if ((-e "$docroot/res/$coursedom/$coursenum") && (!-e $targetrights)) {
+                                        my $nokeyref = &Apache::lonpublisher::getnokey($r->dir_config('lonIncludes'));
+                                        my $output = &Apache::lonpublisher::batchpublish($r,$sourcerights,$targetrights,$nokeyref,1);
+                                    }
+                                }
+                            }
+                            if ($env{'form.newresourceadd'}) {
+                                my $template = $env{'form.template'};
+                                my $source = $docroot.$redirect;
+                                my $target = $redirect;
+                                $target =~ s{^/priv/}{/res/};
+                                $target = $docroot.$target;
+                                if (!-e $source) {
+                                    my $copyfrom; 
+                                    if ($template) {
+                                        my %templates;
+                                        my @files = &Apache::lonhomework::get_template_list('problem');
+                                        foreach my $poss (@files) {
+                                            if (ref($poss) eq 'ARRAY') {
+                                                if ($template eq $poss->[0]) {
+                                                    $templates{$template} = 1;
+                                                    last;
+                                                }
+                                            }
+                                        }
+                                        if ($templates{$template}) {
+                                            $copyfrom = $template;
+                                        }
+                                    }
+                                    unless ($copyfrom) {
+                                        $copyfrom = $r->dir_config('lonIncludes').'/templates/blank.problem';
+                                    }
+                                    &File::Copy::copy($copyfrom,$source);
+                                }
+                                if (!-e "$source.meta") {
+                                    my $cid = $coursedom.'_'.$coursenum;
+                                    my $now = time;
+                                    if (open(my $fh,">$source.meta")) {
+                                        my $author=$env{'environment.firstname'}.' '.
+                                                   $env{'environment.middlename'}.' '.
+                                                   $env{'environment.lastname'}.' '.
+                                                   $env{'environment.generation'};
+                                        $author =~ s/\s+$//;
+                                        my $title = $env{'form.newresourcetitle'};
+                                        $title =~ s/^\s+|\s+$//g;
+                                        print $fh <<END;
+
+<abstract></abstract>
+<author>$author</author>
+<authorspace>$coursenum:$coursedom</authorspace>
+<copyright>custom</copyright>
+<creationdate>$now</creationdate>
+<customdistributionfile>/res/$coursedom/$coursenum/default.rights</customdistributionfile>
+<dependencies></dependencies>
+<domain>$coursedom</domain>
+<highestgradelevel>0</highestgradelevel>
+<keywords></keywords>
+<language>notset </language>
+<lastrevisiondate>$now</lastrevisiondate>
+<lowestgradelevel>0</lowestgradelevel>
+<mime>problem</mime>
+<modifyinguser>$coursenum:$coursedom</modifyinguser>
+<notes></notes>
+<obsolete></obsolete>
+<obsoletereplacement></obsoletereplacement>
+<owner>$coursenum:$coursedom</owner>
+<sourceavail></sourceavail>
+<standards></standards>
+<subject></subject>
+<title>$title</title>
+END
+                                        close($fh);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                } else {
+                    my ($auname,$audom,$role) = split('___',$env{'form.authorrole'});
+                    my $rolehome = &Apache::lonnet::homeserver($auname,$audom);
+                    if (grep(/^\Q$rolehome\E$/, at ids)) {
+                        my $now = time;
+                        if (exists($env{'user.role.'.$role.'./'.$audom.'/'.$auname})) {
+                            my ($start,$end) = split(/\./,$env{'user.role.'.$role.'./'.$audom.'/'.$auname});
+                            if (($start <= $now) && (($end == 0) || ($end >= $now))) { 
+                                my $url = "/priv/$audom/$auname";  
+                                my $path = $r->dir_config('lonDocRoot').$url;
+                                my $subdir = $env{'form.authorpath'};
+                                $redirect = &finishnewprob($url,$path,$subdir,$newsubdir,$filename);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return ($redirect,$error);
+}
+
+sub finishnewprob {
+    my ($url,$path,$subdir,$newsubdir,$filename) = @_;
+    my $redirect;
+    if ($subdir ne '/') {
+        $subdir = &cleandir($subdir);
+        if (($subdir ne '') && (-d "$path/$subdir")) {
+            $path .= "/$subdir";
+            $url .= "/$subdir";
+        }
+    }
+    my $dest;
+    if ($newsubdir ne '') {
+        $newsubdir = &cleandir($newsubdir);
+    }
+    if ($newsubdir ne '') {
+        if (-d "$path/$newsubdir") {
+            $dest = "$path/$newsubdir/$filename";
+        } else {
+            my $dirok;
+            unless (-e "$path/$newsubdir") {
+                if (mkdir("$path/$newsubdir",02770)) {
+                    if (chmod(02770,"$path/$newsubdir")) {
+                        $dirok = 1;
+                    }
+                }
+            }
+            if ($dirok) {
+                $dest = "$path/$newsubdir/$filename";
+            }
+        }
+        if (($dest ne '') && (!-e $dest)) {
+            $redirect = "$url/$newsubdir/$filename";
+        }
+    } else {
+        $dest = "$path/$filename";
+        if (($dest ne '') && (!-e $dest)) {
+            $redirect = "$url/$filename";
+        }
+    }
+    return $redirect;
+}
+
+sub cleandir {
+    my ($dir) = @_;
+    $dir =~ s/^\s+//;
+    $dir =~ s/\s+$//;
+    $dir =~ s/\.+//g;
+    $dir =~ s/[\#\?&%\":]//g;
+    return $dir;
+}
+
 1;
 __END__
 
Index: loncom/interface/loncommon.pm
diff -u loncom/interface/loncommon.pm:1.1245 loncom/interface/loncommon.pm:1.1246
--- loncom/interface/loncommon.pm:1.1245	Wed Jun 15 17:20:44 2016
+++ loncom/interface/loncommon.pm	Sun Jun 19 04:27:49 2016
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # a pile of common routines
 #
-# $Id: loncommon.pm,v 1.1245 2016/06/15 17:20:44 raeburn Exp $
+# $Id: loncommon.pm,v 1.1246 2016/06/19 04:27:49 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -5426,10 +5426,20 @@
         $lastitem = $thisdisfn;
     }
 
+    my ($crsauthor,$title);
+    if (($env{'request.course.id'}) &&
+        ($env{'course.'.$env{'request.course.id'}.'.num'} eq $uname) &&
+        ($env{'course.'.$env{'request.course.id'}.'.num'} eq $uname)) {
+        $crsauthor = 1;
+        $title = &mt('Course Authoring Space');
+    } else {
+        $title = &mt('Authoring Space');
+    }
+
     my $output =
          '<div>'
         .&Apache::loncommon::help_open_menu('','',3,'Authoring') #FIXME: Broken? Where is it?
-        .'<b>'.&mt('Authoring Space:').'</b> '
+        .'<b>'.$title.'</b> '
         .'<form name="dirs" method="post" action="'.$formaction
         .'" target="_top">' #FIXME lonpubdir: target="_parent"
         .&Apache::lonhtmlcommon::crumbs($uname.'/'.$parentpath,'_top','/priv/'.$udom,undef,undef);
@@ -5441,13 +5451,17 @@
             .'</span>';
     }
 
-    $output .=
-         '<br />'
-        #FIXME lonpubdir: &Apache::lonhtmlcommon::crumbs($uname.$thisdisfn.'/','_top','/priv','','+1',1)."</b></tt><br />"
-        .&Apache::lonhtmlcommon::select_recent('construct','recent','this.form.action=this.form.recent.value;this.form.submit()')
-        .'</form>'
-        .&Apache::lonmenu::constspaceform()
-        .'</div>';
+    if ($crsauthor) {
+        $output .= '</form>'.&Apache::lonmenu::constspaceform();
+    } else {
+        $output .=
+             '<br />'
+            #FIXME lonpubdir: &Apache::lonhtmlcommon::crumbs($uname.$thisdisfn.'/','_top','/priv','','+1',1)."</b></tt><br />"
+            .&Apache::lonhtmlcommon::select_recent('construct','recent','this.form.action=this.form.recent.value;this.form.submit()')
+            .'</form>'
+            .&Apache::lonmenu::constspaceform();
+    }
+    $output .= '</div>';
 
     return $output;
 }
Index: loncom/interface/lonindexer.pm
diff -u loncom/interface/lonindexer.pm:1.224 loncom/interface/lonindexer.pm:1.225
--- loncom/interface/lonindexer.pm:1.224	Sat Jun 18 16:15:38 2016
+++ loncom/interface/lonindexer.pm	Sun Jun 19 04:27:50 2016
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Directory Indexer
 #
-# $Id: lonindexer.pm,v 1.224 2016/06/18 16:15:38 raeburn Exp $
+# $Id: lonindexer.pm,v 1.225 2016/06/19 04:27:50 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -710,6 +710,19 @@
 	#This is a kludge, sorry aboot this
 	my ($strip,$dom,undef,$testdir,undef,undef,undef,undef,undef,undef,undef,undef,undef,undef,$obs,undef)=split(/\&/,$line,16); 
 	next if (($strip =~ /\.meta$/) || ($obs));
+        if ($dom ne 'domain') {
+            my ($udom,$uname);
+            if ($dom eq 'user') {
+                ($udom) = ($startdir =~ m{^/res/($match_domain)});
+                $uname = $strip;
+            } else {
+                ($udom,$uname) = ($startdir =~ m{^/res/($match_domain)/($match_courseid)});
+            }
+            if ($udom ne '' && $uname ne '') {
+                # Don't display "course author" directory.
+                next if (&Apache::lonnet::is_course($udom,$uname));
+            }
+        }
 	my (@fileparts) = split(/\./,$strip);
 	if ($hash{'display_attrs_9'} != 1) {
             # if not all versions to be shown
Index: loncom/interface/lonmenu.pm
diff -u loncom/interface/lonmenu.pm:1.450 loncom/interface/lonmenu.pm:1.451
--- loncom/interface/lonmenu.pm:1.450	Thu Jun  2 01:43:46 2016
+++ loncom/interface/lonmenu.pm	Sun Jun 19 04:27:50 2016
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Routines to control the menu
 #
-# $Id: lonmenu.pm,v 1.450 2016/06/02 01:43:46 raeburn Exp $
+# $Id: lonmenu.pm,v 1.451 2016/06/19 04:27:50 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -812,7 +812,11 @@
             if ($currdir =~ m-/$-) {
                 $is_const_dir = 1;
                 if ($thisdisfn eq '') {
-                    $is_const_dir = 2;
+                    unless (($env{'request.course.id'}) && 
+                            ($env{'course.'.$env{'request.course.id'}.'.num'} eq $uname) &&
+                            ($env{'course.'.$env{'request.course.id'}.'.domain'} eq $udom)) { 
+                        $is_const_dir = 2;
+                    }
                 }
             } else {
                 $currdir =~ s|[^/]+$||;
Index: loncom/publisher/lonpublisher.pm
diff -u loncom/publisher/lonpublisher.pm:1.296 loncom/publisher/lonpublisher.pm:1.297
--- loncom/publisher/lonpublisher.pm:1.296	Sun Jun 19 01:08:01 2016
+++ loncom/publisher/lonpublisher.pm	Sun Jun 19 04:27:57 2016
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Publication Handler
 #
-# $Id: lonpublisher.pm,v 1.296 2016/06/19 01:08:01 raeburn Exp $
+# $Id: lonpublisher.pm,v 1.297 2016/06/19 04:27:57 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -1875,17 +1875,27 @@
     $metadatafields{'url'} = $distarget;
     $metadatafields{'version'} = 'current';
 
-    my ($error,$success) = &store_metadata(%metadatafields);
-    if ($success) {
-	$output .= '<p>'.&mt('Synchronized SQL metadata database').'</p>';
-	print $logfile "\nSynchronized SQL metadata database";
-    } else {
-	$output .= $error;
-	print $logfile "\n".$error;
+    my $crsauthor;
+    if ($env{'request.course.id'}) {
+        my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+        my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+        if ($distarget =~ m{^/res/$cdom/$cnum}) {
+            $crsauthor = 1;
+        }
     }
-    unless ($usebuffer) {
-        $r->print($output);
-        $output = '';
+    unless ($crsauthor) {
+        my ($error,$success) = &store_metadata(%metadatafields);
+        if ($success) {
+	    $output .= '<p>'.&mt('Synchronized SQL metadata database').'</p>';
+	    print $logfile "\nSynchronized SQL metadata database";
+        } else {
+	    $output .= $error;
+	    print $logfile "\n".$error;
+        }
+        unless ($usebuffer) {
+            $r->print($output);
+            $output = '';
+        }
     }
 # --------------------------------------------- Delete author resource messages
     my $delresult=&Apache::lonmsg::del_url_author_res_msg($target); 
Index: loncom/publisher/lonpubdir.pm
diff -u loncom/publisher/lonpubdir.pm:1.168 loncom/publisher/lonpubdir.pm:1.169
--- loncom/publisher/lonpubdir.pm:1.168	Fri Jun 10 22:31:34 2016
+++ loncom/publisher/lonpubdir.pm	Sun Jun 19 04:27:58 2016
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Authoring Space Directory Lister
 #
-# $Id: lonpubdir.pm,v 1.168 2016/06/10 22:31:34 raeburn Exp $
+# $Id: lonpubdir.pm,v 1.169 2016/06/19 04:27:58 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -82,21 +82,33 @@
         }
     }
     $thisdisfn=~s/^\Q$docroot\E\/priv//;
-    
+
     my $resdir=$docroot.'/res'.$thisdisfn; # Resource directory
     my $targetdir='/res'.$thisdisfn; # Publication target directory.
     my $linkdir='/priv'.$thisdisfn;      # Full URL name of constr space.
 
+    my $cstr = 'author';
+    my ($crsauthor,$crstype);
+    if ($env{'request.course.id'}) {
+        my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+        my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+        if ($thisdisfn =~ m{^/\Q$cdom/$cnum\E}) {
+            $crsauthor = 1;
+            $cstr = 'course';
+            $crstype = &Apache::loncommon::course_type();
+        }
+    }
+
     my %bombs=&Apache::lonmsg::all_url_author_res_msg($uname,$udom);
 
     my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'};
     my $current_disk_usage = &Apache::lonnet::diskusage($udom,$uname,
                                 "$londocroot/priv/$udom/$uname"); # expressed in kB
     my $disk_quota = &Apache::loncommon::get_user_quota($uname,$udom,
-                                'author'); # expressed in MB
+                                                 $cstr,$crstype); # expressed in MB
 
     # Put out the start of page.
-    &startpage($r, $uname, $udom, $thisdisfn, $current_disk_usage, $disk_quota); 
+    &startpage($r, $uname, $udom, $thisdisfn, $current_disk_usage, $disk_quota, $crsauthor); 
 
     if (!-d $fn) {
         if (-e $fn) {
@@ -348,19 +360,27 @@
 #      $thisdisfn - Displayable version of the filename.
 #      $current_disk_usage - User's current disk usage (in kB).
 #      $disk_quota - Disk quota for user's authoring space (in MB).
+#      $crstype - Course type, if this is for "course author"
 
 sub startpage {
-    my ($r, $uname, $udom, $thisdisfn, $current_disk_usage, $disk_quota) = @_;
+    my ($r, $uname, $udom, $thisdisfn, $current_disk_usage, $disk_quota, $crsauthor) = @_;
     &Apache::loncommon::content_type($r,'text/html');
     $r->send_http_header;
 
     my $formaction='/priv'.$thisdisfn.'/';
     $formaction=~s|/+|/|g;
-    &Apache::lonhtmlcommon::store_recent('construct',$formaction,$formaction);
+
+    my $title;
+    if ($crsauthor) {
+        $title = 'Course Authoring';
+    } else {
+        $title = 'Authoring Space';
+        &Apache::lonhtmlcommon::store_recent('construct',$formaction,$formaction);
+    }
 
     &Apache::lonhtmlcommon::clear_breadcrumbs();
     &Apache::lonhtmlcommon::add_breadcrumb({
-        'text'  => 'Authoring Space',
+        'text'  => $title,
         'href'  => &Apache::loncommon::authorspace($formaction),
     });
     # breadcrumbs (and tools) will be created 
@@ -369,7 +389,7 @@
     $env{'request.noversionuri'}=$formaction;
     my $js = '<script type="text/javascript" 
                 src="/res/adm/includes/file_upload.js"></script>';
-    $r->print(&Apache::loncommon::start_page('Authoring Space', $js));
+    $r->print(&Apache::loncommon::start_page($title, $js));
 
     $disk_quota = 1024 * $disk_quota; # convert from MB to kB
 
@@ -381,7 +401,7 @@
                     .&Apache::loncommon::CSTR_pageheader()));
 
     my $esc_thisdisfn = &Apache::loncommon::escape_single($thisdisfn);
-    my $doctitle = 'LON-CAPA '.&mt('Authoring Space');
+    my $doctitle = 'LON-CAPA '.&mt($title);
     my $newname = &mt('New Name');
     my $pubdirscript=(<<ENDPUBDIRSCRIPT);
 <script type="text/javascript">
Index: loncom/publisher/lonunauthorized.pm
diff -u loncom/publisher/lonunauthorized.pm:1.17 loncom/publisher/lonunauthorized.pm:1.18
--- loncom/publisher/lonunauthorized.pm:1.17	Fri Jun  7 16:07:49 2013
+++ loncom/publisher/lonunauthorized.pm	Sun Jun 19 04:27:58 2016
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # Unauthorized to access construction space
 #
-# $Id: lonunauthorized.pm,v 1.17 2013/06/07 16:07:49 bisitz Exp $
+# $Id: lonunauthorized.pm,v 1.18 2016/06/19 04:27:58 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -203,15 +203,51 @@
         my $realownerhome=
 	    &Apache::lonnet::homeserver($realownername,$realownerdom);
         unless ($realownerhome eq 'no_host') {
-            my $plainname=&Apache::loncommon::plainname($realownername,$realownerdom);
-            my $user=$realownername.':'.$realownerdom;
-            my $userlink=&Apache::loncommon::aboutmewrapper(
-                             $plainname.' ('.$user.')'
-                            ,$realownername
-                            ,$realownerdom);
-	    $r->print('<p>'
-                     .&mt('Contact [_1] for access.',$userlink)
-                     .'</p>');
+            if (&Apache::lonnet::is_course($realownerdom,$realownername)) {
+                my $ccrole = 'cc';
+                my %crsenv = &Apache::lonnet::coursedescription("$realownerdom/$realownername",{one_time => 1});
+                my $cdesc = $crsenv{'description'};
+                my $crstype = $crsenv{'type'};
+                if ($crstype eq 'Community') {
+                    $ccrole = 'co';
+                }
+                my $rolename = $crsenv{$ccrole.'.plaintext'};
+                if ($rolename eq '') {
+                    $rolename = &Apache::lonnet::plaintext($ccrole,$crstype,$realownerdom.'_'.$realownername,1);
+                }
+                my $allowed = &Apache::lonnet::allowed('mdc',$realownerdom.'_'.$realownername);
+                if (!$allowed) {
+                    my %roleshash = &Apache::lonnet::get_my_roles('','','userroles',['active'],
+                                                                  [$ccrole],[$realownerdom]);
+                    if (exists($roleshash{$realownername.':'.$realownerdom.':'.$ccrole})) {
+                        $r->print(&mt('[_1]Switch role[_2] for access',
+                                      '<a href="/adm/roles?selectrole=1&'.
+                                      &HTML::Entities::encode($ccrole."./$realownerdom/$realownername".'=1','<>&"').
+                                      '&orgurl='.&HTML::Entities::encode($env{'request.editurl'},'<>&"').
+                                      '">','<a/>'));
+                    } else {
+                        if ($crstype eq 'Community') {
+                            $r->print('<p>'
+                                     .&mt('Contact a [_1] in the community ([_2]) for access.',$rolename,$cdesc)
+                                     .'</p>');
+                        } else {
+                            $r->print('<p>'
+                                     .&mt('Contact a [_1] in the course ([_2]) for access.',$rolename,$cdesc)
+                                     .'</p>');
+                        }
+                    }
+                }
+            } else {
+                my $plainname=&Apache::loncommon::plainname($realownername,$realownerdom);
+                my $user=$realownername.':'.$realownerdom;
+                my $userlink=&Apache::loncommon::aboutmewrapper(
+                                 $plainname.' ('.$user.')'
+                                ,$realownername
+                                ,$realownerdom);
+	        $r->print('<p>'
+                         .&mt('Contact [_1] for access.',$userlink)
+                         .'</p>');
+            }
         }
     }
     $r->print(&Apache::loncommon::end_page());
Index: loncom/metadata_database/searchcat.pl
diff -u loncom/metadata_database/searchcat.pl:1.84 loncom/metadata_database/searchcat.pl:1.85
--- loncom/metadata_database/searchcat.pl:1.84	Sun Jan 31 21:25:49 2016
+++ loncom/metadata_database/searchcat.pl	Sun Jun 19 04:28:08 2016
@@ -2,7 +2,7 @@
 # The LearningOnline Network
 # searchcat.pl "Search Catalog" batch script
 #
-# $Id: searchcat.pl,v 1.84 2016/01/31 21:25:49 raeburn Exp $
+# $Id: searchcat.pl,v 1.85 2016/06/19 04:28:08 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -208,13 +208,20 @@
     closedir RESOURCES;
     &log(5,'users = '.$dom.':'.join(',', at homeusers));
     #
+    my %courses;
     if ($oneuser) {
+        %courses = &courseiddump($dom,'.',1,'.','.',$oneuser,undef,
+                                 undef,'.');
         @homeusers=($oneuser);
+    } else {
+        # get courseIDs for domain on current machine
+        %courses=&Apache::lonnet::courseiddump($dom,'.',1,'.','.','.',1,[$hostid],'.');
     }
 
     #
     # Loop through the users
     foreach my $user (@homeusers) {
+        next if (exists($courses{$dom.'_'.$user}));
         &log(0,"=== User: ".$user);
         &process_dynamic_metadata($user,$dom);
         #
@@ -228,7 +235,7 @@
              }, join('/',($Apache::lonnet::perlvar{'lonDocRoot'},'res',$dom,$user)) );
     }
     # Search for all users and public portfolio files
-    my (%allusers,%portusers,%courses);
+    my (%allusers,%portusers);
     if ($oneuser) {
         %portusers = (
                         $oneuser => '',
@@ -236,11 +243,7 @@
         %allusers = (
                         $oneuser => '',
                        );
-        %courses = &courseiddump($dom,'.',1,'.','.',$oneuser,undef,
-                                 undef,'.');
     } else {
-        # get courseIDs for domain on current machine
-        %courses=&Apache::lonnet::courseiddump($dom,'.',1,'.','.','.',1,[$hostid],'.');
         my $dir = $Apache::lonnet::perlvar{lonUsersDir}.'/'.$dom;
         &descend_tree($dom,$dir,0,\%portusers,\%allusers);
     }
Index: loncom/lonnet/perl/lonnet.pm
diff -u loncom/lonnet/perl/lonnet.pm:1.1311 loncom/lonnet/perl/lonnet.pm:1.1312
--- loncom/lonnet/perl/lonnet.pm:1.1311	Sun Jun 19 00:19:24 2016
+++ loncom/lonnet/perl/lonnet.pm	Sun Jun 19 04:28:19 2016
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # TCP networking package
 #
-# $Id: lonnet.pm,v 1.1311 2016/06/19 00:19:24 raeburn Exp $
+# $Id: lonnet.pm,v 1.1312 2016/06/19 04:28:19 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -7383,6 +7383,15 @@
             $ownerhome = &homeserver($ownername,$ownerdomain);
             return ($ownername,$ownerdomain,$ownerhome);
         }
+        if ($env{'request.course.id'}) {
+            if (($ownername eq $env{'course.'.$env{'request.course.id'}.'.num'}) &&
+                ($ownerdomain eq $env{'course.'.$env{'request.course.id'}.'.domain'})) {
+                if (&allowed('mdc',$env{'request.course.id'})) {
+                    $ownerhome = $env{'course.'.$env{'request.course.id'}.'.home'};
+                    return ($ownername,$ownerdomain,$ownerhome);
+                }
+            }
+        }
     }
 
 # We don't have any access right now. If we are not possibly going to do anything about this,


More information about the LON-CAPA-cvs mailing list