CVE-2020-14067: Unrestricted Upload of File with Dangerous Type (CWE-434)
value: The install_from_hash functionality in Navigate CMS 2.9 does not consider the .phtml extension when examining files within a ZIP archive that may contain PHP code, in check_upload in lib/packages/extensions/extension.class.php and lib/packages/themes/theme.class.php.
CWE description: The product allows the upload or transfer of dangerous file types that are automatically processed within its environment.
CVSS v3 base score: 9.8
Published: 2020-06-15T01:15Z
Repository: https://github.com/NavigateCMS/Navigate-CMS
Language: PHP
Files changed: lib/packages/extensions/extension.class.php, lib/packages/extensions/extensions.js, lib/packages/extensions/extensions.php, lib/packages/themes/theme.class.php, lib/packages/themes/themes.js, lib/packages/themes/themes.php
Commit date: 2020-06-11 12:20:32 +0200
Commit message: * themes,extensions: secure "install_from_hash" functionality

Diff: diff --git a/lib/packages/extensions/extension.class.php b/lib/packages/extensions/extension.class.php
index aa47ce9b5..655c364f4 100644
--- a/lib/packages/extensions/extension.class.php
+++ b/lib/packages/extensions/extension.class.php
@@ -549,11 +549,11 @@ class extension
             core_remove_folder($tempdir);
             return false;
         }
 
         // check every php file included
