View Issue Details

IDProjectCategoryView StatusLast Update
05460Development [All Projects] Theme editorpublic2012-10-30 14:05
ReportermdekkerAssigned To 
PrioritynormalSeverityminor 
Status newResolutionopen 
Product Version1.91+ 
Target Version1.91+Fixed in Version 
Summary05460: allow upload of extra css / js files and allow them to be edited
DescriptionThe template system would be more flexible if one could upload his own css / js files and edit them from the editor
TagsNo tags attached.

Activities

mdekker

mdekker

2011-09-14 11:10

developer   ~16275

Last edited: 2011-09-14 11:12

View 2 revisions

Carsten, can you review the patch for me? I apologize for the white-space changes, i can undo them when i commit the patch if you like.

What I did is:

 * add a setting to the global settings so the allowed extensions can be edited. (maybe css/js should be added to the default?)

 * add css/js files to the cssfiles var, but after the copy/check for needed files is done

 * also fixed a helper function that left out some files

 * leave the extra css/js files in the right box so one can still delete them if desired

mdekker

mdekker

2011-09-14 11:18

developer   ~16276

(added the right patch)
mdekker

mdekker

2011-09-23 11:11

developer   ~16318

Edit: new patch works with templates that have no extra files and allows names with uppercase
mdekker

mdekker

2011-10-10 13:53

developer   ~16386

Could you please review my patch? Will work on de CI when approved.
c_schmitz

c_schmitz

2011-10-10 17:10

administrator   ~16387

I would love to review the patch. Unfortunately it is not created with Subversion.
Can you try again and attach it please?
mdekker

mdekker

2011-10-11 09:20

developer  

cssjsedit.diff (15,517 bytes)
Index: admin/globalsettings.php
===================================================================
--- admin/globalsettings.php	(revision 11133)
+++ admin/globalsettings.php	(working copy)
@@ -95,6 +95,7 @@
             setGlobalSetting('ipInfoDbAPIKey',$_POST['ipInfoDbAPIKey']);
             setGlobalSetting('googleMapsAPIKey',$_POST['googleMapsAPIKey']);
             setGlobalSetting('force_ssl',$_POST['force_ssl']);
+            setGlobalSetting('allowedtemplateuploads',strip_tags(returnglobal('allowedtemplateuploads')));
             setGlobalSetting('surveyPreview_require_Auth',strip_tags($_POST['surveyPreview_require_Auth']));
             $savetime=trim(strip_tags((float) $_POST['timeadjust']).' hours'); //makes sure it is a number, at least 0
             if ((substr($savetime,0,1)!='-') && (substr($savetime,0,1)!='+')) { $savetime = '+'.$savetime;}
@@ -391,6 +392,10 @@
             $editsurvey .= ">".$clang->gT("No")."</option>\n"
             . "\t\t</select></li>\n";
 
+            //Allowed template uploads
+            $editsurvey .= "\t<li><label for='allowedtemplateuploads'>".$clang->gT("Allowed template uploads:")."</label>\n"
+            . "\t\t<input type='text' size='50' id='allowedtemplateuploads' name='allowedtemplateuploads' value=\"".htmlspecialchars(getGlobalSetting('allowedtemplateuploads'))."\" /></li>\n";
+
             $thisusercontrolSameGroupPolicy=getGlobalSetting('usercontrolSameGroupPolicy');
             $editsurvey .= "\t<li><label for='usercontrolSameGroupPolicy'>".$clang->gT("Group member can only see own group:")."</label>\n"
             . "\t\t<select id='usercontrolSameGroupPolicy' name='usercontrolSameGroupPolicy'>\n"
@@ -434,7 +439,6 @@
 	    . "<li><span style='font-size:0.7em;'>$warning_force_ssl\n</span></li>\n";
 	    unset($thisforce_ssl,$opt_force_ssl_on,$opt_force_ssl_off,$opt_force_ssl_neither,$warning_force_ssl,$this_opt);
 
-
         $editsurvey .= "\t</ul></div>\n";
 
         // presentation settings tab
