<?php

# PLUGIN PREVIEW BY TEXTPATTERN.INFO


/*
    adi_scripts - Script File Management

    Written by Adi Gilbert

    Released under the GNU General Public License

    Version history:
    0.3        - Updated for TXP 4.6
            - minimum supported release 4.5
            - all script files must have ".js" extension
    0.2        - introduced tagging
            - security fix
            - updates lastmod
    0.1        - initial release

*/

// TXP 4.6 tag registration
if (class_exists('\Textpattern\Tag\Registry')) {
    
Txp::get('\Textpattern\Tag\Registry')
        ->
register('adi_scripts')
    ;
}

if (@
txpinterface == 'admin') {
    global 
$adi_scripts_debug;

    
$adi_scripts_debug 0;

    if (!
version_compare(txp_version,'4.5.0','>=')) return;

    
adi_scripts_init();
}

function 
adi_scripts_init() {
// initial set up
    
global $prefs,$event,$adi_scripts_tab_list,$adi_scripts_prefs,$adi_scripts_debug,$adi_scripts_plugin_status,$adi_scripts_url,$adi_scripts_priv_levels,$adi_scripts_txp450,$textarray,$adi_scripts_txp460;

    
$adi_scripts_txp450 = (version_compare(txp_version,'4.5','>='));
    
$adi_scripts_txp460 = (version_compare(txp_version,'4.6-dev','>='));

    
// default preferences
    
$adi_scripts_prefs = array(
        
'adi_scripts_dir' => array('value' => 'textpattern''blank' => 1'private' => 0'input' => 'text_input''tab' => 'admin'),
        
'adi_scripts_new_dir' => array('value' => 'textpattern/vendors/jquery/jquery,textpattern/vendors/jquery/jquery-ui''blank' => 1'private' => 0'input' => 'text_input''tab' => ''),
    );

# --- BEGIN PLUGIN TEXTPACK ---
    
$adi_scripts_gtxt = array(
        
'adi_add_tag' => 'Add tag',
        
'adi_directory' => 'Directory',
        
'adi_directories' => 'Directories',
        
'adi_enabled' => 'Enabled',
        
'adi_ie_conditionals' => 'IE conditionals',
        
'adi_install_fail' => 'Unable to install',
        
'adi_installed' => 'Installed',
        
'adi_invalid_input' => 'Invalid input',
        
'adi_none_found' => 'None found',
        
'adi_not_installed' => 'Not installed',
        
'adi_not_readable' => 'Not readable',
        
'adi_script' => 'Script',
        
'adi_scripts' => 'Scripts',
        
'adi_scripts_dir' => 'Scripts directory',
        
'adi_scripts_dir_not_found' => 'Directory not found',
        
'adi_scripts_general_warning' => 'Some directories/files not readable',
        
'adi_scripts_manage_fail' => 'Unable to manage scripts',
        
'adi_scripts_manage_selected' => 'Manage selected scripts',
        
'adi_scripts_managed' => 'Selected scripts now managed',
        
'adi_scripts_managed_scripts' => 'Managed scripts',
        
'adi_scripts_unmanaged_scripts' => 'Unmanaged scripts',
        
'adi_scripts_updated' => 'Script settings updated',
        
'adi_textpack_fail' => 'Textpack installation failed',
        
'adi_textpack_feedback' => 'Textpack feedback',
        
'adi_textpack_online' => 'Textpack also available online',
        
'adi_uninstall' => 'Uninstall',
        
'adi_uninstall_fail' => 'Unable to uninstall',
        
'adi_uninstalled' => 'Uninstalled',
        
'adi_update_prefs' => 'Update preferences',
        
'adi_update_directories' => 'Update directories',
        
'adi_update_scripts' => 'Update script settings',
        );
# --- END PLUGIN TEXTPACK ---

    // update $textarray
    
$textarray += $adi_scripts_gtxt;

    
// Textpack
    
$adi_scripts_url = array(
        
'textpack' => 'http://www.greatoceanmedia.com.au/files/adi_textpack.txt',
        
'textpack_download' => 'http://www.greatoceanmedia.com.au/textpack/download',
        
'textpack_feedback' => 'http://www.greatoceanmedia.com.au/textpack/?plugin=adi_scripts',
    );
    if (
strpos($prefs['plugin_cache_dir'],'adi') !== FALSE// use Adi's local version
        
$adi_scripts_url['textpack'] = $prefs['plugin_cache_dir'].'/adi_textpack.txt';

    
// plugin lifecycle
    
register_callback('adi_scripts_lifecycle','plugin_lifecycle.adi_scripts');

    
// adi_scripts Admin tab
    
add_privs("adi_scripts_admin"); // defaults to priv '1' only
    
register_tab("extensions","adi_scripts_admin",gTxt('adi_scripts')); // add new tab under 'Extensions'
    
register_callback("adi_scripts_admin","adi_scripts_admin");

    
// style
    
if ($event == "adi_scripts_admin")
        
register_callback('adi_scripts_style','admin_side','head_end');

    
// script
    
if (strstr($event,'adi_scripts_admin'))
        
register_callback('adi_scripts_admin_script','admin_side','head_end');

    
// plugin options
    
$adi_scripts_plugin_status fetch('status','txp_plugin','name','adi_scripts',$adi_scripts_debug);
    if (
$adi_scripts_plugin_status) { // proper install - options under Plugins tab
        
add_privs('plugin_prefs.adi_scripts'); // defaults to priv '1' only
        
register_callback('adi_scripts_options','plugin_prefs.adi_scripts');
    }
    else { 
// txpdev - options under Extensions tab
        
add_privs('adi_scripts_options'); // defaults to priv '1' only
        
register_tab('extensions','adi_scripts_options','adi_scripts options');
        
register_callback('adi_scripts_options','adi_scripts_options');
    }

}

function 
adi_scripts_style() {
// some style for the admin page

    
echo
        
'<style type="text/css">
            #adi_scripts h1, #adi_scripts h2 { text-align:center }
            #adi_scripts p { text-align:center }
            #adi_scripts form table + p { margin-top:0.5em }
            #adi_scripts table.txp-list { width:auto; margin:0 auto }
            #adi_scripts label { margin-right:0.5em }
            .adi_scripts_admin_managed, .adi_scripts_admin_unmanaged, .adi_scripts_prefs { margin-bottom:3em }
            .adi_scripts_prefs .adi_scripts_text_input { margin-right:0.5em }
            .adi_scripts_prefs .adi_scripts_new_dir { width:20em }
            .adi_scripts_button { margin-top:1em; text-align:center }
            td.adi_scripts_enabled, td.adi_scripts_forget, td.adi_scripts_manage { text-align:center }
            .adi_scripts_ie input { width:6em; margin-left:0.3em; margin-right:0.3em; font-family:courier,monospace }
            .adi_scripts_ie span { color:#000; font-weight:bold; font-family:courier,monospace }
            .adi_scripts_disabled { color:#ccc }
            span.adi_scripts_disabled { color:#ccc; font-weight:normal }
            .adi_scripts_sort input { width:2.5em }
            .adi_scripts_tag_header_header { text-align:center; border-bottom:1px solid #ddd }
            .adi_scripts_tag_header { text-align:center; font-weight:normal }
            .adi_scripts_tags { text-align:center }
            .adi_scripts_sections { width:16em }
            .adi_scripts_sections label { margin-right:1em }
            .adi_scripts_multi_checkboxes { margin:0.3em 0 0.5em; width:15em; height:5em; padding:0.2em; overflow:auto; border:1px solid #ccc }
            .adi_scripts_multi_checkboxes label { display:block; float:none; width:auto }
            .adi_scripts_drag_drop { display:none } /* revealed by jQuery later */
        </style>'
;
}

function 
adi_scripts_admin($event$step) {
// the adi_scripts admin tab
    
global $prefs,$adi_scripts_debug,$adi_scripts_plugin_status,$adi_scripts_prefs,$adi_scripts_txp450,$adi_scripts_problem_count;

    if (
$adi_scripts_debug) echo __FUNCTION__.':'.br;

    
$message '';
    
$installed adi_scripts_installed();

    if (
$installed) {
        
$upgrade_required adi_scripts_upgrade();
        if (
$upgrade_required)
            
$message = array(gTxt('adi_upgrade_required'),E_WARNING);
        else {
            
/* stuff */
        
}
    }
    else
        
$message = array(gTxt('adi_not_installed'),E_ERROR);

    
// admin steps
    
$new_tag='';
    if (
$step == 'update') {
        
$new_settings ps('adi_scripts_settings');
        
$result adi_scripts_update_settings($new_settings);
        
$result $message gTxt('adi_scripts_updated') : $message = array(gTxt('adi_scripts_update_fail'),E_ERROR);
    }
    else if (
$step == 'update_prefs') {
        
$result TRUE;
        
// process prefs
        
foreach ($adi_scripts_prefs as $pref_name => $pref_info) { // awkward to convert to std adi_admin_plugin_update_prefs() - two result conditions - return TRUE/FALSE/message?
            // get/massage pref value
            
if (array_key_exists($pref_name,$_POST)) // pref present in POST
                
$value $_POST[$pref_name];
            else if (
$pref_info['input'] == 'yesnoradio'// pref missing from POST, make it zero
                
$value '0';
//             else if ($pref_info['blank']) // pref missing from POST, pref allowed to be blank, make it blank
//                 $value = '';
            
else
                
$value $pref_info['value']; // pref missing from POST, reset value
            // special processing & validation
            
if ($pref_name == 'adi_scripts_dir') {
                
// compare stored dir list with pref changes
                
if (adi_scripts_pref('adi_scripts_dir'))
                    
$old_list explode(',',adi_scripts_pref('adi_scripts_dir'));
                else
                    
$old_list = array();
                
$new_list $value;
                
$updated_list = array();
                
// see if existing dir needs to be removed in dir list
                
foreach ($old_list as $dir) {
                    if (
array_search($dir,$new_list) === FALSE)
                        
$updated_list[] = $dir;
                }
                
// add a newcomer (subject to terms & conditions)
                
$input_ok TRUE;
                if (
$new_list['new']) {
//                     if (strpbrk($new_list['new'],"\\/?%*:|\"<>") === FALSE) { /* check directory is kosher (i.e. doesn't contain illegal characters) */
                    
if (strpbrk($new_list['new'],"\\?%*:|\"<>") === FALSE) { /* check directory doesn't contain illegal characters; as of v0.3 & TXP 4.6 now allowing "/" to cater for subdirectories */
                        
if (preg_match("/^[.\/]/",$new_list['new']) === 0) { /* check directory doesn't start with . or / ... STRIP INSTEAD? */
                            
$updated_list[] = $new_list['new'];
                        }
                        else
                            
$input_ok FALSE;
                    }
                    else
                        
$input_ok FALSE;
                }
                
// lose les oubliettees from the database (NOT SURE WHY DID I DID THIS ANYWAY ... i.e. delete scripts when "forget" their directories)
//                 foreach ($new_list as $dir) {
//                     $where = "directory='".doSlash($dir)."'";
//                     $result = $result && safe_delete('adi_scripts',$where,$adi_scripts_debug);
//                 }
                
$value implode(',',$updated_list);
            }
            if (
$pref_name == 'adi_scripts_new_dir'// internal use only, so don't think it should be blank (tab='')
                
$value adi_scripts_pref('adi_scripts_new_dir');
            
// some values not allowed to be blank, reset to default
            
if ((!$pref_info['blank']) && (trim($value) == ''))
                    
$value $adi_scripts_prefs[$pref_name]['value'];
            
$result $result && adi_scripts_pref($pref_name,$value);
        }
        
// it's a result
        
if ($result)
            
$message gTxt('preferences_saved');
        else
            
$message = array(gTxt('adi_pref_update_fail'),E_ERROR);
        
// DRS
        
if ($result && !$input_ok)
            
$message = array(gTxt('adi_invalid_input'),E_ERROR);
    }
    else if (
$step == 'new_scripts') {
        
$new_scripts ps('adi_scripts_new_list');
        
$result TRUE;
        if (
$new_scripts)
            foreach (
$new_scripts as $directory => $files)
                foreach (
$files as $file)
                    
$result $result && adi_scripts_manage_script($file,$directory);
        
$result $message gTxt('adi_scripts_managed') : $message = array(gTxt('adi_scripts_manage_fail'),E_ERROR);
    }
    else if (
$step == 'new_tag') {
        
$new_tag sanitizeForURL(assert_string(ps('adi_scripts_new_tag')));
    }

    
$installed adi_scripts_installed();

    
$adi_scripts_problem_count 0// may morph into a list of dodgy dirs/files one day

    // see if scripts directories are ok & gather list of script files from each
    
if ($installed) {
        if (
adi_scripts_pref('adi_scripts_dir'))
            
$directories explode(',',adi_scripts_pref('adi_scripts_dir'));
        else
            
$directories = array();
        if (
$adi_scripts_debug) {
            echo 
"SCRIPT DIRECTORIES:".br;
            
dmp($directories);
        }
        
$file_list = array();
        foreach (
$directories as $dir) {
            if (
$adi_scripts_debug) echo "CHECKING DIRECTORY $dir".br;
            
$dir_message adi_scripts_check_dir($dir);
            if (empty(
$dir_message))
                
$file_list[$dir] = adi_scripts_get_files($dir);
            else
                
$adi_scripts_problem_count += 1;
        }
        if (
$adi_scripts_debug) {
            echo 
br."COMBINED FILE LIST".br;
            
dmp($file_list);
            if (
$new_tag != '')
                echo 
br."NEW TAG = $new_tag".br.br;
        }
    }

    
// admin tab markup
    
$out '';
    if (
$installed && !$upgrade_required) {
        
$out .= '<div id="adi_scripts">';
        
// managed scripts
        
$out .= tag(
            
adi_scripts_managed_list($new_tag)
            ,
'div'
            
,' class="adi_scripts_admin_managed"'
        
);
        
// unmanaged scripts
        
$out .= tag(
            
adi_scripts_unmanaged_list($file_list)
            ,
'div'
            
,' class="adi_scripts_admin_unmanaged"'
        
);
        
// directories
        
$out .= tag(
            
adi_scripts_directories($directories)
            ,
'div'
            
,' class="adi_scripts_prefs"'
        
);
        
// new tag
        
$out .= tag(
            
adi_scripts_new_tag()
            ,
'div'
            
,' class="adi_scripts_prefs"'
        
);
        
$out .= '</div>';
    }

    if (!
$message && $adi_scripts_problem_count)
        
$message = array(gTxt('adi_scripts_general_warning'),E_WARNING);

    
// generate page
    
pagetop(gTxt('adi_scripts').' '.gTxt('admin'),$message);

    echo 
$out;

    if (
$adi_scripts_debug) {
        if (
$installed) {
            echo 
'<b>Prefs:</b><br/>';
            foreach (
$adi_scripts_prefs as $name => $this_pref)
                echo 
$name.' = '.adi_scripts_pref($name).br;
            echo 
"adi_scripts_problem_count = $adi_scripts_problem_count";
            echo 
'<br/>';
        }
    }
}

function 
adi_scripts_admin_script() {
// jQuery magic for admin tab
    
global $prefs,$adi_scripts_txp460;

    
$ui_script '';
    if (!
$adi_scripts_txp460)
        
$ui_script '<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.9.0/jquery-ui.min.js"></script>';

    echo <<<END_SCRIPT
<script type="text/javascript">
    $(function(){
        // section list peekaboo
        $('td.adi_scripts_sections').each(function(){
            var this_td = $(this);
            // hide sections if "All" ticked
            $('input[name*="all_sections"][value="1"]:checked',this).each(function(){
                $('div',this_td).hide();
            });
            // an "All" has been deselected
            $('input[name*="all_sections"]:radio:eq(1)',this).change(function(){
                $('div',this_td).show();
            });
            // an "All" has been selected
            $('input[name*="all_sections"]:radio:eq(0)',this).change(function(){
                $('div',this_td).hide();
            });
        });
        // disabled script ghosting
        $('td.adi_scripts_enabled').each(function(){
             var this_td = $(this);
            // dim scripts if not enabled
            $('input:checkbox:not(:checked)',this).each(function(){
                $(this_td).parent().addClass("adi_scripts_disabled");
            });
            // script enabled/disabled
            $('input',this).change(function(){
                if (this.checked)
                    $(this_td).parent().removeClass("adi_scripts_disabled");
                else
                     $(this_td).parent().addClass("adi_scripts_disabled");
            });
        });
    });
</script>
<!-- drag and drop -->
$ui_script
<script type="text/javascript">
    if (jQuery.ui) { // jQuery UI available
        $(function() {
            $('.adi_scripts_admin_managed table tbody tr').css('cursor','pointer'); // make like a pointer
            $('.adi_scripts_admin_managed table .adi_scripts_drag_drop').show(); // reveal drag & drop icon
            $('.adi_scripts_admin_managed table .adi_scripts_sort').hide(); // lose sort value column
            $(".adi_scripts_admin_managed table tbody").sortable();
            $(".adi_scripts_admin_managed table tbody").bind("sortstop",function(event, ui) {
                $('td.adi_scripts_sort input').each(function(i) { // renumber sort values
                    var this_td = $(this);
                    this_td.val(i+10);
                });
            });
        });
    }
</script>
END_SCRIPT;
}

function 
adi_scripts_options($event,$step) {
// display adi_scripts options: install/uninstall/upgrade
    
global $adi_scripts_debug,$adi_scripts_url,$adi_scripts_plugin_status;

    
$message '';
    
$installed adi_scripts_installed();

    if (
$installed) {
        
$upgrade_required adi_scripts_upgrade();
        if (
$upgrade_required) { // upgrade
            
$res adi_scripts_upgrade(TRUE);
            if (
$res)
                
$message gTxt('adi_upgraded');
            else
                
$message = array(gTxt('adi_upgrade_fail'),E_ERROR);
        }
        
// $stepping out
        
if ($step == "uninstall") { // uninstall adi_scripts
            
$res adi_scripts_uninstall();
            if (
$res)
                
$message gTxt('adi_uninstalled');
            else
                
$message = array(gTxt('adi_uninstall_fail'),E_ERROR);
        }
        else if (
$step == 'textpack') {
            
$adi_textpack file_get_contents($adi_scripts_url['textpack']);
            if (
$adi_textpack) {
                
$result install_textpack($adi_textpack);
                
$message gTxt('textpack_strings_installed', array('{count}' => $result));
                
$textarray load_lang(LANG); // load in new strings
            
}
            else
                
$message = array(gTxt('adi_textpack_fail'),E_ERROR);
        }

        else if (
$step == 'update_prefs') {
            
$result TRUE;
            
// run through all prefs
            
foreach ($adi_scripts_prefs as $name => $data) {
                if (
array_key_exists($name,$_POST))
                    
$value $_POST[$name];
                else if (
$data['input'] == 'yesnoradio')
                    
$value '0';
                else
                    
$value $data['value'];
                if (
is_array($value)) { // string-ify arrays
                    
$values array_keys($value); // need index values not 1s
                    
if ($name == 'adi_scripts_admin_privs') {
                        
// IF NO ADMIN TAB THEN LOSE THIS (I.E. ALLOWED TO SWITCH SELF & PUBLISHER OFF)
                        
$user_priv safe_field('privs','txp_users',"name='".doSlash($txp_user)."'");
                        
$values array_unique(array_merge($values,array(1,$user_priv))); // can't kill off Publisher or self
                    
}
                    
$value implode(',',$values);
                }
                
// some values not allowed to be blank, reset to default
                
$non_blanks = array();
                foreach (
$non_blanks as $non_blank)
                    if ((
$name == $non_blank) && (trim($value) == ''))
                        
$value $adi_scripts_prefs[$non_blank]['value'];
                
$result &= adi_scripts_pref($name,$value);
            }
            
$result $message gTxt('preferences_saved') : $message = array(gTxt('adi_pref_update_fail'),E_ERROR);
        }

    }
    else { 
// not installed
        
if ($step == "install") { // install adi_scripts
            
$res adi_scripts_install();
            if (
$res)
                
$message gTxt('adi_installed');
            else
                
$message = array(gTxt('adi_install_fail'),E_ERROR);
        }
        else
            
$message = array(gTxt('adi_not_installed'),E_ERROR);
    }

    
// generate page
    
pagetop('adi_scripts - '.gTxt('plugin_prefs'),$message);

    
$install_button =
        
form(
            
fInput("submit""adi_scripts_options_submit"gTxt('install'), "publish","",'return verify(\''.gTxt('are_you_sure').'\')')
            .
eInput($event).sInput("install")
            ,
'','','post','adi_scripts_nstall_button'
        
);
    
$uninstall_button =
        
form(
            
fInput("submit""do_something"gTxt('adi_uninstall'), "publish","",'return verify(\''.gTxt('are_you_sure').'\')')
            .
eInput($event).sInput("uninstall")
            ,
'','','post','adi_scripts_nstall_button adi_scripts_uninstall_button'
        
);

    if (
$adi_scripts_plugin_status// proper plugin install, so lifecycle takes care of install/uninstall
        
$install_button $uninstall_button '';

    
$installed adi_scripts_installed();

    
// options
    
echo tag(
        
tag('adi_scripts '.gTxt('plugin_prefs'),'h1')
        .( 
$installed ?
            
// textpack links
            
graf(href(gTxt('install_textpack'),'?event='.$event.'&amp;step=textpack'))
            .
graf(href(gTxt('adi_textpack_online'),$adi_scripts_url['textpack_download']))
            .
graf(href(gTxt('adi_textpack_feedback'),$adi_scripts_url['textpack_feedback']))
            .
$uninstall_button
            
$install_button
        
)
        ,
'div'
        
,' style="text-align:center"'
    
);
}

function 
adi_scripts_install() {
// install adi_scripts in database
    
global $adi_scripts_debug,$adi_scripts_prefs,$adi_scripts_txp460;

    if (
$adi_scripts_debug) echo __FUNCTION__.':';

    
$res safe_query(
        
"CREATE TABLE IF NOT EXISTS "
        
.safe_pfx('adi_scripts')
        .
" (
            `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
            `filename` VARCHAR(255) NOT NULL,
            `directory` VARCHAR(255) NOT NULL,
            `enabled` TINYINT(1) DEFAULT 0 NOT NULL,
            `tags` VARCHAR(255) NOT NULL,
            `sections` VARCHAR(255) NOT NULL,
            `ie` VARCHAR(255) NOT NULL,
            `sort` TINYINT(3) UNSIGNED DEFAULT 0 NOT NULL
        );"
        
,$adi_scripts_debug);
    
// fix up default pref values for 4.6
    
if ($adi_scripts_txp460) {
        
$res $res && adi_scripts_pref('adi_scripts_dir',adi_scripts_pref('adi_scripts_new_dir')); // create dirs pref with 4.6 dirs
        
$res $res && adi_scripts_pref('adi_scripts_new_dir',''); // flush out new dirs pref (to prevent triggering upgrade again)
    
}

     return 
$res;
}

function 
adi_scripts_uninstall() {
// uninstall adi_scripts
    
global $adi_scripts_debug;

    if (
$adi_scripts_debug) echo __FUNCTION__.':';

    
// delete table
    
$res safe_query("DROP TABLE ".safe_pfx('adi_scripts').";",$adi_scripts_debug);
    
// delete preferences
    
$res $res && safe_delete('txp_prefs',"name LIKE 'adi_scripts_%'",$adi_scripts_debug);

    return 
$res;
}

function 
adi_scripts_lifecycle($event,$step) {
// a matter of life & death
// $event:    "plugin_lifecycle.adi_plugin"
// $step:    "installed", "enabled", disabled", "deleted"
// TXP 4.5: reinstall/upgrade only triggers "installed" event (now have to manually detect whether upgrade required)
    
global $adi_scripts_debug,$adi_scripts_txp450;

    
$result '?';
    
// set upgrade flag if upgrading/reinstalling in TXP 4.5+
    
$upgrade = (($step == "installed") && $adi_scripts_txp450 && adi_scripts_installed());
    if (
$step == 'enabled')
        
$result $upgrade adi_scripts_install();
    else if (
$step == 'deleted')
        
$result adi_scripts_uninstall();
    if (
$upgrade)
        
$result $result && adi_scripts_upgrade(TRUE);
    if (
$adi_scripts_debug)
        echo 
"Event=$event Step=$step Result=$result Upgrade=$upgrade";
}

function 
adi_scripts_pref($name,$value=NULL,$private=FALSE) {
// read or set pref
    
global $prefs,$adi_scripts_prefs;

    if (
$value === NULL)
        return 
get_pref($name,$adi_scripts_prefs[$name]['value']);
    else {
        if (
array_key_exists($name,$adi_scripts_prefs))
            
$html $adi_scripts_prefs[$name]['input'];
        else
            
$html 'text_input';
        
$res set_pref($name,$value,'adi_scripts_admin',2,$html,0,$private);
        
$prefs[$name] = get_pref($name,$adi_scripts_prefs[$name]['value'],TRUE);
        return 
$res;
    }
}

function 
adi_scripts_installed($table='adi_scripts') {
// see if supplied table is present
    
global $adi_scripts_debug;

    if (
$adi_scripts_debug) echo __FUNCTION__.':';

    
$found FALSE;
    
$rs safe_query("SHOW TABLES LIKE '".safe_pfx($table)."'",$adi_scripts_debug);
    
$a nextRow($rs);
    if (
$a)
        
$found TRUE;

    return 
$found;
}

function 
adi_scripts_upgrade($do_upgrade=FALSE) {
// internal upgrade required?
    
global $adi_scripts_debug,$adi_scripts_txp450,$adi_scripts_txp460;

    
$upgrade_required FALSE;
    if (
adi_scripts_installed()) { // find out what needs upgrading
        // version 0.2 - tagging
        
$rs safe_query('SHOW FIELDS FROM '.safe_pfx('adi_scripts')." LIKE 'tags'",$adi_scripts_debug); // find out if column exists
        
$a nextRow($rs);
        
$v0_2 = empty($a);
        
// version 0.3 flags on different TXP versions
        
$v0_3_45 = !get_pref('adi_scripts_new_dir','',TRUE) && (version_compare(txp_version,'4.5','>=')) && (version_compare(txp_version,'4.5.7','<='));
        
$v0_3_46 adi_scripts_pref('adi_scripts_new_dir') && $adi_scripts_txp460;
        
$upgrade_required $upgrade_required || $v0_2 || $v0_3_45 || $v0_3_46;
        if (
$do_upgrade) {
            if (
$upgrade_required) {
                
$res TRUE;
                if (
$v0_2)
                    
$res $res && safe_query("ALTER TABLE ".safe_pfx("adi_scripts")." ADD `tags` VARCHAR(255) NOT NULL",$adi_scripts_debug); // add new column
                
if ($v0_3_45// set up "new dirs" flag for later (when TXP is upgraded to 4.6)
                    
$res $res && adi_scripts_pref('adi_scripts_new_dir',adi_scripts_pref('adi_scripts_new_dir')); // create new dirs pref
                
if ($v0_3_46) { // new "default dirs" to add? - i.e. TXP 4.6 jQuery/jQuery-UI paths
                    // shift new "default dirs" to current directories list
                    
$current explode(',',adi_scripts_pref('adi_scripts_dir'));
                    
$new explode(',',adi_scripts_pref('adi_scripts_new_dir'));
                    
$combined array_filter(array_unique(array_merge($current,$new))); // combine current with new, lose duplicates & blanks
                    
$res $res && adi_scripts_pref('adi_scripts_dir',implode(',',$combined)); // update dirs pref
                    
$res $res && adi_scripts_pref('adi_scripts_new_dir',''); // flush out new dirs pref (to prevent triggering upgrade again)
                    // modify standard jQuery script entry: "textpattern/jquery.js" -> "textpattern/vendors/jquery/jquery/jquery.js"
                    
$set "directory='textpattern/vendors/jquery/jquery'";
                    
$where "filename='jquery.js' AND directory='textpattern'";
                    
$res $res && safe_update('adi_scripts',$set,$where,$adi_scripts_debug);

                }
                return 
$res;
            }
            else
                return 
FALSE;
        }
        else
            return 
$upgrade_required;
    }
    else
        return 
FALSE;
}

function 
adi_scripts_managed_list($new_tag) {
// managed scripts
    
global $adi_scripts_debug,$prefs,$adi_scripts_problem_count;

    if (
$adi_scripts_debug) echo __FUNCTION__.':';

    
$out '';
    
$script_settings '';
    
$unreadable_count 0;
    
$new_sort 0;

    
// get stored scripts info
    
$rows safe_rows('*','adi_scripts','1=1 ORDER BY sort,id'$adi_scripts_debug);
    
$out .= tag(gTxt('adi_scripts'),'h1');
    if (
$adi_scripts_debug)
        
dmp($rows);

    
// tags
    
$tag_list adi_scripts_tag_list($new_tag);

    if (
$rows) { // managed scripts found in the database
        
foreach ($rows as $row) {
            
$new_sort += 10;
            
extract($row);
            
$file_path $prefs['path_to_site'].'/'.$directory.'/'.$filename;
            if (
file_exists($file_path) && is_readable($file_path))
                
$asterisk '';
            else {
                
$asterisk '*';
                
$unreadable_count += 1;
            }
            if (
$ie)
                
$class '';
            else
                
$class ' class="adi_scripts_disabled"';
            
// tags
            
$tag_settings '';
            foreach (
$tag_list as $tag)
                
$tag_settings .= tda(checkbox2("adi_scripts_settings[$id][tags][$tag]",(array_search($tag,explode(',',$tags)) !== FALSE)),' class="adi_scripts_tags"');
            
// scripts settings
            
$script_settings .=
                
tr(
                    
tda(tag('&#x2195;','span',' class="adi_scripts_drag_drop"'))
                    
// script filename
                    
.tda(
                        
tag(
                            
$directory
                            
.'/'
                            
.$filename
                            
.$asterisk
                            
,'span'
                            
,($asterisk ' class="warning"' '')
                        )
                        .
hInput("adi_scripts_settings[$id][filename]",$filename)
                        .
hInput("adi_scripts_settings[$id][directory]",$directory)


                    )
                    
// enabled?
                    
.tda(checkbox2("adi_scripts_settings[$id][enabled]",$enabled),' class="adi_scripts_enabled"')
                    
// tags
                    
.$tag_settings
                    
// sections
                    
.tda(
                        
tag(gTxt('all'),'label')
                        .
radio("adi_scripts_settings[$id][all_sections]",'1',($sections == ''))
                        .
sp.sp
                        
.tag(gTxt('selected'),'label')
                        .
radio("adi_scripts_settings[$id][all_sections]",'0',($sections != ''))
                        .
tag(adi_scripts_section_checkboxes("adi_scripts_settings[$id][sections]",$sections),'div',' class="adi_scripts_multi_checkboxes"')
                        ,
' class="adi_scripts_sections"'
                    
)
                    
// IE conditionals
                    
.tda(
                        
tag(htmlentities('<!--[if'),'span',$class).finput('text',"adi_scripts_settings[$id][ie]",$ie).tag(htmlentities(']>'),'span',$class)
                        ,
' class="adi_scripts_ie"'
                    
)
                    
// (sort)
                    
.tda(finput("text","adi_scripts_settings[$id][sort]",$new_sort),' class="adi_scripts_sort"')
                    
// forget?
                    
.tda(checkbox2("adi_scripts_settings[$id][forget]",0),' class="adi_scripts_forget"')
                );
        }

        
// tag headers
        
$tag_header_header '';
        if (
$tag_list) {
            if (
count($tag_list) == 1)
                
$header_text gTxt('tag');
            else
                
$header_text gTxt('tags');
            
$tag_header_header tag(hcell(sp,'',' colspan="3"').hcell($header_text,'',' colspan="'.count($tag_list).'" class="adi_scripts_tag_header_header"').hcell(sp,'',' colspan="4"'),'tr');
        }
        
$tag_headers '';
        foreach (
$tag_list as $tag)
            
$tag_headers .= hcell($tag,'',' class="adi_scripts_tag_header"');

        
// generate table
        
$out .= form(
            
startTable('','','txp-list')
            .
tag(
                
$tag_header_header
                
.tag(
                    
hcell(sp// filler for drag/drop icon
                    
.hcell(gTxt('adi_script'))
                    .
hcell(gTxt('adi_enabled'))
                    .
$tag_headers
                    
.hcell(gTxt('sections'))
                    .
hcell(gTxt('adi_ie_conditionals'))
                    .
hcell(gTxt('sort'),'',' class="adi_scripts_sort"')
                    .
hcell(gTxt('forget'))
                    ,
'tr'
                    
)
                ,
'thead'
            
)
            .
tag($script_settings,'tbody')
            .
endTable()
            .(
$unreadable_count graf(tag('* '.gTxt('adi_not_readable'),'em',' class="warning"')) : '')
            .
tag(
                
fInput("submit""do_something",gTxt('save'),'publish').
                
eInput("adi_scripts_admin").sInput("update")
                ,
'div'
                
,' class="adi_scripts_button"'
            
)
        );
    }
    else
        
$out .= graf(tag(gTxt('adi_none_found'),'em'));

    if (
$adi_scripts_debug)
        echo 
"UNREADABLE COUNT = $unreadable_count".br;

    
$adi_scripts_problem_count += $unreadable_count;

    return 
$out;
}

function 
adi_scripts_unmanaged_list($file_list) {
// unmanaged scripts
    
global $prefs,$adi_scripts_debug,$adi_scripts_problem_count;

    if (
$adi_scripts_debug) echo __FUNCTION__.':';

    
$out '';
    
$checkboxes '';
    
$unreadable_count 0;
    foreach (
$file_list as $dir => $files) {
        
$scripts_path $prefs['path_to_site'].'/'.$dir;
        foreach (
$files as $file) {
            
$row safe_row('*','adi_scripts',"filename='".doSlash($file)."' AND directory='".doSlash($dir)."'",$adi_scripts_debug);
            if (!
$row) { // not being managed
                
$file_path $scripts_path.'/'.$file;
                if (
is_readable($file_path))
                    
$asterisk '';
                else {
                    
$asterisk '*';
                    
$unreadable_count += 1;
                }
                
$checkboxes .=
                    
tr(
                        
tda(
                            
tag(
                                
$dir.'/'.$file.$asterisk
                                
,'label'
                                
,($asterisk ' class="warning"' '')
                            )
                        )
                        .
tda(
                            
checkbox("adi_scripts_new_list[$dir][]",$file,FALSE)
                            ,
' class="adi_scripts_manage"'
                        
)
                    );
            }
        }
    }
    
$out .= tag(gTxt('adi_scripts_unmanaged_scripts'),'h2');
    if (
$checkboxes) { // unmanaged scripts found in scripts directory
        
$out .= form(
                
startTable('','','txp-list')
                .
tag(
                    
tag(
                        
hcell(gTxt('adi_script'))
                        .
hcell(gTxt('manage'))
                        ,
'tr'
                    
)
                    ,
'thead'
                
)
                .
tag($checkboxes,'tbody')
                .
endTable()
                .(
$unreadable_count graf(tag('* '.gTxt('adi_not_readable'),'em',' class="warning"')) : '')
                .
tag(
                    
fInput("submit""do_something"gTxt('adi_scripts_manage_selected'), "smallerbox")
                    .
eInput("adi_scripts_admin").sInput("new_scripts")
                    ,
'div'
                    
,' class="adi_scripts_button"'
                
)
            );
    }
    else
        
$out .= graf(tag(gTxt('adi_none_found'),'em'));

    if (
$adi_scripts_debug)
        echo 
"UNREADABLE COUNT = $unreadable_count".br;

    
$adi_scripts_problem_count += $unreadable_count;

    return 
$out;
}

function 
adi_scripts_directories($directories) {
// directories of interest
    
global $prefs,$adi_scripts_problem_count;

    
$out '';
    
$markup '';
    
$unreadable_count 0;

    
// directories of interest
    
foreach ($directories as $dir) {
        
$scripts_path $prefs['path_to_site'].'/'.$dir;
        if (
is_readable($scripts_path))
            
$asterisk '';
        else {
            
$asterisk '*';
            
$unreadable_count += 1;
        }
        
$markup .=
            
tr(
                
tda(n// spacer for '+' column
                
.tda(
                    
tag(
                        
$dir.$asterisk
                        
,'label'
                        
,($asterisk ' class="warning"' '')
                    )
                )
                .
tda(
                    
checkbox("adi_scripts_dir[]",$dir,FALSE)
                    ,
' class="adi_scripts_manage"'
                
)
            );
    }
    
$markup .=
        
tr(
            
tda(
                
tag('+','b')
            )
            .
tda(
                
finput("text",'adi_scripts_dir[new]','','adi_scripts_new_dir')
            )
            .
tda(n)
        );

    
$out tag(gTxt('adi_directories'),'h2')
    .
form(
        
startTable('','','txp-list')
        .
tag(
            
tag(
                
hcell(n// spacer for '+' column
                
.hcell(gTxt('adi_directory'))
                .
hcell(gTxt('forget'))
                ,
'tr'
            
)
            ,
'thead'
        
)
        .
tag($markup,'tbody')
        .
endTable()
        .(
$unreadable_count graf(tag('* '.gTxt('adi_not_readable'),'em',' class="warning"')) : '')
        .
tag(
            
fInput("submit""do_something"gTxt('adi_update_directories'), "smallerbox")
            .
eInput("adi_scripts_admin")
            .
sInput("update_prefs")
            ,
'div'
            
,' class="adi_scripts_button"'
        
)
    );

    
$adi_scripts_problem_count += $unreadable_count;

    return 
$out;
}

function 
adi_scripts_new_tag() {
// introduce new tag in the mix

    
$out =
        
tag(gTxt('tags'),'h2')
        .
form(
            
graf(
                
finput("text",'adi_scripts_new_tag','','adi_scripts_text_input')
                .
fInput("submit""do_something"gTxt('adi_add_tag'), "smallerbox")
                .
eInput("adi_scripts_admin").sInput("new_tag")
            )
        );
    return 
$out;
}

function 
adi_scripts_manage_script($file,$directory) {
// bring a script into the fold
    
global $adi_scripts_debug;

    if (
$adi_scripts_debug) echo __FUNCTION__.':';
    
$set "filename='".doSlash($file)."', directory='".doSlash($directory)."', enabled=1, tags='', sections='', ie='', sort='255'";
    return 
safe_insert('adi_scripts',$set,$adi_scripts_debug);
}

function 
adi_scripts_update_settings($settings) {
// update script settings in the database
    
global $adi_scripts_debug;

    if (
$adi_scripts_debug) echo __FUNCTION__.':';
    
$res TRUE;
    foreach (
$settings as $setting) {
        
extract($setting);
        if (isset(
$setting['forget'])) {
            
$where "filename='".doSlash($filename)."' AND directory='".doSlash($directory)."'";
            
$res $res && safe_delete('adi_scripts',$where,$adi_scripts_debug);
        }
        else {
            if (isset(
$setting['enabled']))
                
$enabled $setting['enabled'];
            else
                
$enabled 0;
            if (
$sort == ''// set blank to zero
                
$sort 0;
            if (
array_key_exists('tags',$setting))
                
$tag_list doSlash(strtolower(implode(',',array_keys($setting['tags']))));
            else
                
$tag_list '';
            if (
array_key_exists('sections',$setting))
                
$section_list doSlash(implode(',',$setting['sections']));
            else
                
$section_list '';
            if (
$setting['all_sections']) // radio button
                
$section_list '';
            
$set "enabled=$enabled, tags='".$tag_list."', sections='".$section_list."', ie='".doSlash($ie)."', sort='".doSlash($sort)."'";
            
$where "filename='".doSlash($filename)."' AND directory='".doSlash($directory)."'";
            
$res $res && safe_update('adi_scripts',$set,$where,$adi_scripts_debug);
        }
    }

    
update_lastmod();
    return 
$res;
}

function 
adi_scripts_check_dir($directory) {
// nobody expects the Spanish Inquisition
    
global $prefs,$adi_scripts_debug;

    
$scripts_path $prefs['path_to_site'].'/'.$directory;
    
$message '';
    
// check scripts directory
    
if (file_exists($scripts_path)) {
        if (
$adi_scripts_debug) echo "$scripts_path found".br;
        if (
is_dir($scripts_path)) {
            if (
$adi_scripts_debug) echo "$scripts_path is a directory".br;
            if (
is_readable($scripts_path)) {
                if (
$adi_scripts_debug) echo "$scripts_path is readable".br;
            }
            else {
                if (
$adi_scripts_debug) echo "$scripts_path is not readable".br;
                
$message = array(gTxt('adi_scripts_dir_not_readable'),E_ERROR);
            }
        }
        else {
            if (
$adi_scripts_debug) echo "$scripts_path not a directory".br;
            
$message = array(gTxt('adi_scripts_dir_not_dir'),E_ERROR);
        }
    }
    else {
        if (
$adi_scripts_debug) echo "$scripts_path not found".br;
        
$message = array(gTxt('adi_scripts_dir_not_found'),E_ERROR);
    }

    return 
$message;
}

function 
adi_scripts_get_files($directory) {
// generate list of files in given directory
    
global $prefs,$adi_scripts_debug;

    
$file_list = array();
    
$scripts_path $prefs['path_to_site'].'/'.$directory;
    if (
$adi_scripts_debug)
        echo 
br."CONTENTS OF $directory".br;

    
// get filenames from directory & decide whether to ignore or not
    
if ($handle opendir($scripts_path)) {
        while (
false !== ($file readdir($handle))) {
            
$ok FALSE;
            
$diags $file' (';
            if (
is_dir($scripts_path.'/'.$file)) // directory
                
$diags .=  'DIR';
            else if (
strpos($file,'.') === 0// hidden file
                
$diags .=  'HIDDEN FILE';
            else if (
is_file($scripts_path.'/'.$file)) { // file
                
$diags .=  'FILE';
                
$path_parts pathinfo($file);
                if (isset(
$path_parts['extension'])) {
                    if (
$path_parts['extension'] != 'js')
                        
$diags .=  ' - WRONG EXTENSION';
                    else
                        
$ok TRUE;
                }
                else
                    
$diags .=  ' - NO EXTENSION';
            }
            if (!
$ok)
                
$diags .=  ' - IGNORED';
            if (
$ok && !is_readable($scripts_path.'/'.$file)) // script no readable
                
$diags .=  ' - NOT READABLE';
            if (
$adi_scripts_debug)
                echo 
$diags.')'.br;
            if (
$ok)
                
$file_list[] = $file;
        }
        
closedir($handle);
    }

    if (
$adi_scripts_debug) {
        echo 
br."FILTERED FILE LIST FROM $directory:".br;
        
dmp($file_list);
    }

    return 
$file_list;
}

function 
adi_scripts_section_checkboxes($field_name,$value) {
// generate section checkboxes

    
$section_list explode(',',$value);
    
$out '';
    
$rs safe_column('name''txp_section''1=1');
    if (
$rs) {
        foreach (
$rs as $section)
            
$out .= tag(checkbox($field_name.'[]',$section,(array_search($section,$section_list) !== FALSE '1' '0')).$section,'label');
        return 
$out;
    }

    return 
FALSE;
}

function 
adi_scripts_tag_list($new_tag='') {
// create list of tags from DB
    
global $adi_scripts_debug;

    
// get all tags in DB
    
$rows safe_rows('tags','adi_scripts','1=1');
    
$tag_list = array();
    foreach (
$rows as $row) {
        
$r explode(',',$row['tags']);
        
$tag_list array_merge($tag_list,$r);
    }
    
// new tag?
    
if ($new_tag != '')
        
$tag_list[] = $new_tag;
    
// create unique list
    
$tag_list array_unique($tag_list);
    
// sort
    
sort($tag_list);
    
// find empty "tag" (i.e. untagged) & lose it
    
$blank_key array_search('',$tag_list);
    if (
$blank_key !== FALSE)
        unset(
$tag_list[$blank_key]);

    if (
$adi_scripts_debug) {
        echo 
'TAG LIST:';
        
dmp($tag_list);
    }

    return 
$tag_list;
}

function 
adi_scripts($atts) {
// <txp:adi_scripts /> tag
    
global $prefs,$s;

    
extract(lAtts(array(
        
'tags'    => '',        // restrict to specified tagged scripts
        
'debug' => 0        // to also output <script> code
    
), $atts));

    
$out = array();

    
// HTML5 adjustment
    
$type ' type="text/javascript"';
    if (isset(
$prefs['doctype']))
        if (
$prefs['doctype'] == 'html5')
            
$type '';

    
// tagged?
    
if ($tags == '')
        
$tags_q '';
    else { 
// (stolen from keywords in publish.php)
        
$tag_list doSlash(do_list($tags));
        foreach (
$tag_list as $tag) {
            
$tagparts[] = "FIND_IN_SET('".$tag."',tags)";
        }
        
$tags_q " (" join(' OR ',$tagparts) . ") AND ";
    }

    
// get script filenames from database which are "enabled" ... and, if sections non-blank, match current section
    
$rows safe_rows('*','adi_scripts',"enabled=1 AND ".$tags_q."IF(sections='',1,FIND_IN_SET('".doSlash($s)."',sections)) ORDER BY sort");

    if (
$rows) { // output <script>...</script> markup
        
foreach ($rows as $row) {
            
extract($row);
            
$ie_start $ie_end '';
            if (
$ie) {
                
$ie_start "<!--[if $ie]>";
                
$ie_end '<![endif]-->';
            }
            
$out[] = $ie_start.'<script'.$type.' src="http://'.$prefs['siteurl'].'/'.$directory.'/'.$filename.'"></script>'.$ie_end;
        }
    }

    if (
$debug// output script markup as plain text
        
foreach ($out as $line)
            
$out[] = htmlentities($line).br;

    return 
implode("\n",$out);
}