-        $files = core_recursive_file_search($tempdir,  '/.*\/*.php/');
+        $files = core_recursive_file_search($tempdir,  '/.*\/*.(php|phtml)/');
 
         $prohibited_functions = array(
             'eval(',
             'system(',
             'exec(',
@@ -564,12 +564,16 @@ class extension
             '`' // https://www.php.net/manual/en/language.operators.execution.php
         );
 
         foreach($files as $file)
         {
-            // remove all spaces
+            if(!file_exists($file))
+            {
+                continue;
+            }
             $file_content = file_get_contents($file);
+            // remove all spaces
             $file_content = str_replace(array(' ', "\t", "\r", "\n"), '', $file_content);
 
             foreach($prohibited_functions as $pf)
             {
                 if(stripos($file_content, $pf) !== false)
diff --git a/lib/packages/extensions/extensions.js b/lib/packages/extensions/extensions.js
index 6f2b71c53..966ddca5b 100644
--- a/lib/packages/extensions/extensions.js
+++ b/lib/packages/extensions/extensions.js
@@ -1,233 +1,279 @@
-// make executable the runnable extensions
-$(".navigrid-item-buttonset[run='1'],.navigrid-item-buttonset[run='true']").parent().on("dblclick", function()
+function navigate_extensions_init()
 {
-    // is this extension enabled?
-    if($(this).find(".navigrid-item-buttonset").attr("enabled")=="0")
-        return;
-
-    var extension = $(this).find(".navigrid-item-buttonset").attr("extension");
-    //location.href = NAVIGATE_APP + "?fid=extensions&act=run&extension=" + extension;
-    location.href = NAVIGATE_APP + "?fid=ext_" + extension;
-});
+    // make executable the runnable extensions
+    $(".navigrid-item-buttonset[run='1'],.navigrid-item-buttonset[run='true']").parent().on("dblclick", function()
+    {
+        // is this extension enabled?
+        if($(this).find(".navigrid-item-buttonset").attr("enabled")=="0")
+            return;
 
-// open configuration on NON runnable extensions (if configuration is available)
-$(".navigrid-item-buttonset[run='']").parent().on("dblclick", function()
-{
-    // is this extension enabled?
-    if($(this).find(".navigrid-item-buttonset").attr("enabled")=="0")
-        return;
+        var extension = $(this).find(".navigrid-item-buttonset").attr("extension");
+        //location.href = NAVIGATE_APP + "?fid=extensions&act=run&extension=" + extension;
+        location.href = NAVIGATE_APP + "?fid=ext_" + extension;
+    });
 
-    // has this extension a configuration option?
-    if($(this).find('.navigrid-extensions-settings').length > 0)
-        $(this).find('.navigrid-extensions-settings').trigger('click');
-});
+    // open configuration on NON runnable extensions (if configuration is available)
+    $(".navigrid-item-buttonset[run='']").parent().on("dblclick", function()
+    {
+        // is this extension enabled?
+        if($(this).find(".navigrid-item-buttonset").attr("enabled")=="0")
+            return;
 
-// show extension info window
-$(".navigrid-extensions-info").bind("click", function()
-{
-    var extension = $(this).parent().attr("extension");
+        // has this extension a configuration option?
+        if($(this).find('.navigrid-extensions-settings').length > 0)
+            $(this).find('.navigrid-extensions-settings').trigger('click');
+    });
 
-    $("#navigrid-extension-information").attr("title", $(this).parent().attr("extension-title"));
-    $("#navigrid-extension-information").load("?fid=extensions&act=extension_info&extension=" + extension, function()
+    // show extension info window
+    $(".navigrid-extensions-info").bind("click", function()
     {
-        $("#navigrid-extension-information").dialog(
-            {
-                width: 700,
-                height: 500,
-                modal: true,
-                title: "<img src=\"img/icons/silk/information.png\" align=\"absmiddle\"> " + $("#navigrid-extension-information").attr("title")
-            }).dialogExtend(
-            {
-                maximizable: true
-            });
-    });
-});
+        var extension = $(this).parent().attr("extension");
 
-// disable extension
-$(".navigrid-extensions-disable").bind("click", function()
-{
-    var extension = $(this).parent().attr("extension");
-    $.post(
-        NAVIGATE_APP + "?fid=extensions&act=disable",
-        { extension: extension },
-        function(data)
+        $("#navigrid-extension-information").attr("title", $(this).parent().attr("extension-title"));
+        $("#navigrid-extension-information").load("?fid=extensions&act=extension_info&extension=" + extension, function()
         {
-            $("div#item-" + extension).find(".navigrid-extensions-enable").hide();
-            $("div#item-" + extension).find(".navigrid-extensions-disable").hide();
-            $("div#item-" + extension).find(".navigrid-extensions-remove").hide();
+            $("#navigrid-extension-information").dialog(
+                {
+                    width: 700,
+                    height: 500,
+                    modal: true,
+                    title: "<img src=\"img/icons/silk/information.png\" align=\"absmiddle\"> " + $("#navigrid-extension-information").attr("title")
+                }).dialogExtend(
+                {
+                    maximizable: true
+                });
+        });
+    });
 
-            if(data=="true")
-            {
-                $("div#item-" + extension).find(".navigrid-extensions-enable").show();
-                $("div#item-" + extension).find(".navigrid-extensions-remove").show();
-                $("div#item-" + extension).find(".navigrid-item-buttonset").attr("enabled", 1);
-            }
-            else
+    // disable extension
+    $(".navigrid-extensions-disable").on("click", function()
+    {
+        var extension = $(this).parent().attr("extension");
+        $.post(
+            NAVIGATE_APP + "?fid=extensions&act=disable",
+            { extension: extension },
+            function(data)
             {
-                $("div#item-" + extension).find(".navigrid-extensions-disable").show();
-            }
+                $("div#item-" + extension).find(".navigrid-extensions-enable").hide();
+                $("div#item-" + extension).find(".navigrid-extensions-disable").hide();
+                $("div#item-" + extension).find(".navigrid-extensions-remove").hide();
 
-            navigate_extensions_refresh();
-        });
-});
+                if(data=="true")
+                {
+                    $("div#item-" + extension).find(".navigrid-extensions-enable").show();
+                    $("div#item-" + extension).find(".navigrid-extensions-remove").show();
+                    $("div#item-" + extension).find(".navigrid-item-buttonset").attr("enabled", 1);
+                }
+                else
+                {
+                    $("div#item-" + extension).find(".navigrid-extensions-disable").show();
+                }
 
-// enable extension
-$(".navigrid-extensions-enable").bind("click", function()
-{
-    var extension = $(this).parent().attr("extension");
-    $.post(
-        NAVIGATE_APP + "?fid=extensions&act=enable",
-        { extension: extension },
-        function(data)
-        {
-            $("div#item-" + extension).find(".navigrid-extensions-enable").hide();
-            $("div#item-" + extension).find(".navigrid-extensions-disable").hide();
-            $("div#item-" + extension).find(".navigrid-extensions-remove").hide();
+                navigate_extensions_refresh();
+            });
+    });
 
-            if(data=="true")
-            {
-                $("div#item-" + extension).find(".navigrid-extensions-disable").show();
-            }
-            else
+    // enable extension
+    $(".navigrid-extensions-enable").on("click", function()
+    {
+        var extension = $(this).parent().attr("extension");
+        $.post(
+            NAVIGATE_APP + "?fid=extensions&act=enable",
+            { extension: extension },
+            function(data)
             {
-                $("div#item-" + extension).find(".navigrid-extensions-enable").show();
-                $("div#item-" + extension).find(".navigrid-extensions-remove").show();
-            }
+                $("div#item-" + extension).find(".navigrid-extensions-enable").hide();
+                $("div#item-" + extension).find(".navigrid-extensions-disable").hide();
+                $("div#item-" + extension).find(".navigrid-extensions-remove").hide();
 
-            navigate_extensions_refresh();
-        });
-});
+                if(data=="true")
+                {
+                    $("div#item-" + extension).find(".navigrid-extensions-disable").show();
+                }
+                else
+                {
+                    $("div#item-" + extension).find(".navigrid-extensions-enable").show();
+                    $("div#item-" + extension).find(".navigrid-extensions-remove").show();
+                }
 
-// add extension as favorite
-$(".navigrid-extensions-favorite").bind("click", function()
-{
-    var extension = $(this).parent().attr("extension");
-    var add_as_favorite = ($(this).parent().attr("favorite")==0);
-    var el = this;
-
-    $.post(
-        NAVIGATE_APP + "?fid=extensions&act=favorite",
-        { extension: extension,
-            value: (add_as_favorite? 1 : 0)
-        },
-        function(data)
-        {
-            $(el).find("img").removeClass("silk-heart_add");
-            $(el).find("img").removeClass("silk-heart_delete");
+                navigate_extensions_refresh();
+            });
+    });
 
-            if(data=="true")
+    // add extension as favorite
+    $(".navigrid-extensions-favorite").on("click", function()
+    {
+        var extension = $(this).parent().attr("extension");
+        var add_as_favorite = ($(this).parent().attr("favorite")==0);
+        var el = this;
+
+        $.post(
+            NAVIGATE_APP + "?fid=extensions&act=favorite",
+            { extension: extension,
+                value: (add_as_favorite? 1 : 0)
+            },
+            function(data)
             {
-                if(add_as_favorite)
+                $(el).find("img").removeClass("silk-heart_add");
+                $(el).find("img").removeClass("silk-heart_delete");
+
+                if(data=="true")
                 {
-                    $(el).parent().attr("favorite", 1);
-                    $(el).find("img").addClass("silk-heart_delete");
+                    if(add_as_favorite)
+                    {
+                        $(el).parent().attr("favorite", 1);
+                        $(el).find("img").addClass("silk-heart_delete");
+                    }
+                    else
+                    {
+                        $(el).parent().attr("favorite", 0);
+                        $(el).find("img").addClass("silk-heart_add");
+                    }
                 }
                 else
                 {
-                    $(el).parent().attr("favorite", 0);
-                    $(el).find("img").addClass("silk-heart_add");
+                    // show error
+                    navigate_notification(navigate_lang_dictionary[56]);
                 }
-            }
-            else
-            {
-                // show error
-                navigate_notification(navigate_lang_dictionary[56]);
-            }
-
-            navigate_extensions_refresh();
-        });
-});
-
-$(".navigrid-extensions-settings").on("click", function()
-{
-    var extension = $(this).parent().attr("extension");
 
-    $("#navigrid-extension-options").attr("title", $(this).parent().attr("extension-title"));
-    //$("#navigrid-extension-options").load("?fid=extensions&act=options&extension=" + extension, function()
-    $("#navigrid-extension-options").html('<iframe width="100%" height="100%" frameborder="0" src="?fid=extensions&act=options&extension=' + extension + '"></iframe>');
+                navigate_extensions_refresh();
+            });
+    });
 
-    $("#navigrid-extension-options").dialog(
-    {
-        width: $(window).width() * 0.95,
-        height: $(window).height() * 0.95,
-        modal: true,
-        title: "<img src=\"img/icons/silk/cog.png\" align=\"absmiddle\"> " + $("#navigrid-extension-options").attr("title")
-    }).dialogExtend(
+    $(".navigrid-extensions-settings").on("click", function()
     {
-        maximizable: true
-    });
-});
+        var extension = $(this).parent().attr("extension");
 