Index: admin/templates.php
===================================================================
--- admin/templates.php	(revision 11133)
+++ admin/templates.php	(working copy)
@@ -71,53 +71,53 @@
 
 //Page display blocks
 $SurveyList=array('startpage.pstpl',
-                  'surveylist.pstpl', 
+                  'surveylist.pstpl',
                   'endpage.pstpl'
                   );
 $Welcome=array('startpage.pstpl',
-               'welcome.pstpl', 
-               'privacy.pstpl', 
-               'navigator.pstpl', 
+               'welcome.pstpl',
+               'privacy.pstpl',
+               'navigator.pstpl',
                'endpage.pstpl'
                );
 $Question=array('startpage.pstpl',
-                'survey.pstpl', 
-                'startgroup.pstpl', 
-                'groupdescription.pstpl',  
-                'question.pstpl', 
-                'endgroup.pstpl', 
-                'navigator.pstpl', 
+                'survey.pstpl',
+                'startgroup.pstpl',
+                'groupdescription.pstpl',
+                'question.pstpl',
+                'endgroup.pstpl',
+                'navigator.pstpl',
                 'endpage.pstpl'
                 );
 $CompletedTemplate=array(
-                'startpage.pstpl', 
-                'assessment.pstpl', 
-                'completed.pstpl', 
+                'startpage.pstpl',
+                'assessment.pstpl',
+                'completed.pstpl',
                 'endpage.pstpl'
                 );
 $Clearall=array('startpage.pstpl',
-                'clearall.pstpl', 
+                'clearall.pstpl',
                 'endpage.pstpl'
                 );
 $Register=array('startpage.pstpl',
-                'survey.pstpl', 
-                'register.pstpl', 
+                'survey.pstpl',
+                'register.pstpl',
                 'endpage.pstpl'
                 );
 $Save=array('startpage.pstpl',
-            'save.pstpl', 
+            'save.pstpl',
             'endpage.pstpl'
             );
 $Load=array('startpage.pstpl',
-            'load.pstpl', 
+            'load.pstpl',
             'endpage.pstpl'
             );
 $printtemplate=array('startpage.pstpl',
-                     'printanswers.pstpl', 
+                     'printanswers.pstpl',
                      'endpage.pstpl'
                      );
 $printablesurveytemplate=array('print_survey.pstpl',
-                               'print_group.pstpl', 
+                               'print_group.pstpl',
                                'print_question.pstpl'
                                );
 
@@ -131,7 +131,7 @@
 
 if (!isset($templatename)) {$templatename = sanitize_paranoid_string(returnglobal('templatename'));}
 if (!isset($templatedir)) {$templatedir = sanitize_paranoid_string(returnglobal('templatedir'));}
-if (!isset($editfile)) {$editfile = sanitize_filename(returnglobal('editfile'));}
+if (!isset($editfile)) {$editfile = sanitize_filename(returnglobal('editfile'), false);}  //No lowercasing
 if (!isset($screenname)) {$screenname=auto_unescape(returnglobal('screenname'));}
 
 // Checks if screen name is in the list of allowed screen names
@@ -144,7 +144,7 @@
 if (!isset($newname)) {$newname = sanitize_paranoid_string(returnglobal('newname'));}
 if (!isset($copydir)) {$copydir = sanitize_paranoid_string(returnglobal('copydir'));}
 
-if(is_file($usertemplaterootdir.'/'.$templatename.'/question_start.pstpl')) 
+if(is_file($usertemplaterootdir.'/'.$templatename.'/question_start.pstpl'))
 {
    $files[]=array('name'=>'question_start.pstpl');
    $Question[]='question_start.pstpl';
@@ -154,6 +154,20 @@
 $js_admin_includes[]= $homeurl."/scripts/edit_area/edit_area_loader.js";
 $js_admin_includes[]= $homeurl."/scripts/templates.js";
 
+//Now add any extra css/js files so they can be edited too
+$extracssfiles = array();
+if ($handle = opendir(sGetTemplatePath($templatename))) {
+   while(false !== ($file = readdir($handle))) {
+       if ((substr($file,-4) == '.css' || substr($file,-3) == '.js')
+           && !multiarray_search($cssfiles, 'name', $file)) {
+           if (!is_dir($templatedir.DIRECTORY_SEPARATOR.$file)) {
+               $extracssfiles[] = array("name"=>$file);
+           }
+       }
+   } // while
+   closedir($handle);
+}
+
 // find out language for code editor
 $availableeditorlanguages=array('bg','cs','de','dk','en','eo','es','fi','fr','hr','it','ja','mk','nl','pl','pt','ru','sk','zh');
 $extension = substr(strrchr($editfile, "."), 1);
@@ -180,7 +194,7 @@
 }
 
 
