From 28de3911825bde79ee5a92762940ef310baab737 Mon Sep 17 00:00:00 2001
From: Thomas Bruederli <thomas@roundcube.net>
Date: Tue, 06 Nov 2012 07:21:04 -0500
Subject: [PATCH] Recursively resolve paths of iframe contents; unify contentframe registration and reduce code-duplication

---
 program/steps/settings/identities.inc |    6 --
 plugins/help/help.php                 |    3 -
 program/include/rcube_output_html.php |   70 ++++++++++++++++++++++++----------
 program/steps/settings/folders.inc    |    7 ---
 program/steps/addressbook/func.inc    |    7 ---
 program/steps/mail/func.inc           |    2 
 program/steps/settings/func.inc       |    7 ---
 7 files changed, 55 insertions(+), 47 deletions(-)

diff --git a/plugins/help/help.php b/plugins/help/help.php
index 1a76cbb..4b11dce 100644
--- a/plugins/help/help.php
+++ b/plugins/help/help.php
@@ -90,8 +90,7 @@
 
         $attrib['name'] = $attrib['id'];
 
-        return html::tag('iframe', $attrib, '', array(
-            'id', 'class', 'style', 'src', 'width', 'height', 'frameborder'));
+        return $rcmail->output->frame($attrib);
     }
 
 }
diff --git a/program/include/rcube_output_html.php b/program/include/rcube_output_html.php
index 71aec77..a372264 100644
--- a/program/include/rcube_output_html.php
+++ b/program/include/rcube_output_html.php
@@ -206,6 +206,31 @@
 
 
     /**
+     * Find the given file in the current skin path stack
+     *
+     * @param string File name/path to resolve (starting with /)
+     * @param string Reference to the base path of the matching skin
+     * @param string Additional path to search in
+     * @return mixed Relative path to the requested file or False if not found
+     */
+    public function get_skin_file($file, &$skin_path, $add_path = null)
+    {
+        $skin_paths = $this->skin_paths;
+        if ($add_path)
+            array_unshift($skin_paths, $add_path);
+
+        foreach ($skin_paths as $skin_path) {
+            $path = realpath($skin_path . $file);
+            if (is_file($path)) {
+                return $skin_path . $file;
+            }
+        }
+
+        return false;
+    }
+
+
+    /**
      * Register a GUI object to the client script
      *
      * @param  string Object name
@@ -401,13 +426,13 @@
             // apply skin search escalation list to plugin directory
             $plugin_skin_paths = array();
             foreach ($this->skin_paths as $skin_path) {
-                $plugin_skin_paths[] = $this->app->plugins->dir . $plugin . '/' . $skin_path;
+                $plugin_skin_paths[] = $this->app->plugins->url . $plugin . '/' . $skin_path;
             }
 
             // add fallback to default skin
             if (is_dir($this->app->plugins->dir . $plugin . '/skins/default')) {
                 $skin_dir = $plugin . '/skins/default';
-                $plugin_skin_paths[] = $this->app->plugins->dir . $skin_dir;
+                $plugin_skin_paths[] = $this->app->plugins->url . $skin_dir;
             }
 
             // add plugin skin paths to search list
@@ -536,12 +561,17 @@
      * Make URLs starting with a slash point to skin directory
      *
      * @param  string Input string
+     * @param  boolean True if URL should be resolved using the current skin path stack
      * @return string
      */
-    public function abs_url($str)
+    public function abs_url($str, $search_path = false)
     {
-        if ($str[0] == '/')
+        if ($str[0] == '/') {
+            if ($search_path && ($file_url = $this->get_skin_file($str, $skin_path)))
+                return $file_url;
+
             return $this->base_path . $str;
+        }
         else
             return $str;
     }
@@ -825,15 +855,9 @@
             // include a file
             case 'include':
                 $old_base_path = $this->base_path;