-$(".navigrid-extensions-remove").bind("click", function()
-{
-    var extension = $(this).parent().attr("extension");
+        $("#navigrid-extension-options").attr("title", $(this).parent().attr("extension-title"));
+        //$("#navigrid-extension-options").load("?fid=extensions&act=options&extension=" + extension, function()
+        $("#navigrid-extension-options").html('<iframe width="100%" height="100%" frameborder="0" src="?fid=extensions&act=options&extension=' + extension + '"></iframe>');
 
-    $("#navigrid-extensions-remove-confirmation").dialog(
+        $("#navigrid-extension-options").dialog(
         {
-            resizable: true,
-            width: 300,
-            height: 150,
+            width: $(window).width() * 0.95,
+            height: $(window).height() * 0.95,
             modal: true,
-            buttons:
-                [
-                    {
-                        text: navigate_lang_dictionary[190],
-                        click: function()
+            title: "<img src=\"img/icons/silk/cog.png\" align=\"absmiddle\"> " + $("#navigrid-extension-options").attr("title")
+        }).dialogExtend(
+        {
+            maximizable: true
+        });
+    });
+
+    $(".navigrid-extensions-remove").bind("click", function()
+    {
+        var extension = $(this).parent().attr("extension");
+
+        $("#navigrid-extensions-remove-confirmation").dialog(
+            {
+                resizable: true,
+                width: 300,
+                height: 150,
+                modal: true,
+                buttons:
+                    [
                         {
-                            $.post(
-                                NAVIGATE_APP + "?fid=extensions&act=remove&extension=" + extension,
-                                { },
-                                function(data)
-                                {
-                                    if(data=="true")
-                                    {
-                                        $("#item-" + extension).fadeOut("slow", function(){ $("#item-" + extension).remove(); });
-                                    }
-                                    else
+                            text: navigate_lang_dictionary[190],
+                            click: function()
+                            {
+                                $.post(
+                                    NAVIGATE_APP + "?fid=extensions&act=remove&extension=" + extension,
+                                    { },
+                                    function(data)
                                     {
-                                        navigate_notification(navigate_lang_dictionary[56]);
+                                        if(data=="true")
+                                        {
+                                            $("#item-" + extension).fadeOut("slow", function(){ $("#item-" + extension).remove(); });
+                                        }
+                                        else
+                                        {
+                                            navigate_notification(navigate_lang_dictionary[56]);
+                                        }
                                     }
-                                }
-                            );
-                            $( this ).dialog( "close" );
-                        }
-                    },
-                    {
-                        text: navigate_lang_dictionary[58],
-                        click: function()
+                                );
+                                $( this ).dialog( "close" );
+                            }
+                        },
                         {
-                            $( this ).dialog( "close" );
+                            text: navigate_lang_dictionary[58],
+                            click: function()
+                            {
+                                $( this ).dialog( "close" );
+                            }
                         }
-                    }
-                ]
-        });
-    return false;
-});
+                    ]
+            });
+        return false;
+    });
 
