CVE-2020-14067 (published 2020-06-15T01:15Z)

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.

Severity: HIGH
CVSS v2 base score: 7.5 (AV:N/AC:L/Au:N/C:P/I:P/A:P)
CVSS v3 base score: 9.8, CRITICAL (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-434
cwe_name: Unrestricted Upload of File with Dangerous Type
description: The product allows the upload or transfer of dangerous file types that are automatically processed within its environment.
extended_description: 
            
            
            
            
            
         
         

Fix information:
repo_url: https://github.com/NavigateCMS/Navigate-CMS
commit_details: repo_url: https://github.com/NavigateCMS/Navigate-CMS
author: NavigateCMS
author_date: 2020-06-11 12:20:32+02:00
msg: * themes,extensions: secure "install_from_hash" functionality
repository: repo_url: https://github.com/NavigateCMS/Navigate-CMS
repo_name: NavigateCMS/Navigate-CMS
description: Navigate CMS, a very powerful open source content management system for everybody.
repo_language: PHP
owner: NavigateCMS
file_changes: filename: extension.class.php
change_type: ModificationType.MODIFY
diff: @@ -551,7 +551,7 @@ class extension
         }
 
         // check every php file included
-        $files = core_recursive_file_search($tempdir,  '/.*\/*.php/');
+        $files = core_recursive_file_search($tempdir,  '/.*\/*.(php|phtml)/');
 
         $prohibited_functions = array(
             'eval(',
@@ -566,8 +566,12 @@ class extension
 
         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)

programming_language: PHP
filename: extensions.js
change_type: ModificationType.MODIFY
diff: @@ -1,231 +1,277 @@
-// 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()
 {

programming_language: JavaScript
filename: extensions.php
change_type: ModificationType.MODIFY
diff: @@ -158,40 +158,51 @@ function run()
             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
@@ -213,13 +224,21 @@ function run()
                     $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())
@@ -393,51 +412,10 @@ function extensions_grid($list)
                 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

programming_language: PHP
filename: theme.class.php
change_type: ModificationType.MODIFY
diff: @@ -552,7 +552,7 @@ class theme
         }
 
         // check every php file included
-        $files = core_recursive_file_search($tempdir,  '/.*\/*.php/');
+        $files = core_recursive_file_search($tempdir,  '/.*\/*.(php|phtml)/');
 
         $prohibited_functions = array(
             'eval(',
@@ -567,8 +567,12 @@ class theme
 
         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)

programming_language: PHP
filename: themes.js
change_type: ModificationType.MODIFY
diff: @@ -110,12 +110,15 @@ function navigate_themes_init()
         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");

programming_language: JavaScript
filename: themes.php
change_type: ModificationType.MODIFY
diff: @@ -114,40 +114,51 @@ function run()
             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
@@ -169,12 +180,21 @@ function run()
                     $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())

programming_language: PHP