-                $skin_paths = $this->skin_paths;
-                if ($attrib['skin_path'])
-                    array_unshift($skin_paths, $attrib['skin_path']);
-                foreach ($skin_paths as $skin_path) {
-                    $path = realpath($skin_path . $attrib['file']);
-                    if (is_file($path)) {
-                        $this->base_path = $skin_path;
-                        break;
-                    }
+                if ($path = $this->get_skin_file($attrib['file'], $skin_path, $attrib['skin_path'])) {
+                    $this->base_path = $skin_path;
+                    $path = realpath($path);
                 }
 
                 if (is_readable($path)) {
@@ -1350,21 +1374,25 @@
      * Returns iframe object, registers some related env variables
      *
      * @param array $attrib HTML attributes
-     *
+     * @param boolean $is_contentframe Register this iframe as the 'contentframe' gui object
      * @return string IFRAME element
      */
-    public function frame($attrib)
+    public function frame($attrib, $is_contentframe = false)
     {
+        static $idcount = 0;
+
         if (!$attrib['id']) {
-            $attrib['id'] = 'rcmframe';
+            $attrib['id'] = 'rcmframe' . ++$idcount;
         }
 
-        if (!$attrib['name']) {
-            $attrib['name'] = $attrib['id'];
-        }
+        $attrib['name'] = $attrib['id'];
+        $attrib['src'] = $attrib['src'] ? $this->abs_url($attrib['src'], true) : 'program/resources/blank.gif';
 
-        $this->set_env('contentframe', $attrib['id']);
-        $this->set_env('blankpage', $attrib['src'] ? $this->abs_url($attrib['src']) : 'program/resources/blank.gif');
+        // register as 'contentframe' object
+        if ($is_contentframe)
+            $this->set_env('contentframe', $attrib['name']);
+            $this->set_env('blankpage', $attrib['src']);
+        }
 
         return html::iframe($attrib);
     }
diff --git a/program/steps/addressbook/func.inc b/program/steps/addressbook/func.inc
index 3a05080..cefe49e 100644
--- a/program/steps/addressbook/func.inc
+++ b/program/steps/addressbook/func.inc
@@ -367,12 +367,7 @@
     if (!$attrib['id'])
         $attrib['id'] = 'rcmcontactframe';
 
-    $attrib['name'] = $attrib['id'];
-
-    $OUTPUT->set_env('contentframe', $attrib['name']);
-    $OUTPUT->set_env('blankpage', $attrib['src'] ? $OUTPUT->abs_url($attrib['src']) : 'program/resources/blank.gif');
-
-    return html::iframe($attrib);
+    return $OUTPUT->frame($attrib, true);
 }
 
 
diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc
index 47d1a48..9ad3a6e 100644
--- a/program/steps/mail/func.inc
+++ b/program/steps/mail/func.inc
@@ -471,7 +471,7 @@
     $OUTPUT->set_env('contentframe', $attrib['id']);
   $OUTPUT->set_env('blankpage', $attrib['src'] ? $OUTPUT->abs_url($attrib['src']) : 'program/resources/blank.gif');
 
-  return html::iframe($attrib);
+  return $OUTPUT->frame($attrib, true);
 }
 
 
diff --git a/program/steps/settings/folders.inc b/program/steps/settings/folders.inc
index 12e449e..0c7d906 100644
--- a/program/steps/settings/folders.inc
+++ b/program/steps/settings/folders.inc
@@ -369,12 +369,7 @@
     if (!$attrib['id'])
         $attrib['id'] = 'rcmfolderframe';
 
-    $attrib['name'] = $attrib['id'];
-
-    $OUTPUT->set_env('contentframe', $attrib['name']);
-    $OUTPUT->set_env('blankpage', $attrib['src'] ? $OUTPUT->abs_url($attrib['src']) : 'program/resources/blank.gif');
-
-    return html::iframe($attrib);
+    return $OUTPUT->frame($attrib, true);
 }
 
 function rcmail_rename_folder($oldname, $newname)
diff --git a/program/steps/settings/func.inc b/program/steps/settings/func.inc
index d5ccbb2..8bef2ff 100644
--- a/program/steps/settings/func.inc
+++ b/program/steps/settings/func.inc
@@ -31,12 +31,7 @@
   if (!$attrib['id'])
     $attrib['id'] = 'rcmprefsframe';
 
-  $attrib['name'] = $attrib['id'];
-
-  $OUTPUT->set_env('contentframe', $attrib['name']);
-  $OUTPUT->set_env('blankpage', $attrib['src'] ? $OUTPUT->abs_url($attrib['src']) : 'program/resources/blank.gif');
-
-  return html::iframe($attrib);
+  return $OUTPUT->frame($attrib, true);
 }
 
 
diff --git a/program/steps/settings/identities.inc b/program/steps/settings/identities.inc
index 26bd432..82a1841 100644
--- a/program/steps/settings/identities.inc
+++ b/program/steps/settings/identities.inc
@@ -33,11 +33,7 @@
   if (!$attrib['id'])
     $attrib['id'] = 'rcmIdentityFrame';
 
-  $attrib['name'] = $attrib['id'];
-
-  $OUTPUT->set_env('contentframe', $attrib['name']);
-
-  return html::iframe($attrib);
+  return $OUTPUT->frame($attrib, true);
   }
 
 $OUTPUT->add_handler('identityframe', 'rcmail_identity_frame');

--
Gitblit v1.9.1