-$(".navigrid-extensions-update").on("click", function()
-{
-    var extension = $(this).parent().attr("extension");
+    $(".navigrid-extensions-update").on("click", function()
+    {
+        var extension = $(this).parent().attr("extension");
+
+        $("#navigrid-extensions-update").dialog(
+            {
+                resizable: false,
+                width: 980,
+                height: 650,
+                modal: true
+            }
+        );
+
+        $("#navigrid-extensions-update").find('iframe').
+            css({
+                "width": "960",
+                "height": 600
+            }).
+            attr('src', 'http://www.navigatecms.com/en/marketplace/purchase?extension='+extension+'&get_update')
+
+        return false;
+    });
+
+    $(".navigrid-item-buttonset").each(function(i, el)
+    {
+        $(el).hide().css("visibility", "visible");
+        $(el).fadeIn();
+        $(".navigrid-extensions-disable").addClass("ui-corner-right");
+    });
+
+    $("#extension-upload-button").on("click", function()
+    {
+        $("#extension-upload-button").parent().find("form").remove();
+        $("#extension-upload-button").after('<form action="?fid=extensions&act=extension_upload" enctype="multipart/form-data" method="post"></form>');
+        $("#extension-upload-button").next().append('<input type="hidden" id="_nv_csrf_token" name="_nv_csrf_token" value="'+navigatecms.csrf_token+'" />');
+        $("#extension-upload-button").next().append('<input type="file" name="extension-upload" style=" display: none;" />');
 
-    $("#navigrid-extensions-update").dialog(
+        $("#extension-upload-button").next().find("input").on("change", function()
         {
-            resizable: false,
-            width: 980,
-            height: 650,
-            modal: true
-        }
-    );
+            if($(this).val()!="")
+            {
+                $(this).parent().submit();
+            }
+        });
+        $("#extension-upload-button").next().find("input").trigger("click");
 
-    $("#navigrid-extensions-update").find('iframe').
-        css({
-            "width": "960",
-            "height": 600
-        }).
-        attr('src', 'http://www.navigatecms.com/en/marketplace/purchase?extension='+extension+'&get_update')
+        return false;
+    });
+}
+
+function navitable_quicksearch(value)
+{
+    $(".navigrid-item").hide();
 
-    return false;
-});
+    if(value=="")
+        $(".navigrid-item").show();
+    else
+    {
+        $(".navigrid-item").each(function(i, el)
+        {
+            var item_text = $(el).text().toLowerCase();
+            if( item_text.indexOf(value.toLowerCase()) >= 0 )
+                $(el).fadeIn();
+        });
+    }
+}
 
 function navigate_extensions_refresh()
 {
     $(".navigrid-extensions-enable").each(function(i, el)
     {
diff --git a/lib/packages/extensions/extensions.php b/lib/packages/extensions/extensions.php
index a384fc03a..fa838c0f0 100644
--- a/lib/packages/extensions/extensions.php
+++ b/lib/packages/extensions/extensions.php
@@ -156,44 +156,55 @@ function run()
             $url = base64_decode($_GET['hash']);
 
             if(!empty($url) && $user->permission("extensions.install")=="true")
             {
                 $error = false;
+                $tmp_file = NULL;
+
                 parse_str(parse_url($url, PHP_URL_QUERY), $query);
 
-                $tmp_file = sys_get_temp_dir().DIRECTORY_SEPARATOR.$query['code'].'.zip';
-                @core_file_curl($url, $tmp_file);
-                if(@filesize($tmp_file) == 0)
+                if(parse_url($url, PHP_URL_HOST) == 'www.navigatecms.com')
                 {
-                    @unlink($tmp_file);
-                    // core file curl failed, try using file_get_contents...
-                    $tmp = @file_get_contents($url);
-                    if(!empty($tmp))
-                    {
-                        @file_put_contents($tmp_file, $tmp);
-                    }
-                    unset($tmp);
+                    $tmp_file = sys_get_temp_dir().DIRECTORY_SEPARATOR.$query['code'].'.zip';
+                    @core_file_curl($url, $tmp_file);
                 }
 
-                if(@filesize($tmp_file) > 0)
+                if(!empty($tmp_file) && @filesize($tmp_file) > 0)
                 {
-                    // uncompress ZIP and copy it to the extensions dir
-                    @mkdir(NAVIGATE_PATH.'/plugins/'.$query['code']);
+                    $secure = extension::check_upload(
+                        array(
+                            'type' => mime_content_type($tmp_file),
+                            'name' => $query['code'].'.zip',
+                            'tmp_name' => $tmp_file
+                        ),
+                        $query['code']
+                    );
 
-                    $zip = new ZipArchive();
-                    $zip_open_status = $zip->open($tmp_file);
-                    if($zip_open_status === TRUE)
+                    if($secure !== true)
                     {
-                        $zip->extractTo(NAVIGATE_PATH.'/plugins/'.$query['code']);
-                        $zip->close();
-
-                        $layout->navigate_notification(t(374, "Item installed successfully."), false);
+                        $layout->navigate_notification(t(344, 'Security error'), true, true);
+                        $error = true;
                     }
-                    else // zip extraction failed
+                    else // everything seems fine, go ahead
                     {
-                        $layout->navigate_notification('ERROR '.$zip_open_status, true, true);
-                        $error = true;
+                        // uncompress ZIP and copy it to the extensions dir
+                        @mkdir(NAVIGATE_PATH.'/plugins/'.$query['code']);
+
+                        $zip = new ZipArchive();
+                        $zip_open_status = $zip->open($tmp_file);
+                        if($zip_open_status === TRUE)
+                        {
+                            $zip->extractTo(NAVIGATE_PATH.'/plugins/'.$query['code']);
+                            $zip->close();
+
+                            $layout->navigate_notification(t(374, "Item installed successfully."), false);
+                        }
+                        else // zip extraction failed
+                        {
+                            $layout->navigate_notification('ERROR '.$zip_open_status, true, true);
+                            $error = true;
+                        }
                     }
                 }
                 else
                 {
                     $layout->navigate_notification(t(56, 'Unexpected error'), true, true);
@@ -211,17 +222,25 @@ function run()
                         </div>
                     ');
                     $layout->add_script('
                         $("#navigate_marketplace_install_from_hash_error").dialog({
                             modal: true,
-                            title: "'.t(56, "Unexpected error").'"
+                            title: "'.t(56, "Unexpected error").'",
+                            close: function()
+                            {
+                                window.location.replace("?fid=extensions");
+                            }
                         });
                     ');
                 }
-
+                else
+                {
+                    // redirect to extensions grid
+                    core_terminate('?fid=extensions');
+                }
             }
-        // don't break, we want to show the themes grid right now (theme_upload by browser upload won't trigger)
+            break;
 
         case 'extension_upload':
             if(!naviforms::check_csrf_token())
             {
                 $layout->navigate_notification(t(344, 'Security error'), true, true);
@@ -391,55 +410,14 @@ function extensions_grid($list)
                 dataType: "script",
                 cache: true,
                 url: "lib/packages/extensions/extensions.js?r='.$current_version->revision.'",
                 complete: function()
                 {                   
+                    navigate_extensions_init();
                     navigate_extensions_refresh();
                 }
             });
-
-            $(window).on("load", function()
-            {
-                $(".navigrid-item-buttonset").each(function(i, el)
-                {
-                    $(el).hide().css("visibility", "visible");
-                    $(el).fadeIn();
-                    $(".navigrid-extensions-disable").addClass("ui-corner-right");
-                });
-            });
-
-            function navitable_quicksearch(value)
-            {
-                $(".navigrid-item").hide();
-
-                if(value=="")
-                    $(".navigrid-item").show();
-                else
-                {
-                    $(".navigrid-item").each(function(i, el)
-                    {
-                        var item_text = $(el).text().toLowerCase();
-                        if( item_text.indexOf(value.toLowerCase()) >= 0 )
-                            $(el).fadeIn();
-                    });
-                }
-            }
-            
-            $("#extension-upload-button").on("click", function()
-            {
-                $("#extension-upload-button").parent().find("form").remove();
-                $("#extension-upload-button").after(\'<form action="?fid=extensions&act=extension_upload" enctype="multipart/form-data" method="post"><input type="file" name="extension-upload" style=" display: none;" /><input type="hidden" id="_nv_csrf_token" name="_nv_csrf_token" value="\'+navigatecms.csrf_token+\'" /></form>\');
-                $("#extension-upload-button").next().find("input").on("change", function()
-                {
-                    if($(this).val()!="")
-                        $(this).parent().submit();
-                });
-                $("#extension-upload-button").next().find("input").trigger("click");
-
-                return false;
-            });
-
         ');
     }
     else
     {
         $html = '
diff --git a/lib/packages/themes/theme.class.php b/lib/packages/themes/theme.class.php
index 45d5234d4..89ec49d7b 100644
--- a/lib/packages/themes/theme.class.php
+++ b/lib/packages/themes/theme.class.php
@@ -550,11 +550,11 @@ class theme
             core_remove_folder($tempdir);
             return false;
         }
 
         // check every php file included
-        $files = core_recursive_file_search($tempdir,  '/.*\/*.php/');
+        $files = core_recursive_file_search($tempdir,  '/.*\/*.(php|phtml)/');
 
         $prohibited_functions = array(
             'eval(',
             'system(',
             'exec(',
@@ -565,12 +565,16 @@ class theme
             '`' // https://www.php.net/manual/en/language.operators.execution.php
         );
 
         foreach($files as $file)
         {
-            // remove all spaces
+            if(!file_exists($file))
+            {
+                continue;
+            }
             $file_content = file_get_contents($file);
+            // remove all spaces
             $file_content = str_replace(array(' ', "\t", "\r", "\n"), '', $file_content);
 
             foreach($prohibited_functions as $pf)
             {
                 if(stripos($file_content, $pf) !== false)
diff --git a/lib/packages/themes/themes.js b/lib/packages/themes/themes.js
index c3910b570..1924e173b 100644
--- a/lib/packages/themes/themes.js
+++ b/lib/packages/themes/themes.js
@@ -108,16 +108,19 @@ function navigate_themes_init()
     $("#theme-upload-button").on("click", function(e)
     {
         e.stopPropagation();
         e.preventDefault();
         $("#theme-upload-button").parent().find("form").remove();
-        $("#theme-upload-button").after('<form action="?fid=themes&act=theme_upload" enctype="multipart/form-data" method="post"><input type="file" name="theme-upload" style=" display: none;" /><input type="hidden" id="_nv_csrf_token" name="_nv_csrf_token" value="'+navigatecms.csrf_token+'" /></form>');
+        $("#theme-upload-button").after('<form action="?fid=themes&act=theme_upload" enctype="multipart/form-data" method="post"></form>');
+        $("#theme-upload-button").next().append('<input type="hidden" id="_nv_csrf_token" name="_nv_csrf_token" value="'+navigatecms.csrf_token+'" />');
+        $("#theme-upload-button").next().append('<input type="file" name="theme-upload" style=" display: none;" />');
         $("#theme-upload-button").next().find("input").on("change", function()
         {
             if($(this).val()!="")
             {
                 $(this).parent().submit();
+                return false;
             }
         });
         $("#theme-upload-button").next().find("input").trigger("click");
 
         return false;
diff --git a/lib/packages/themes/themes.php b/lib/packages/themes/themes.php
index 5bf429542..53d95836b 100644
--- a/lib/packages/themes/themes.php
+++ b/lib/packages/themes/themes.php
@@ -112,44 +112,55 @@ function run()
             $url = base64_decode($_GET['hash']);
 
             if(!empty($url) && $user->permission("themes.install")=="true")
             {
                 $error = false;
+                $tmp_file = NULL;
+
                 parse_str(parse_url($url, PHP_URL_QUERY), $query);
 
-                $tmp_file = sys_get_temp_dir() . DIRECTORY_SEPARATOR . $query['code'] . '.zip';
-                @core_file_curl($url, $tmp_file);
-                if(@filesize($tmp_file) == 0)
+                if(parse_url($url, PHP_URL_HOST) == 'www.navigatecms.com')
                 {
-                    @unlink($tmp_file);
-                    // core file curl failed, try using file_get_contents...
-                    $tmp = @file_get_contents($url);
-                    if(!empty($tmp))
-                    {
-                        @file_put_contents($tmp_file, $tmp);
-                    }
-                    unset($tmp);
+                    $tmp_file = sys_get_temp_dir().DIRECTORY_SEPARATOR.$query['code'].'.zip';
+                    @core_file_curl($url, $tmp_file);
                 }
 
-                if(@filesize($tmp_file) > 0)
+                if(!empty($tmp_file) && @filesize($tmp_file) > 0)
                 {
-                    // uncompress ZIP and copy it to the themes dir
-                    @mkdir(NAVIGATE_PATH.'/themes/'.$query['code']);
+                    $secure = theme::check_upload(
+                        array(
+                            'type' => mime_content_type($tmp_file),
+                            'name' => $query['code'].'.zip',
+                            'tmp_name' => $tmp_file
+                        ),
+                        $query['code']
+                    );
 
-                    $zip = new ZipArchive();
-                    $zip_open_status = $zip->open($tmp_file);
-                    if($zip_open_status === TRUE)
+                    if($secure !== true)
                     {
-                        $zip->extractTo(NAVIGATE_PATH.'/themes/'.$query['code']);
-                        $zip->close();
-
-                        $layout->navigate_notification(t(374, "Item installed successfully."), false);
+                        $layout->navigate_notification(t(344, 'Security error'), true, true);
+                        $error = true;
                     }
-                    else // zip extraction failed
+                    else // everything seems fine, go ahead
                     {
-                        $layout->navigate_notification('ERROR '.$zip_open_status, true, true);
-                        $error = true;
+                        // uncompress ZIP and copy it to the themes dir
+                        @mkdir(NAVIGATE_PATH.'/themes/'.$query['code']);
+
+                        $zip = new ZipArchive();
+                        $zip_open_status = $zip->open($tmp_file);
+                        if($zip_open_status === TRUE)
+                        {
+                            $zip->extractTo(NAVIGATE_PATH.'/themes/'.$query['code']);
+                            $zip->close();
+
+                            $layout->navigate_notification(t(374, "Item installed successfully."), false);
+                        }
+                        else // zip extraction failed
+                        {
+                            $layout->navigate_notification('ERROR '.$zip_open_status, true, true);
+                            $error = true;
+                        }
                     }
                 }
                 else
                 {
                     $layout->navigate_notification(t(56, 'Unexpected error'), true, true);
@@ -167,16 +178,25 @@ function run()
                         </div>
                     ');
                     $layout->add_script('
                         $("#navigate_marketplace_install_from_hash_error").dialog({
                             modal: true,
-                            title: "'.t(56, "Unexpected error").'"
+                            title: "'.t(56, "Unexpected error").'",
+                            close: function()
+                            {
+                                window.location.replace("?fid=themes");
+                            }
                         });
                     ');
                 }
+                else
+                {
+                    // redirect to themes grid
+                    core_terminate('?fid=themes');
+                }
             }
-            // don't break, we want to show the themes grid right now (theme_upload by browser upload won't trigger)
+            break;
 
         case 'theme_upload':
             if(!naviforms::check_csrf_token())
             {
                 $layout->navigate_notification(t(344, 'Security error'), true, true);

Vulnerable code:         $files = core_recursive_file_search($tempdir,  '/.*\/*.php/');
            // remove all spaces
// make executable the runnable extensions
$(".navigrid-item-buttonset[run='1'],.navigrid-item-buttonset[run='true']").parent().on("dblclick", function()
    // is this extension enabled?
    if($(this).find(".navigrid-item-buttonset").attr("enabled")=="0")
        return;

    var extension = $(this).find(".navigrid-item-buttonset").attr("extension");
    //location.href = NAVIGATE_APP + "?fid=extensions&act=run&extension=" + extension;
    location.href = NAVIGATE_APP + "?fid=ext_" + extension;
});
// open configuration on NON runnable extensions (if configuration is available)
$(".navigrid-item-buttonset[run='']").parent().on("dblclick", function()
{
    // is this extension enabled?
    if($(this).find(".navigrid-item-buttonset").attr("enabled")=="0")
        return;
    // has this extension a configuration option?
    if($(this).find('.navigrid-extensions-settings').length > 0)
        $(this).find('.navigrid-extensions-settings').trigger('click');
});
// show extension info window
$(".navigrid-extensions-info").bind("click", function()
{
    var extension = $(this).parent().attr("extension");
    $("#navigrid-extension-information").attr("title", $(this).parent().attr("extension-title"));
    $("#navigrid-extension-information").load("?fid=extensions&act=extension_info&extension=" + extension, function()
        $("#navigrid-extension-information").dialog(
            {
                width: 700,
                height: 500,
                modal: true,
                title: "<img src=\"img/icons/silk/information.png\" align=\"absmiddle\"> " + $("#navigrid-extension-information").attr("title")
            }).dialogExtend(
            {
                maximizable: true
            });
    });
});
// disable extension
$(".navigrid-extensions-disable").bind("click", function()
{
    var extension = $(this).parent().attr("extension");
    $.post(
        NAVIGATE_APP + "?fid=extensions&act=disable",
        { extension: extension },
        function(data)
            $("div#item-" + extension).find(".navigrid-extensions-enable").hide();
            $("div#item-" + extension).find(".navigrid-extensions-disable").hide();
            $("div#item-" + extension).find(".navigrid-extensions-remove").hide();
            if(data=="true")
            {
                $("div#item-" + extension).find(".navigrid-extensions-enable").show();
                $("div#item-" + extension).find(".navigrid-extensions-remove").show();
                $("div#item-" + extension).find(".navigrid-item-buttonset").attr("enabled", 1);
            }
            else
                $("div#item-" + extension).find(".navigrid-extensions-disable").show();
            }
            navigate_extensions_refresh();
        });
});
// enable extension
$(".navigrid-extensions-enable").bind("click", function()
{
    var extension = $(this).parent().attr("extension");
    $.post(
        NAVIGATE_APP + "?fid=extensions&act=enable",
        { extension: extension },
        function(data)
        {
            $("div#item-" + extension).find(".navigrid-extensions-enable").hide();
            $("div#item-" + extension).find(".navigrid-extensions-disable").hide();
            $("div#item-" + extension).find(".navigrid-extensions-remove").hide();
            if(data=="true")
            {
                $("div#item-" + extension).find(".navigrid-extensions-disable").show();
            }
            else
                $("div#item-" + extension).find(".navigrid-extensions-enable").show();
                $("div#item-" + extension).find(".navigrid-extensions-remove").show();
            }
            navigate_extensions_refresh();
        });
});
// add extension as favorite
$(".navigrid-extensions-favorite").bind("click", function()
{
    var extension = $(this).parent().attr("extension");
    var add_as_favorite = ($(this).parent().attr("favorite")==0);
    var el = this;

    $.post(
        NAVIGATE_APP + "?fid=extensions&act=favorite",
        { extension: extension,
            value: (add_as_favorite? 1 : 0)
        },
        function(data)
        {
            $(el).find("img").removeClass("silk-heart_add");
            $(el).find("img").removeClass("silk-heart_delete");
            if(data=="true")
                if(add_as_favorite)
                    $(el).parent().attr("favorite", 1);
                    $(el).find("img").addClass("silk-heart_delete");
                    $(el).parent().attr("favorite", 0);
                    $(el).find("img").addClass("silk-heart_add");
            }
            else
            {
                // show error
                navigate_notification(navigate_lang_dictionary[56]);
            }

            navigate_extensions_refresh();
        });
});

$(".navigrid-extensions-settings").on("click", function()
{
    var extension = $(this).parent().attr("extension");
    $("#navigrid-extension-options").attr("title", $(this).parent().attr("extension-title"));
    //$("#navigrid-extension-options").load("?fid=extensions&act=options&extension=" + extension, function()
    $("#navigrid-extension-options").html('<iframe width="100%" height="100%" frameborder="0" src="?fid=extensions&act=options&extension=' + extension + '"></iframe>');
    $("#navigrid-extension-options").dialog(
    {
        width: $(window).width() * 0.95,
        height: $(window).height() * 0.95,
        modal: true,
        title: "<img src=\"img/icons/silk/cog.png\" align=\"absmiddle\"> " + $("#navigrid-extension-options").attr("title")
    }).dialogExtend(
        maximizable: true
    });
});
$(".navigrid-extensions-remove").bind("click", function()
{
    var extension = $(this).parent().attr("extension");
    $("#navigrid-extensions-remove-confirmation").dialog(
            resizable: true,
            width: 300,
            height: 150,
            buttons:
                [
                    {
                        text: navigate_lang_dictionary[190],
                        click: function()
                            $.post(
                                NAVIGATE_APP + "?fid=extensions&act=remove&extension=" + extension,
                                { },
                                function(data)
                                {
                                    if(data=="true")
                                    {
                                        $("#item-" + extension).fadeOut("slow", function(){ $("#item-" + extension).remove(); });
                                    }
                                    else
                                        navigate_notification(navigate_lang_dictionary[56]);
                                }
                            );
                            $( this ).dialog( "close" );
                        }
                    },
                    {
                        text: navigate_lang_dictionary[58],
                        click: function()
                            $( this ).dialog( "close" );
                    }
                ]
        });
    return false;
});
$(".navigrid-extensions-update").on("click", function()
{
    var extension = $(this).parent().attr("extension");
    $("#navigrid-extensions-update").dialog(
            resizable: false,
            width: 980,
            height: 650,
            modal: true
        }
    );
    $("#navigrid-extensions-update").find('iframe').
        css({
            "width": "960",
            "height": 600
        }).
        attr('src', 'http://www.navigatecms.com/en/marketplace/purchase?extension='+extension+'&get_update')
    return false;
});
                $tmp_file = sys_get_temp_dir().DIRECTORY_SEPARATOR.$query['code'].'.zip';
                @core_file_curl($url, $tmp_file);
                if(@filesize($tmp_file) == 0)
                    @unlink($tmp_file);
                    // core file curl failed, try using file_get_contents...
                    $tmp = @file_get_contents($url);
                    if(!empty($tmp))
                    {
                        @file_put_contents($tmp_file, $tmp);
                    }
                    unset($tmp);
                if(@filesize($tmp_file) > 0)
                    // uncompress ZIP and copy it to the extensions dir
                    @mkdir(NAVIGATE_PATH.'/plugins/'.$query['code']);
                    $zip = new ZipArchive();
                    $zip_open_status = $zip->open($tmp_file);
                    if($zip_open_status === TRUE)
                        $zip->extractTo(NAVIGATE_PATH.'/plugins/'.$query['code']);
                        $zip->close();

                        $layout->navigate_notification(t(374, "Item installed successfully."), false);
                    else // zip extraction failed
                        $layout->navigate_notification('ERROR '.$zip_open_status, true, true);
                        $error = true;
                            title: "'.t(56, "Unexpected error").'"

        // don't break, we want to show the themes grid right now (theme_upload by browser upload won't trigger)

            $(window).on("load", function()
            {
                $(".navigrid-item-buttonset").each(function(i, el)
                {
                    $(el).hide().css("visibility", "visible");
                    $(el).fadeIn();
                    $(".navigrid-extensions-disable").addClass("ui-corner-right");
                });
            });

            function navitable_quicksearch(value)
            {
                $(".navigrid-item").hide();

                if(value=="")
                    $(".navigrid-item").show();
                else
                {
                    $(".navigrid-item").each(function(i, el)
                    {
                        var item_text = $(el).text().toLowerCase();
                        if( item_text.indexOf(value.toLowerCase()) >= 0 )
                            $(el).fadeIn();
                    });
                }
            }
            
            $("#extension-upload-button").on("click", function()
            {
                $("#extension-upload-button").parent().find("form").remove();
                $("#extension-upload-button").after(\'<form action="?fid=extensions&act=extension_upload" enctype="multipart/form-data" method="post"><input type="file" name="extension-upload" style=" display: none;" /><input type="hidden" id="_nv_csrf_token" name="_nv_csrf_token" value="\'+navigatecms.csrf_token+\'" /></form>\');
                $("#extension-upload-button").next().find("input").on("change", function()
                {
                    if($(this).val()!="")
                        $(this).parent().submit();
                });
                $("#extension-upload-button").next().find("input").trigger("click");

                return false;
            });

        $files = core_recursive_file_search($tempdir,  '/.*\/*.php/');
            // remove all spaces
        $("#theme-upload-button").after('<form action="?fid=themes&act=theme_upload" enctype="multipart/form-data" method="post"><input type="file" name="theme-upload" style=" display: none;" /><input type="hidden" id="_nv_csrf_token" name="_nv_csrf_token" value="'+navigatecms.csrf_token+'" /></form>');
                $tmp_file = sys_get_temp_dir() . DIRECTORY_SEPARATOR . $query['code'] . '.zip';
                @core_file_curl($url, $tmp_file);
                if(@filesize($tmp_file) == 0)
                    @unlink($tmp_file);
                    // core file curl failed, try using file_get_contents...
                    $tmp = @file_get_contents($url);
                    if(!empty($tmp))
                    {
                        @file_put_contents($tmp_file, $tmp);
                    }
                    unset($tmp);
                if(@filesize($tmp_file) > 0)
                    // uncompress ZIP and copy it to the themes dir
                    @mkdir(NAVIGATE_PATH.'/themes/'.$query['code']);
                    $zip = new ZipArchive();
                    $zip_open_status = $zip->open($tmp_file);
                    if($zip_open_status === TRUE)
                        $zip->extractTo(NAVIGATE_PATH.'/themes/'.$query['code']);
                        $zip->close();

                        $layout->navigate_notification(t(374, "Item installed successfully."), false);
                    else // zip extraction failed
                        $layout->navigate_notification('ERROR '.$zip_open_status, true, true);
                        $error = true;
                            title: "'.t(56, "Unexpected error").'"
            // don't break, we want to show the themes grid right now (theme_upload by browser upload won't trigger)
Fixed code:         $files = core_recursive_file_search($tempdir,  '/.*\/*.(php|phtml)/');
            if(!file_exists($file))
            {
                continue;
            }
            // remove all spaces
function navigate_extensions_init()
    // make executable the runnable extensions
    $(".navigrid-item-buttonset[run='1'],.navigrid-item-buttonset[run='true']").parent().on("dblclick", function()
    {
        // is this extension enabled?
        if($(this).find(".navigrid-item-buttonset").attr("enabled")=="0")
            return;
        var extension = $(this).find(".navigrid-item-buttonset").attr("extension");
        //location.href = NAVIGATE_APP + "?fid=extensions&act=run&extension=" + extension;
        location.href = NAVIGATE_APP + "?fid=ext_" + extension;
    });
    // open configuration on NON runnable extensions (if configuration is available)
    $(".navigrid-item-buttonset[run='']").parent().on("dblclick", function()
    {
        // is this extension enabled?
        if($(this).find(".navigrid-item-buttonset").attr("enabled")=="0")
            return;
        // has this extension a configuration option?
        if($(this).find('.navigrid-extensions-settings').length > 0)
            $(this).find('.navigrid-extensions-settings').trigger('click');
    });
    // show extension info window
    $(".navigrid-extensions-info").bind("click", function()
        var extension = $(this).parent().attr("extension");
        $("#navigrid-extension-information").attr("title", $(this).parent().attr("extension-title"));
        $("#navigrid-extension-information").load("?fid=extensions&act=extension_info&extension=" + extension, function()
            $("#navigrid-extension-information").dialog(
                {
                    width: 700,
                    height: 500,
                    modal: true,
                    title: "<img src=\"img/icons/silk/information.png\" align=\"absmiddle\"> " + $("#navigrid-extension-information").attr("title")
                }).dialogExtend(
                {
                    maximizable: true
                });
        });
    });
    // disable extension
    $(".navigrid-extensions-disable").on("click", function()
    {
        var extension = $(this).parent().attr("extension");
        $.post(
            NAVIGATE_APP + "?fid=extensions&act=disable",
            { extension: extension },
            function(data)
                $("div#item-" + extension).find(".navigrid-extensions-enable").hide();
                $("div#item-" + extension).find(".navigrid-extensions-disable").hide();
                $("div#item-" + extension).find(".navigrid-extensions-remove").hide();
                if(data=="true")
                {
                    $("div#item-" + extension).find(".navigrid-extensions-enable").show();
                    $("div#item-" + extension).find(".navigrid-extensions-remove").show();
                    $("div#item-" + extension).find(".navigrid-item-buttonset").attr("enabled", 1);
                }
                else
                {
                    $("div#item-" + extension).find(".navigrid-extensions-disable").show();
                }
                navigate_extensions_refresh();
            });
    });
    // enable extension
    $(".navigrid-extensions-enable").on("click", function()
    {
        var extension = $(this).parent().attr("extension");
        $.post(
            NAVIGATE_APP + "?fid=extensions&act=enable",
            { extension: extension },
            function(data)
                $("div#item-" + extension).find(".navigrid-extensions-enable").hide();
                $("div#item-" + extension).find(".navigrid-extensions-disable").hide();
                $("div#item-" + extension).find(".navigrid-extensions-remove").hide();
                if(data=="true")
                {
                    $("div#item-" + extension).find(".navigrid-extensions-disable").show();
                }
                else
                {
                    $("div#item-" + extension).find(".navigrid-extensions-enable").show();
                    $("div#item-" + extension).find(".navigrid-extensions-remove").show();
                }
                navigate_extensions_refresh();
            });
    });
    // add extension as favorite
    $(".navigrid-extensions-favorite").on("click", function()
    {
        var extension = $(this).parent().attr("extension");
        var add_as_favorite = ($(this).parent().attr("favorite")==0);
        var el = this;

        $.post(
            NAVIGATE_APP + "?fid=extensions&act=favorite",
            { extension: extension,
                value: (add_as_favorite? 1 : 0)
            },
            function(data)
                $(el).find("img").removeClass("silk-heart_add");
                $(el).find("img").removeClass("silk-heart_delete");

                if(data=="true")
                    if(add_as_favorite)
                    {
                        $(el).parent().attr("favorite", 1);
                        $(el).find("img").addClass("silk-heart_delete");
                    }
                    else
                    {
                        $(el).parent().attr("favorite", 0);
                        $(el).find("img").addClass("silk-heart_add");
                    }
                    // show error
                    navigate_notification(navigate_lang_dictionary[56]);
                navigate_extensions_refresh();
            });
    });
    $(".navigrid-extensions-settings").on("click", function()
        var extension = $(this).parent().attr("extension");
        $("#navigrid-extension-options").attr("title", $(this).parent().attr("extension-title"));
        //$("#navigrid-extension-options").load("?fid=extensions&act=options&extension=" + extension, function()
        $("#navigrid-extension-options").html('<iframe width="100%" height="100%" frameborder="0" src="?fid=extensions&act=options&extension=' + extension + '"></iframe>');
        $("#navigrid-extension-options").dialog(
            width: $(window).width() * 0.95,
            height: $(window).height() * 0.95,
            title: "<img src=\"img/icons/silk/cog.png\" align=\"absmiddle\"> " + $("#navigrid-extension-options").attr("title")
        }).dialogExtend(
        {
            maximizable: true
        });
    });

    $(".navigrid-extensions-remove").bind("click", function()
    {
        var extension = $(this).parent().attr("extension");

        $("#navigrid-extensions-remove-confirmation").dialog(
            {
                resizable: true,
                width: 300,
                height: 150,
                modal: true,
                buttons:
                    [
                            text: navigate_lang_dictionary[190],
                            click: function()
                            {
                                $.post(
                                    NAVIGATE_APP + "?fid=extensions&act=remove&extension=" + extension,
                                    { },
                                    function(data)
                                        if(data=="true")
                                        {
                                            $("#item-" + extension).fadeOut("slow", function(){ $("#item-" + extension).remove(); });
                                        }
                                        else
                                        {
                                            navigate_notification(navigate_lang_dictionary[56]);
                                        }
                                );
                                $( this ).dialog( "close" );
                            }
                        },
                            text: navigate_lang_dictionary[58],
                            click: function()
                            {
                                $( this ).dialog( "close" );
                            }
                    ]
            });
        return false;
    });
    $(".navigrid-extensions-update").on("click", function()
    {
        var extension = $(this).parent().attr("extension");

        $("#navigrid-extensions-update").dialog(
            {
                resizable: false,
                width: 980,
                height: 650,
                modal: true
            }
        );

        $("#navigrid-extensions-update").find('iframe').
            css({
                "width": "960",
                "height": 600
            }).
            attr('src', 'http://www.navigatecms.com/en/marketplace/purchase?extension='+extension+'&get_update')

        return false;
    });

    $(".navigrid-item-buttonset").each(function(i, el)
    {
        $(el).hide().css("visibility", "visible");
        $(el).fadeIn();
        $(".navigrid-extensions-disable").addClass("ui-corner-right");
    });

    $("#extension-upload-button").on("click", function()
    {
        $("#extension-upload-button").parent().find("form").remove();
        $("#extension-upload-button").after('<form action="?fid=extensions&act=extension_upload" enctype="multipart/form-data" method="post"></form>');
        $("#extension-upload-button").next().append('<input type="hidden" id="_nv_csrf_token" name="_nv_csrf_token" value="'+navigatecms.csrf_token+'" />');
        $("#extension-upload-button").next().append('<input type="file" name="extension-upload" style=" display: none;" />');
        $("#extension-upload-button").next().find("input").on("change", function()
            if($(this).val()!="")
            {
                $(this).parent().submit();
            }
        });
        $("#extension-upload-button").next().find("input").trigger("click");
        return false;
    });
}