-$templates=gettemplatelist();   
+$templates=gettemplatelist();
                                // check if a template like this exists
 if (!isset($templates[$templatename]))
 {
@@ -224,7 +238,7 @@
     $changedtext=str_replace("\r\n", "\n", $changedtext);
     if ($editfile) {
         // Check if someone tries to submit a file other than one of the allowed filenames
-        if (multiarray_search($files,'name',$editfile)===false && multiarray_search($cssfiles,'name',$editfile)===false) {die('Invalid template filename');}  // Die you sneaky bastard!
+        if (multiarray_search($files,'name',$editfile)===false && multiarray_search($cssfiles,'name',$editfile)===false && multiarray_search($extracssfiles,'name',$editfile)===false) {die('Invalid template filename');}  // Die you sneaky bastard!
         $savefilename=$usertemplaterootdir."/".$templatename."/".$editfile;
         if (is_writable($savefilename)) {
            if (!$handle = fopen($savefilename, 'w')) {
@@ -266,7 +280,7 @@
    }
 }
 
-if ($action == "templaterename" && isset($newname) && isset($copydir)) 
+if ($action == "templaterename" && isset($newname) && isset($copydir))
 {
     $newdirname=$usertemplaterootdir."/".$newname;
     $olddirname=$usertemplaterootdir."/".$copydir;
@@ -278,7 +292,7 @@
     {
        echo "<script type=\"text/javascript\">\n<!--\nalert(\"".sprintf($clang->gT("Directory could not be renamed to `%s`.","js"), $newname)." ".$clang->gT("Maybe you don't have permission.","js")."\");\n//-->\n</script>";
     }
-    else 
+    else
     {
         $templates[$newname]=$newdirname;
         $templatename=$newname;
@@ -292,10 +306,10 @@
    {
        $action = '';
 
-   } 
+   }
    else
    {
-        $the_full_file_path = $usertemplaterootdir."/".$templatename . "/" . sanitize_filename($_FILES['the_file']['name']); 
+        $the_full_file_path = $usertemplaterootdir."/".$templatename . "/" . sanitize_filename($_FILES['the_file']['name']);
         if ($extfile = strrchr($_FILES['the_file']['name'], '.'))
         {
            if  (!(stripos(','.$allowedtemplateuploads.',',','. substr($extfile,1).',') === false))
@@ -407,6 +421,10 @@
    }
 }
 
+//Now the copying is done, add the extraCss to the cssfiles and otherfiles (so they can be deleted if needed)
+$cssfiles = array_merge($cssfiles, $extracssfiles);
+$otherfiles = $extracssfiles;
+
 if (!$screenname) {$screenname='welcome';}
 if ($screenname != 'welcome') {$_SESSION['step']=1;} else {unset($_SESSION['step']);} //This helps handle the load/save buttons
 
@@ -703,7 +721,7 @@
 
     case 'printanswers':
         unset($files);
-        foreach ($printtemplate as $qs) 
+        foreach ($printtemplate as $qs)
         {
            $files[]=array("name"=>$qs);
         }
@@ -724,36 +742,23 @@
 }
 $myoutput[]="</html>";
 
-if (is_array($files)) {
-   $match=0;
-   foreach ($files as $f) {
-       if ($editfile == $f["name"]) {
-           $match=1;
-       }
-   }
-   foreach ($cssfiles as $f) {
-       if ($editfile == $f["name"]) {
-           $match=1;
-       }
-   }
-   if ($match == 0) {
-       if (count($files) > 0) {
-           $editfile=$files[0]["name"];
-       } else {
-           $editfile="";
-       }
-   }
+//If no editfile or editfile not found, pick the first one
+if (multiarray_search($files,'name',$editfile)===false && multiarray_search($cssfiles,'name',$editfile)===false) {
+    if (is_array($files) && count($files) > 0) {
+        $editfile=$files[0]["name"];
+    } else {
+        $editfile="";
+    }
 }
 
 //Get list of 'otherfiles'
-$otherfiles=array();
 if ($handle = opendir($templatedir)) {
    while(false !== ($file = readdir($handle))) {
        if (!array_search($file, $normalfiles)) {
            if (!is_dir($templatedir.DIRECTORY_SEPARATOR.$file)) {
-               $otherfiles[]=array("name"=>$file);
+                   $otherfiles[]=array("name"=>$file);
+               }
            }
-       }
    } // while
    closedir($handle);
 }
@@ -874,14 +879,14 @@
 if(is_writable($tempdir) && is_writable($usertemplaterootdir))
 {
 $templatesoutput.="\t<a href='#' onclick='javascript:window.open(\"admin.php?action=templatezip&amp;editfile=$editfile&amp;screenname=".urlencode($screenname)."&amp;templatename=$templatename\", \"_top\")'"
-    ." title=\"".$clang->gTview("Export Template")."\" >" 
+    ." title=\"".$clang->gTview("Export Template")."\" >"
     ."<img name='Export' src='$imageurl/export.png' alt='".$clang->gT("Export Template")."' /></a>\n"
     ."<a href='#' onclick='javascript:window.open(\"admin.php?action=templates&amp;subaction=templateupload\", \"_top\")'"
-    ." title=\"".$clang->gTview("Import template")."\" >" 
+    ." title=\"".$clang->gTview("Import template")."\" >"
     ."<img name='ImportTemplate' src='$imageurl/import.png' alt='".$clang->gT("Import template")."' title='' /></a>\n"
     ."\t<img src='$imageurl/seperator.gif' alt='' border='0' />\n"
-    ."<a href='#' title=\"".$clang->gTview("Copy Template")."\" " 
-    ."onclick=\"javascript: copyprompt('".$clang->gT("Please enter the name for the copied template:")."', '".$clang->gT("copy_of_")."$templatename', 	   	'$templatename', 'copy')\">" 
+    ."<a href='#' title=\"".$clang->gTview("Copy Template")."\" "
+    ."onclick=\"javascript: copyprompt('".$clang->gT("Please enter the name for the copied template:")."', '".$clang->gT("copy_of_")."$templatename', 	   	'$templatename', 'copy')\">"
     ."<img name='MakeCopy' src='$imageurl/copy.png' alt='".$clang->gT("Copy Template")."' /></a>";
 }
 elseif(is_writable($usertemplaterootdir))
@@ -889,8 +894,8 @@
     $templatesoutput.="<img name='Export' src='$imageurl/export_disabled.png' alt='".$clang->gT("Export template").' - '.sprintf($clang->gT("Please change the directory permissions of the folder %s in order to enable this option"),$tempdir)."' />\n"
     ."<img name='ImportTemplate' src='$imageurl/import_disabled.png' alt='".$clang->gT("Import template").' - '.sprintf($clang->gT("Please change the directory permissions of the folder %s in order to enable this option"),$tempdir)."' title='' />\n"
 ."\t<img src='$imageurl/seperator.gif' alt='' border='0' />\n"
-    ."<a href='#' title=\"".$clang->gTview("Copy Template")."\" " 
-    ."onclick=\"javascript: copyprompt('".$clang->gT("Please enter the name for the copied template:")."', '".$clang->gT("copy_of_")."$templatename', '$templatename', 'copy')\">" 
+    ."<a href='#' title=\"".$clang->gTview("Copy Template")."\" "
+    ."onclick=\"javascript: copyprompt('".$clang->gT("Please enter the name for the copied template:")."', '".$clang->gT("copy_of_")."$templatename', '$templatename', 'copy')\">"
     ."<img name='MakeCopy' src='$imageurl/copy.png' alt='".$clang->gT("Copy Template")."' /></a>";
 }
 else
@@ -982,7 +987,7 @@
                                        ."<br/><select size='8' name='cssfiles' onchange='javascript: window.open(\"admin.php?action=templates&amp;templatename=$templatename&amp;screenname=".urlencode($screenname)."&amp;editfile=\"+escape(this.value), \"_top\")'>\n"
                                        .makeoptions($cssfiles, "name", "name", $editfile)
                                        . "</select>\n"
-        
+
                                        ."</td>\n"
                                        ."<td valign='top' align='right' width='20%'><form action='admin.php' method='post'>"
                                        ."<table width='90' align='left' border='0' cellpadding='0' cellspacing='0'>\n<tr><td></td></tr>"
@@ -1129,7 +1134,7 @@
        $graph.='$(document).ready(function() {
                 $("div.ui-progressbar-value").removeClass("ui-corner-left");
                 $("div.ui-progressbar-value").addClass("ui-corner-right");
-                });';  
+                });';
     }
     $graph.='</script>
 