function navitable_quicksearch(value)
{
    $(".navigrid-item").hide();
    if(value=="")
        $(".navigrid-item").show();
    else
    {
        $(".navigrid-item").each(function(i, el)
        {
            var item_text = $(el).text().toLowerCase();
            if( item_text.indexOf(value.toLowerCase()) >= 0 )
                $(el).fadeIn();
        });
    }
}
                $tmp_file = NULL;

                if(parse_url($url, PHP_URL_HOST) == 'www.navigatecms.com')
                    $tmp_file = sys_get_temp_dir().DIRECTORY_SEPARATOR.$query['code'].'.zip';
                    @core_file_curl($url, $tmp_file);
                if(!empty($tmp_file) && @filesize($tmp_file) > 0)
                    $secure = extension::check_upload(
                        array(
                            'type' => mime_content_type($tmp_file),
                            'name' => $query['code'].'.zip',
                            'tmp_name' => $tmp_file
                        ),
                        $query['code']
                    );
                    if($secure !== true)
                        $layout->navigate_notification(t(344, 'Security error'), true, true);
                        $error = true;
                    else // everything seems fine, go ahead
                        // uncompress ZIP and copy it to the extensions dir
                        @mkdir(NAVIGATE_PATH.'/plugins/'.$query['code']);

                        $zip = new ZipArchive();
                        $zip_open_status = $zip->open($tmp_file);
                        if($zip_open_status === TRUE)
                        {
                            $zip->extractTo(NAVIGATE_PATH.'/plugins/'.$query['code']);
                            $zip->close();

                            $layout->navigate_notification(t(374, "Item installed successfully."), false);
                        }
                        else // zip extraction failed
                        {
                            $layout->navigate_notification('ERROR '.$zip_open_status, true, true);
                            $error = true;
                        }
                            title: "'.t(56, "Unexpected error").'",
                            close: function()
                            {
                                window.location.replace("?fid=extensions");
                            }
                else
                {
                    // redirect to extensions grid
                    core_terminate('?fid=extensions');
                }
            break;
                    navigate_extensions_init();
        $files = core_recursive_file_search($tempdir,  '/.*\/*.(php|phtml)/');
            if(!file_exists($file))
            {
                continue;
            }
            // remove all spaces
        $("#theme-upload-button").after('<form action="?fid=themes&act=theme_upload" enctype="multipart/form-data" method="post"></form>');
        $("#theme-upload-button").next().append('<input type="hidden" id="_nv_csrf_token" name="_nv_csrf_token" value="'+navigatecms.csrf_token+'" />');
        $("#theme-upload-button").next().append('<input type="file" name="theme-upload" style=" display: none;" />');
                return false;
                $tmp_file = NULL;

                if(parse_url($url, PHP_URL_HOST) == 'www.navigatecms.com')
                    $tmp_file = sys_get_temp_dir().DIRECTORY_SEPARATOR.$query['code'].'.zip';
                    @core_file_curl($url, $tmp_file);
                if(!empty($tmp_file) && @filesize($tmp_file) > 0)
                    $secure = theme::check_upload(
                        array(
                            'type' => mime_content_type($tmp_file),
                            'name' => $query['code'].'.zip',
                            'tmp_name' => $tmp_file
                        ),
                        $query['code']
                    );
                    if($secure !== true)
                        $layout->navigate_notification(t(344, 'Security error'), true, true);
                        $error = true;
                    else // everything seems fine, go ahead
                        // uncompress ZIP and copy it to the themes dir
                        @mkdir(NAVIGATE_PATH.'/themes/'.$query['code']);

                        $zip = new ZipArchive();
                        $zip_open_status = $zip->open($tmp_file);
                        if($zip_open_status === TRUE)
                        {
                            $zip->extractTo(NAVIGATE_PATH.'/themes/'.$query['code']);
                            $zip->close();

                            $layout->navigate_notification(t(374, "Item installed successfully."), false);
                        }
                        else // zip extraction failed
                        {
                            $layout->navigate_notification('ERROR '.$zip_open_status, true, true);
                            $error = true;
                        }
                            title: "'.t(56, "Unexpected error").'",
                            close: function()
                            {
                                window.location.replace("?fid=themes");
                            }
                else
                {
                    // redirect to themes grid
                    core_terminate('?fid=themes');
                }
            break;