@@ -1165,7 +1170,7 @@
         <script type="text/javascript">
         $(document).ready(function() {
         $("div.ui-progressbar-value").hide();
-        }); 
+        });
         </script>';
     }
 
@@ -1216,12 +1221,22 @@
     return $return;
 }
 
-function multiarray_search($arrayVet, $campo, $valor){
-   while(isset($arrayVet[key($arrayVet)])){
-       if($arrayVet[key($arrayVet)][$campo] == $valor){
-           return key($arrayVet);
+/**
+ * Returns true when a nested array has the given key/value pair
+ *
+ * Usage: multiarray_search($cssfiles, 'name', 'template.css')
+ * returns true when cssfiles contains an array with name=>template.css
+ *
+ * @param type $arrayVet Array of arrays
+ * @param type $key      The key to search for
+ * @param type $value    The value to check
+ * @return boolean
+ */
+function multiarray_search($arrayVet, $key, $value){
+   foreach($arrayVet as $index => $element) {
+       if (isset($element[$key]) && $element[$key] == $value) {
+           return true;
        }
-       next($arrayVet);
    }
    return false;
 }
cssjsedit.diff (15,517 bytes)
mdekker

mdekker

2011-10-11 09:21

developer   ~16389

Hope this one works?
c_schmitz

c_schmitz

2011-10-18 18:26

administrator   ~16452

In general the patch for templates.php looks fine.
I just don't want the file extensions be editable in globalsettings.php for security reasons, so maybe you can leave that part out and just add .css and .js to the config-defaults.php.

Please don't forget to apply the changes to the CI version. No new features anymore on stable, please.
c_schmitz

c_schmitz

2012-01-23 16:57

administrator   ~16919

*to the Yii version.

Menno, can you give feedback please on the status of this issue?
ludostev

ludostev

2012-03-01 09:45

reporter  

wTooltip.1.4.min.js (6,141 bytes)
c_schmitz

c_schmitz

2012-06-22 10:27

administrator   ~19458

Feedback please?
c_schmitz

c_schmitz

2012-10-02 12:33

administrator   ~20977

I am moving this to the development tracker for now - maybe someone else can pick up on this later.
helper

helper

2012-10-30 14:05

reporter   ~21771

This is an excellent addition guys! The only thing that I would suggest is to have a subdirectory for these aux files that the admins can put in their custom graphics and other custom files - this would keep the template files separated from the rest of the 'stuff.'

Issue History

Date Modified Username Field Change
2011-09-14 11:07 mdekker New Issue
2011-09-14 11:07 mdekker File Added: cssjsedit.diff
2011-09-14 11:10 mdekker Note Added: 16275
2011-09-14 11:10 mdekker Assigned To => c_schmitz
2011-09-14 11:10 mdekker Status new => feedback
2011-09-14 11:12 mdekker Note Edited: 16275 View Revisions
2011-09-14 11:17 mdekker File Deleted: cssjsedit.diff
2011-09-14 11:17 mdekker File Added: cssjsedit.diff
2011-09-14 11:18 mdekker Note Added: 16276
2011-09-14 11:18 mdekker Status feedback => assigned
2011-09-23 11:10 mdekker File Deleted: cssjsedit.diff
2011-09-23 11:10 mdekker File Added: cssjsedit.diff
2011-09-23 11:11 mdekker Note Added: 16318
2011-10-10 13:53 mdekker Note Added: 16386
2011-10-10 17:10 c_schmitz Note Added: 16387
2011-10-11 09:20 mdekker File Deleted: cssjsedit.diff
2011-10-11 09:20 mdekker File Added: cssjsedit.diff
2011-10-11 09:21 mdekker Note Added: 16389
2011-10-18 18:24 c_schmitz Assigned To c_schmitz => mdekker
2011-10-18 18:26 c_schmitz Note Added: 16452
2012-01-23 16:57 c_schmitz Note Added: 16919
2012-01-23 16:58 c_schmitz Status assigned => feedback
2012-03-01 09:45 ludostev File Added: wTooltip.1.4.min.js
2012-06-22 10:27 c_schmitz Note Added: 19458
2012-07-27 13:53 c_schmitz Assigned To mdekker => c_schmitz
2012-07-27 13:53 c_schmitz Status feedback => assigned
2012-07-27 13:53 c_schmitz Assigned To c_schmitz => mdekker
2012-07-27 13:53 c_schmitz Status assigned => feedback
2012-10-02 12:33 c_schmitz Note Added: 20977
2012-10-02 12:33 c_schmitz Project Bug reports => Development
2012-10-30 09:11 mdekker Assigned To mdekker =>
2012-10-30 09:14 mdekker Status feedback => new
2012-10-30 14:05 helper Note Added: 21771
2015-12-11 14:40 c_schmitz Category Templates => Theme editor