linterna-magica-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[linterna-magica-commit] [157] Merging branch task-11216 back into trunk


From: Ivaylo Valkov
Subject: [linterna-magica-commit] [157] Merging branch task-11216 back into trunk
Date: Tue, 26 Jul 2011 08:02:55 +0000

Revision: 157
          
http://svn.sv.gnu.org/viewvc/?view=rev&root=linterna-magica&revision=157
Author:   valkov
Date:     2011-07-26 08:02:40 +0000 (Tue, 26 Jul 2011)
Log Message:
-----------
Merging branch task-11216 back into trunk

Modified Paths:
--------------
    trunk/HELP
    trunk/HELP.bg
    trunk/Makefile
    trunk/WEBSITES
    trunk/src/lm_about.js
    trunk/src/lm_config_options.js
    trunk/src/lm_constructors.js
    trunk/src/lm_cookies.js
    trunk/src/lm_create_video_object.js
    trunk/src/lm_detect_flash.js
    trunk/src/lm_extract_dom_objects.js
    trunk/src/lm_extract_js_scripts.js
    trunk/src/lm_extract_js_swfobject.js
    trunk/src/lm_extract_video_link.js
    trunk/src/lm_init_options.js
    trunk/src/lm_remove_plugin_install_warning.js
    trunk/src/lm_site_bliptv.js
    trunk/src/lm_site_dailymotion.js
    trunk/src/lm_site_facebook.js
    trunk/src/lm_site_myvideode.js
    trunk/src/lm_site_tedcom.js
    trunk/src/lm_site_theonion.js
    trunk/src/lm_site_vimeo.js
    trunk/src/lm_site_youtube.js
    trunk/src/lm_xhr.js
    trunk/utilities/linternamagica_user_config.user.js

Added Paths:
-----------
    trunk/src/lm_site_boozhocom.js
    trunk/src/lm_site_clipovetecom.js
    trunk/src/lm_site_google_video.js
    trunk/src/lm_site_jwaknet.js
    trunk/src/lm_site_metacafe.js
    trunk/src/lm_site_mqstocom.js
    trunk/src/lm_site_reuters.js
    trunk/src/lm_site_tv7bg.js
    trunk/src/lm_site_vbox7com.js
    trunk/src/lm_site_videoclipsdumpcom.js
    trunk/src/lm_sites.js

Property Changed:
----------------
    trunk/


Property changes on: trunk
___________________________________________________________________
Modified: svn:mergeinfo
   - /branches/0.0.9:94
   + /branches/0.0.9:94
/branches/task-11216:102-156

Modified: trunk/HELP
===================================================================
--- trunk/HELP  2011-07-26 07:55:44 UTC (rev 156)
+++ trunk/HELP  2011-07-26 08:02:40 UTC (rev 157)
@@ -16,7 +16,7 @@
     "controls": "self",
     "locale": "auto",
     "cookies": "restore",
-    "wait_dm": "off",
+    "wait_xhr": "off",
     "quality": "low",
  };
 
@@ -95,8 +95,8 @@
            Just delete the cookies.
         restore
            Extract and restore cookies.
-  wait_dm
-      Timeout before background processing starts in Dailymotion in
+  wait_xhr
+      Timeout before background processing (XHR) starts in
       milliseconds. 1 s = 1000 ms. If you have problems increase the
       value.
         off/no/disabled/false/0
@@ -137,13 +137,16 @@
 automatically set new values to some of the cookies with the
 background request. 
 
-For Dailymotion there is a timeout option. During the first tests of
-this fix there were some problems if the background request was made
-too soon. It seemed that not all cookies were set by the site and
-cleared by Linterna Mágica before the request. Later everything worked
-without timeout. If you have problems with Dailymotion increase the
-value for the "wait_dm" option.
+For Dailymotion you could use a timeout option. During the first
+tests of this fix there were some problems if the background request
+was made too soon. It seemed that not all cookies were set by the site
+and cleared by Linterna Mágica before the request. Later everything
+worked without timeout. If you have problems with Dailymotion increase
+the value for the "wait_xhr" option. 
 
+The wait_xhr option is effective for every site that is supported with
+background requests.
+
 Localisation
 
 Since version 0.0.10 the translations are split from the main

Modified: trunk/HELP.bg
===================================================================
--- trunk/HELP.bg       2011-07-26 07:55:44 UTC (rev 156)
+++ trunk/HELP.bg       2011-07-26 08:02:40 UTC (rev 157)
@@ -15,7 +15,7 @@
     "controls": "self",
     "locale": "auto",
     "cookies": "restore",
-    "wait_dm": "off",
+    "wait_xhr": "off",
     "quality": "low",
  };
 
@@ -96,9 +96,9 @@
            Бисквитките ще бъдат изтрити.
         restore
            Извличане и възстановяване на бисквитки.
-  wait_dm
-      Време за изчакване преди да започне обработката на заден план за
-      Dailymotion в милисекунди. 1 s = 1000 ms. В случай на проблеми
+  wait_xhr
+      Време за изчакване преди да започне обработката на заден план
+      (XHR) в милисекунди. 1 s = 1000 ms. В случай на проблеми
       увеличете стойността.
         off/no/disabled/false/0
            Да не се изчаква (стандартно)
@@ -148,8 +148,11 @@
 от страницата не се записваха всички бисквитки и съответно не се
 изчистваха от Linterna Mágica преди заявката. По-късно решението
 работеше без изчакване. Ако имате проблеми с Dailymotion, увеличете
-стойността на "wait_dm".
+стойността на "wait_xhr".
 
+Настройката wait_xhr важи за всяка страница, която се поддържа чрез
+заявки на заден план.
+
 Превод на интерфейса
 
 От версия 0.0.10 нататък преводите са разделени от основния

Modified: trunk/Makefile
===================================================================
--- trunk/Makefile      2011-07-26 07:55:44 UTC (rev 156)
+++ trunk/Makefile      2011-07-26 08:02:40 UTC (rev 157)
@@ -54,7 +54,7 @@
 
 FIRSTJSFILES="$(srcdir)/lm_inject_script_in_page.js            \
 $(srcdir)/lm_init_options.js $(srcdir)/lm_constructors.js      \
-$(srcdir)/lm_config_options.js"
+$(srcdir)/lm_config_options.js $(srcdir)/lm_sites.js"
 
 LASTJSFILES="$(srcdir)/lm_run.js"
 

Modified: trunk/WEBSITES
===================================================================
--- trunk/WEBSITES      2011-07-26 07:55:44 UTC (rev 156)
+++ trunk/WEBSITES      2011-07-26 08:02:40 UTC (rev 157)
@@ -25,10 +25,6 @@
     - It seems metacafe changes some things often. You might
     experience some trouble.
 http://www.4videosharing.com
-    - Seems their account is disabled by their hosting provider.
-http://www.vidoemo.com
-    - Seems it is disabled and redirects to random sites with sex
-      content.
 http://www.videoclipsdump.com 
     - Support re-written in 0.0.9. Everything seems to be working. 
 http://www.boomclips.com
@@ -87,13 +83,13 @@
 http://jwak.net
 http://failo.bg
     - Hosting account suspended
-http://www.mediashare.bg
-    - Does not exist anymore.
-    - Only clips hosted at the site worked.
 http://www.arenamedia.net
 http://www.screen.bg
 http://www.crazy.bg
 http://www.friends.bg
+    - Only front page and logo are displayed.
+    - Site specific code support dropped in r141 (branch task-11216)
+      after framework changes.
 http://www.vboxbg.net/
 
 Web sites that use one of the following JavaScript libraries to create

Modified: trunk/src/lm_about.js
===================================================================
--- trunk/src/lm_about.js       2011-07-26 07:55:44 UTC (rev 156)
+++ trunk/src/lm_about.js       2011-07-26 08:02:40 UTC (rev 157)
@@ -131,13 +131,6 @@
     p.appendChild(microblog_link);
     box.appendChild(p);
 
-    // We want this for small objects. Scroll bars will be visible and
-    // license and home page links accessible.
-    if (!/youtube\.com/i.test(window.location.hostname))
-    {
-       box.style.setProperty("overflow", "auto", "important");
-    }
-
     return box;
 }
 

Modified: trunk/src/lm_config_options.js
===================================================================
--- trunk/src/lm_config_options.js      2011-07-26 07:55:44 UTC (rev 156)
+++ trunk/src/lm_config_options.js      2011-07-26 08:02:40 UTC (rev 157)
@@ -132,7 +132,7 @@
 
 // Set the timeout for Dailymotion. After this timeout background
 // processing starts
-LinternaMagica.prototype.set_wait_dailymotion = function(wait)
+LinternaMagica.prototype.set_wait_xhr = function(wait)
 {
     var set_wait_to = wait ? wait :"";
 
@@ -156,7 +156,12 @@
        set_wait_to = 0;
     }
 
-    this.wait_dailymotion = set_wait_to;
+    if (/[0-9]+/i.test(wait))
+    {
+       set_wait_to = parseInt(wait);
+    }
+
+    this.wait_xhr = set_wait_to;
 }
 
 // Set updates 

Modified: trunk/src/lm_constructors.js
===================================================================
--- trunk/src/lm_constructors.js        2011-07-26 07:55:44 UTC (rev 156)
+++ trunk/src/lm_constructors.js        2011-07-26 08:02:40 UTC (rev 157)
@@ -81,15 +81,12 @@
        this.log_to = "console";
     }
 
-    // Skip ted.com at the front page. With Gnash installed the flash
-    // object is created. The flashvars attrubute value is 24 KB
-    // (kilo*bytes*) and Firefox and forks block 
-    if (/ted\.com/i.test(window.location.hostname) &&
-       !/[A-Za-z0-9]+/i.test(window.location.pathname))
-    {  
-       this.log("LinternaMagica.constructor:\n"+
-                "Skipping TED front page!"+
-                " Blocks Firefox and forks.");
+    var self = this;
+    var val = this.call_site_function_at_position.apply(self,[
+       "before_options_init",
+       window.location.hostname]);
+    if (!val)
+    {
        return null;
     }
 
@@ -99,7 +96,7 @@
     this.set_autostart(params.autostart);
     this.set_controls(params.controls);
     this.set_cookies(params.cookies);
-    this.set_wait_dailymotion(params.wait_dm);
+    this.set_wait_xhr(params.wait_xhr);
     this.set_check_updates(params.updates);
     this.set_hd_link_quality(params.quality);
 
@@ -127,21 +124,24 @@
        this.player_timers = new Array();
     }
 
-    if (!this.plugin_is_installed &&
-       /dailymotion\.com/i.test(window.location.hostname))
+    var position_function = null ;
+    if (this.plugin_is_installed)
     {
-       this.request_video_link({video_id: window.location.pathname});
+       position_function = "flash_plugin_installed";
     }
-    // If there is a plugin installed do not search in scripts.
-    else if (!this.plugin_is_installed ||
-            /myvideo\.de/i.test(window.location.hostname) ||
-            /theonion\.com/i.test(window.location.hostname))
+    else
     {
-       this.log("LinternaMagica.constructor:\n"+
-                "Examining scripts.", 4);
+       position_function = "no_flash_plugin_installed";
+    }
 
-       // video.google.* bloats in this function. It takes around 1 min
-       this.extract_objects_from_scripts();
+    var self = this;
+    var val = this.call_site_function_at_position.apply(self,[
+       position_function,
+       window.location.hostname]);
+    
+    if (!val)
+    {
+       return null;
     }
 
     this.log("LinternaMagica.constructor:\n"+

Modified: trunk/src/lm_cookies.js
===================================================================
--- trunk/src/lm_cookies.js     2011-07-26 07:55:44 UTC (rev 156)
+++ trunk/src/lm_cookies.js     2011-07-26 08:02:40 UTC (rev 157)
@@ -49,26 +49,56 @@
     var past_date = new  Date(1983, 9, 27);
     var domain = window.location.hostname;
 
-    if (/youtube\.com/i.test(window.location.hostname))
+    var self = this;
+    var val = this.call_site_function_at_position.apply(self,[
+       "set_cookies_domain",
+       window.location.hostname]);
+
+    if (!val)
     {
-       domain = ".youtube.com";
+       return null;
     }
+    else if (typeof(val) == "string")
+    {
+       // See YouTube support.
+       domain = val;
+    }
 
-    for (var i=0; i<cookies.length; i++)
+    for (var i=0, l=cookies.length; i<l; i++)
     {
-       // Host is used in dailymotion. It is not documented anywhere
-       document.cookie = cookies[i]+
-           (expire ? "; expires="+past_date.toUTCString(): "")+
-           "; domain="+domain+"; path=/; host="+domain+"; ";
+        var val = this.call_site_function_at_position.apply(self,[
+            "process_cookies",
+            window.location.hostname]);
 
-       // Dailymotion uses www.dailymotion.com and .dailymotion.com
-       if (/dailymotion\.com/i.test(window.location.hostname))
+       try 
        {
-           // Host is used in dailymotion. It is not documented anywhere
+           if (typeof(val) == "string")
+           {
+               document.cookie = cookies[i]+
+                   (expire ? "; expires="+
+                    past_date.toUTCString(): "")+val;
+           }
+       }
+       catch(e)
+       {
+           this.log("LinternaMagica.store_cookies:\n"+
+                    "Exception while setting cookie with"+
+                    " site specific string: "+e,1);
+       }
+
+       try
+       {
+           // Host is used in dailymotion. It is not documented
+           // anywhere. It is overkill to export it.
            document.cookie = cookies[i]+
                (expire ? "; expires="+past_date.toUTCString(): "")+
-               "; domain=.dailymotion.com; path=/; host="+domain+"; ";
+               "; domain="+domain+"; path=/; host="+domain+"; ";
        }
+       catch(e)
+       {
+           this.log("LinternaMagica.store_cookies:\n"+
+                    "Exception while setting cookie: "+e,1);
+       }
     }
 }
 

Modified: trunk/src/lm_create_video_object.js
===================================================================
--- trunk/src/lm_create_video_object.js 2011-07-26 07:55:44 UTC (rev 156)
+++ trunk/src/lm_create_video_object.js 2011-07-26 08:02:40 UTC (rev 157)
@@ -312,14 +312,6 @@
     {
        toggle_plugin = this.create_toggle_plugin_link(this.priority, id);
 
-       // Fix displacement of toggle_plugin link/button in vimeo
-       if (/vimeo\.com/i.test(window.location.hostname))
-       {
-           toggle_plugin.style.setProperty("top", 
-                                           parseInt(object_data.height)+10+
-                                           "px", "important");
-       }
-
        var before = this.get_flash_video_object(id).nextSibling;
 
        if (before)
@@ -383,73 +375,27 @@
        }
     }
 
-    // Various CSS fix-ups
+    // Defaults style fixes applied always.
+    about_box.style.setProperty("overflow", "auto", "important");
+
     container.style.setProperty("height",
                                ((parseInt(object_data.height)+26+
                                  (this.controls ? 24 : 0))+"px"),
                                "important");
 
-    // In channels/user pages in YouTube the web controlls are
-    // overlapped by this element.
-    if (/youtube\.com/i.test(window.location.hostname) &&
-       document.getElementById("playnav-playview"))
-    {
-       var el =        document.getElementById("playnav-playview");
-       el.style.setProperty("margin-top", "50px", "important");
-    }
-
-    // The thumbnail image overlaps the toggle plugin button after our
-    // changes. This way our button is visible.
-    if (/vimeo\.com/i.test(window.location.hostname) && 
-       object_data.parent.firstChild)
-    {
-       // The first child should be a div with thumbnail as
-       // background. Reduce it's size so it will not overlap our
-       // button.
-       object_data.parent.firstChild.style.
-           setProperty("height", parseInt(object_data.height)+"px",
-                       "important");
-    }
-
     if (object_data.parent)
     {
-       var move_down_fb_frame = null;
-       if (/mqsto\.com/i.test(window.location.hostname))
-       {
-           // Move the facebook comment frame in mqsto.com 100px
-           // down. overlaps the player.
-           move_down_fb_frame = 100;
-       }
-
        object_data.parent.style.setProperty("height",
                                             (parseInt(object_data.height)+
-                                             26+(move_down_fb_frame ? 
-                                                 move_down_fb_frame: 0)+
+                                             26+
                                              // borders 1px x 2
                                              2+
                                              (this.controls ? 24 : 0))+"px",
                                             "important");
-
-       // Show HD links list. 
-       if (/vimeo\.com/i.test(window.location.hostname))
-       {
-           object_data.parent.style.
-               setProperty("overflow", "visible", "important");
-
-           object_data.parent.parentNode.style.
-               setProperty("overflow", "visible", "important");
-       }
-       // if (/vimeo\.com/i.test(window.location.hostname))
-       // {
-       //     // object_data.parent.parentNode.style.
-       //     //       setProperty("overflow-y", "visible", "important");
-
-       //     // Hides the HD links menu
-       //     // object_data.parent.parentNode.style.
-       //     //       setProperty("overflow-x", "hidden", "important");
-       // }
     }
 
+    
+
     var dom_object = this.get_flash_video_object(id);
     // Objects extracted from script usually does not have cloned object
     // For example youtube
@@ -458,26 +404,18 @@
        // Prevent the object to fill the container at 100% (if set)
        // This way the toggle plugin link after the object is not
        // overlaping elements.
-       dom_object.style.setProperty("height",
-                                                object_data.height+"px",
-                                                "important");
+       dom_object.style.setProperty("height", object_data.height+"px",
+                                    "important");
     }
+
     // Prevent the video object to fill the area at 100% and overlap
     // other elements. This happends if the site CSS sets this
-    object_tag.style.setProperty("height",
-                                object_data.height+"px",
+    object_tag.style.setProperty("height", object_data.height+"px",
                                 "important");
 
-    object_tag.style.setProperty("width",
-                                object_data.width+"px",
+    object_tag.style.setProperty("width", object_data.width+"px",
                                 "important");
 
-    // No idea what this fixes.
-    if (/vimeo\.com/i.test(window.location.href))
-    {
-       object_tag.style.setProperty("position","relative","important");
-    }
-
     if (this.plugin_is_installed)
     {
        // Remove backrounds so the toggle plugin link is visible
@@ -500,66 +438,6 @@
     // parent.parentNode is not an object
     if (object_data.parent && object_data.parent.parentNode)
     {
-
-       // The CSS hides parts of our elements
-       if (/tv7\.bg/i.test(window.location.hostname) ||
-           /vimeo\.com/i.test(window.location.hostname))
-       {
-           object_data.parent.parentNode.style.
-               setProperty("height",
-                           (parseInt(object_data.height)+26+
-                            // borders 1px x 2
-                            2+
-                            (this.controls ? 24 : 0)  )+"px",
-                           "important");
-
-           object_data.parent.parentNode.style.
-               setProperty("width",
-                           (parseInt(object_data.width+2))+"px",
-                           "important");
-       }
-
-       if (/tv7\.bg/i.test(window.location.hostname) ||
-           /vimeo\.com/i.test(window.location.hostname))
-       {
-           var third_parent = object_data.parent.parentNode.parentNode;
-           if (third_parent)
-           {
-               third_parent.style.setProperty("overflow", "visible", 
"important");
-               third_parent.style.
-                   setProperty("height", 
-                               (parseInt(object_data.height)+26+
-                                // borders 1px x 2
-                                2+
-                                (this.controls ? 24 : 0)  )+"px",
-                               "important");
-           }
-       }
-
-       if (/vimeo\.com/i.test(window.location.hostname) ||
-           /reuters\.com/i.test(window.location.hostname))
-       {
-           // Extra height for reuters.com. Otherwise the controlls
-           // are hidden.
-           var reuters = 
-               /reuters\.com/i.test(window.location.hostname) ? 100 : 0;
-
-           var fourth_parent = 
object_data.parent.parentNode.parentNode.parentNode;
-           if (fourth_parent)
-           {
-               fourth_parent.style.setProperty("overflow", "visible", 
"important");
-               fourth_parent.style.
-                   setProperty("height", 
-                               (parseInt(object_data.height)+26+
-                                reuters+
-                                // borders 1px x 2
-                                2+
-                                (this.controls ? 24 : 0)  )+"px",
-                               "important");
-           }
-       }
-
-
        // dailymotion.com && metacafe.com && btn.bg
        // These have single div inside another one
        // which (through height) overlaps elemenst
@@ -587,16 +465,6 @@
        }
     }
 
-    // Bug #33504 https://savannah.nongnu.org/bugs/?33504
-    if (/youtube\.com/i.test(window.location.hostname))
-    {
-       object_data.parent.style.setProperty("overflow", 
-                                            "visible", "important");
-    }
-
-    // Temporary
-    // parent.style.setProperty("border", "1px solid red", "important");
-
     // Init the web controls functions
     // only if Linterna Mágica has priority
     if (this.controls &&
@@ -608,5 +476,11 @@
     // Examine the option for updates and check if necessary.
     this.check_for_updates();
 
+    // Various CSS fixes
+    var self = this;
+    var val = this.call_site_function_at_position.apply(self,[
+       "css_fixes",
+       window.location.hostname, object_data]);
+
     return null;
 }

Modified: trunk/src/lm_detect_flash.js
===================================================================
--- trunk/src/lm_detect_flash.js        2011-07-26 07:55:44 UTC (rev 156)
+++ trunk/src/lm_detect_flash.js        2011-07-26 08:02:40 UTC (rev 157)
@@ -112,13 +112,18 @@
        }
        // Not a swf but best to detect remotely embedded clips with
        // current logic.
-       else if (element.localName.toLowerCase() == "iframe" &&
-                // Without this and if Flashblock is installed, it
-                // will replace an iframe that has something to do
-                // with tweeter. This way the Flashblock blocked
-                // object is replaced.
-                !/dailymotion\.com/i.test(window.location.hostname))
+       else if (element.localName.toLowerCase() == "iframe")
        {
+           var self = this;
+           var val = this.call_site_function_at_position.apply(self,[
+               "do_not_force_iframe_detection",
+               window.location.hostname]);
+
+           if (!val)
+           {
+               return false;
+           }
+
            is_swf = true;
            detected_via = "forced for iframe";
        }

Modified: trunk/src/lm_extract_dom_objects.js
===================================================================
--- trunk/src/lm_extract_dom_objects.js 2011-07-26 07:55:44 UTC (rev 156)
+++ trunk/src/lm_extract_dom_objects.js 2011-07-26 08:02:40 UTC (rev 157)
@@ -77,16 +77,26 @@
            || (this.is_swf_object(object)
                && !this.is_swf_object(object.parentNode)))
        {
-           if (/dailymotion\.com/i.test(window.location.hostname))
+           var extracted_data = new Object();
+
+           var self = this;
+           var val = this.call_site_function_at_position.apply(self,[
+               "skip_video_id_extraction",
+               window.location.hostname]);
+
+           if (!val)
            {
-               var extracted_data = new Object();
-               extracted_data.video_id = window.location.pathname;
+               return null;
            }
-           else
+           else if (typeof(val) == "boolean")
            {
                this.create_param_list(object);
-               var extracted_data = this.extract_link_from_param_list();
+               extracted_data = this.extract_link_from_param_list();
            }
+           else
+           {
+               extracted_data = val;
+           }
 
            object_data.remote_site_link = extracted_data.remote_site_link;
            object_data.link = extracted_data.link;
@@ -106,18 +116,21 @@
                continue;
            }
 
-           if (/myvideo\.de/i.test(window.location.hostname) &&
-               object_data.video_id)
+           if (object_data.video_id)
            {
-               // See the comments for this function
-               object_data.link = this.create_myvideode_link();
+               var self = this;
+               var val = this.call_site_function_at_position.apply(self,[
+                   "skip_xhr_if_video_id",
+                   window.location.hostname, object_data]);
 
-               // Now that we have a link remove the video_id
-               // so it is not processed
-               if (object_data.link)
+               if (!val)
                {
-                   object_data.video_id = null;
+                   return null;
                }
+               else if(typeof(val) != "boolean")
+               {
+                   object_data = val;
+               }
            }
 
            var parent = object.parentNode.localName.toLowerCase();
@@ -222,35 +235,38 @@
            }
            else if (object_data.video_id)
            {
-               this.log("LinternaMagica.extract_objects_from_dom:\n"+
-                        "Requesting video link via video_id "+
-                        object_data.video_id,1);
+               if ((!/blip\.tv/i.test(window.location.hostname) &&
+                    ((object.hasAttribute('src') &&
+                      /blip\.tv/i.test(object.getAttribute('src'))) ||
+                     (object.hasAttribute('data') && 
+                      /blip\.tv/i.test(object.getAttribute('data'))))) || 
+                   (/blip\.tv/i.test(window.location.hostname) && 
+                    ((object.hasAttribute('src') &&
+                      /blip\.tv\/play/i.test(object.getAttribute('src'))) ||
+                     (object.hasAttribute('data') && 
+                      /blip\.tv\/play/i.test(object.getAttribute('data'))))))
+               {
+                   this.request_bliptv_jsonp_data(object_data);
+               }
+               else if (this.wait_xhr)
+               {
+                   this.log("LinternaMagica.extract_objects_from_dom:\n"+
+                            "Waiting "+this.wait_xhr+
+                            " ms ("+(this.wait_xhr/1000)+
+                            " s) before requesting video link via"+
+                            " video_id "+object_data.video_id+" ",1);
 
-               // Wait a while for Dailymotion At the beginning it
-               // seemed that cookies are not set for few seconds.
-               if (/dailymotion\.com/i.test(window.location.hostname))
-               {
+                   var self = this;
                    var data = object_data;
-                   var self = this;
                    setTimeout(function() {
                        self.request_video_link.apply(self,[data]);
-                   }, this.wait_dailymotion);
+                   }, this.wait_xhr);
                }
-               else if ((!/blip\.tv/i.test(window.location.hostname) &&
-                         ((object.hasAttribute('src') &&
-                           /blip\.tv/i.test(object.getAttribute('src'))) ||
-                          (object.hasAttribute('data') && 
-                           /blip\.tv/i.test(object.getAttribute('data'))))) || 
-                        (/blip\.tv/i.test(window.location.hostname) && 
-                         ((object.hasAttribute('src') &&
-                           /blip\.tv\/play/i.test(object.getAttribute('src'))) 
||
-                          (object.hasAttribute('data') && 
-                           
/blip\.tv\/play/i.test(object.getAttribute('data'))))))
-               {
-                   this.request_bliptv_jsonp_data(object_data);
-               }
                else
                {
+                   this.log("LinternaMagica.extract_objects_from_dom:\n"+
+                            "Requesting video link via video_id "+
+                            object_data.video_id,1);
                    this.request_video_link(object_data);
                }
            }
@@ -397,19 +413,16 @@
                break;
            }
 
-           // This bloats FF in youtube:
-           // LinternaMagica.extract_link_from_param_list: Trying
-           // to extract a link from param/attribute "flashvars"
-           // at www.youtube.com time: ***14:58:59:999***
-           // LinternaMagica.extract_link: No link found. at
-           // www.youtube.com time: ***15:12:21:356***
-           if (!/youtube\.com/i.test(window.location.hostname) &&
-               !/youtube-nocookie\.com/i.test(window.location.hostname))
+           var self = this;
+           var val = this.call_site_function_at_position.apply(self,[
+               "skip_link_extraction",
+               window.location.hostname]);
+
+           if (val)
            {
                this.log("LinternaMagica.extract_link_from_param_list:\n"+
                         "Trying to extract a link from"+
                         " param/attribute \""+param.name+"\"",4);
-
                if (!extracted.link)
                {
                    this.extract_link_data = param.value;
@@ -431,21 +444,24 @@
            }
        }
 
-       if (/ted\.com/i.test(window.location.hostname))
+       if (extracted.link)
        {
-           if (extracted.link)
+           this.extract_link_data = param.value;
+           var self = this;
+           var val = this.call_site_function_at_position.apply(self,[
+               "extract_hd_links_from_dom_if_link",
+               window.location.hostname]);
+       
+           if (val && typeof(val) != "boolean")
            {
-               this.log("LinternaMagica.extract_link_from_param_list:\n"+
-                        "Trying to extract ted.com HD links ",1);
-               extracted.hd_links =
-                   this.extract_tedcom_hd_links(param.value);
+               extracted.hd_links = val;
                break;
            }
        }
-       else
+
+       if (extracted.link || extracted.video_id)
        {
-           if (extracted.link || extracted.video_id)
-               break;
+           break;
        }
     }
 

Modified: trunk/src/lm_extract_js_scripts.js
===================================================================
--- trunk/src/lm_extract_js_scripts.js  2011-07-26 07:55:44 UTC (rev 156)
+++ trunk/src/lm_extract_js_scripts.js  2011-07-26 08:02:40 UTC (rev 157)
@@ -63,50 +63,36 @@
        this.script_data = scripts[s].textContent;
        var object_data = null;
 
-       if (/ted\.com/i.test(window.location.hostname) && 
-           this.script_data.length >=15000)
+       var self = this;
+       var val = this.call_site_function_at_position.apply(self,[
+           "skip_script_processing",
+           window.location.hostname]);
+
+       if (!val)
        {
            continue;
        }
 
-       if (/theonion\.com/i.test(window.location.hostname))
-       {
-           object_data = this.extract_object_from_script_theonion();
+       var self = this;
+       var val = this.call_site_function_at_position.apply(self,[
+           "extract_object_from_script",
+           window.location.hostname]);
 
-           if (!object_data)
-           {
-               // No other method of extraction is useful. Skip to
-               // next script.
-               continue;
-           }
-       }
-
-       if (/youtube\.com/i.test(window.location.hostname) ||
-           (/youtube-nocookie\.com/i.test(window.location.hostname)))
+       if (this.sites[window.location.hostname] && !val)
        {
-           object_data =
-               this.extract_object_from_script_youtube();
+           // Site specific code is used but no results were
+           // returned. Can't extract object information. General
+           // purpose extraction might not worк, so it is useless.
+           this.log("LinternaMagica.extract_objects_from_scripts:\n"+
+                    "Site specific code did not return object data. Skipping"+
+                    " general purpose extraction",6);
 
-           // Fix bloating in FF (mainly). Optimizes script
-           // processing. No need to check the other swf constructors
-           // in YouTube.
-           if (!object_data)
-           {
-               continue;
-           }
+           continue;
        }
 
-       if (/vimeo\.com/i.test(window.location.hostname))
+       if (val && typeof(val) != "boolean")
        {
-           object_data =
-               this.extract_object_from_script_vimeo();
-
-           // Optimizes script processing. No need to check the other
-           // swf constructors in Vimeo.
-           if (!object_data)
-           {
-               continue;
-           }
+           object_data = val;
        }
 
        if (!object_data)
@@ -134,44 +120,37 @@
                     object_data.video_id,1);
 
            this.request_video_link(object_data);
-
-           if (/youtube\.com/i.test(window.location.hostname) ||
-               (/youtube-nocookie\.com/i.test(window.location.hostname)))
-           {
-               // We assume there is only one object per page in 
-               // YouTube found trough scripts.
-               // Stop processing, so it will not bloat.
-               this.log("LinternaMagica.constructor:\n"+
-                        "Found one object in YouTube. Stopping script 
processing",1);
-               break;
-           }
        }
 
        if (object_data && object_data.link)
        {
-           if(!/youtube\.com/i.test(window.location.hostname) &&
-              !/.*facebook\.com/i.test(window.location.hostname))
-           {
+           var self = this;
+           var val = this.call_site_function_at_position.apply(self,[
+               "replace_extracted_object_from_script",
+               window.location.hostname,object_data]);
 
+           // Default
+           if (val && typeof(val) == "boolean")
+           {
                this.log("LinternaMagica.extract_objects_from_scripts:\n"+
-                        "Removing plugin install warning.",2);
+                        "Removing plugin install warning.",2);
 
-               this.remove_plugin_install_warning(object_data.parent);
+               this.remove_plugin_install_warning(object_data.parent);
 
-               this.create_video_object(object_data);
+               this.create_video_object(object_data);
            }
+       }
 
-           if (/.*facebook\.com/i.test(window.location.hostname)  &&
-               !this.facebook_flash_upgrade_timeout)
+       if (object_data && (object_data.video_id || object_data.link))
+       {
+           var self = this;
+           var val = this.call_site_function_at_position.apply(self,[
+               "stop_if_one_extracted_object_from_script",
+               window.location.hostname]);
+
+           if (!val)
            {
-               this.facebook_flash_upgrade_counter = 0;
-               var data = object_data;
-               var self = this;
-               this.facebook_flash_upgrade_timeout =
-                   setInterval(function() {
-                       self.detect_facebook_flash_upgrade.
-                           apply(self,[data]);
-                   }, 500);
+               break;
            }
        }
     }

Modified: trunk/src/lm_extract_js_swfobject.js
===================================================================
--- trunk/src/lm_extract_js_swfobject.js        2011-07-26 07:55:44 UTC (rev 
156)
+++ trunk/src/lm_extract_js_swfobject.js        2011-07-26 08:02:40 UTC (rev 
157)
@@ -120,52 +120,48 @@
        object_data.height = object_data.parent.clientHeight;
     }
 
-    if (/dailymotion\.com/i.test(window.location.hostname))
+    this.extract_link_data = data;
+    object_data.link = this.extract_link();
+
+
+    if (!object_data.link)
     {
-       object_data.video_id = window.location.pathname;
-    }
-    else
-    {
-       this.extract_link_data = data;
-       object_data.link = this.extract_link();
+       this.extract_video_id_data = data;
 
-       if (!object_data.link)
+       var self = this;
+       var val = this.call_site_function_at_position.apply(self,[
+           "libswfobject_skip_video_id_extraction",
+           window.location.hostname,object_data]);
+
+       // Result from default function
+       if (val && typeof(val) == "boolean")
        {
-           this.extract_video_id_data = data;
            object_data.video_id = this.extract_video_id();
        }
+       else if(val)
+       {
+           // Result from site function
+           object_data.video_id = val;
+       }
     }
 
     if (object_data.video_id || object_data.link)
     {
-       // if (/dailymotion\.com/i.test(window.location.hostname))
-       // {
-       //     
this.log("LinternaMagica.extract_object_from_script_swfobject:\n"+
-       //           "Trying to extract dailymotion.com HQ links ",1);
-       //     object_data.hd_links = this.extract_dailymotion_hd_links(data);
-
-       // }
-       // else
-       if (/ted\.com/i.test(window.location.hostname))
-       {
-           this.log("LinternaMagica.extract_object_from_script_swfobject:\n"+
-                    "Trying to extract ted.com HQ links ",1);
-           object_data.hd_links = this.extract_tedcom_hd_links(data);
-       }
-       // else if (/myvideo\.de/i.test(window.location.hostname))
-       // {
-       //     // See the comments for this function
-       //     object_data.link = this.create_myvideode_link();
-       //     // Now that we have a link remove the video_id
-       //     // so it is not processed
-       //     object_data.video_id = null;
-       // }
-
        this.log("LinternaMagica.extract_object_from_script_swfobject:\n"+
                 "SWF object extracted from script ",1);
 
        object_data.linterna_magica_id =
            this.mark_flash_object("extracted-from-script");
+       
+       var self = this;
+       var val = this.call_site_function_at_position.apply(self,[
+           "extract_hd_links_from_script_if_link",
+           window.location.hostname, data]);
+       
+       if (val && typeof(val) != "boolean")
+       {
+           object_data.hd_links = val;
+       }
 
        return object_data;
     }

Modified: trunk/src/lm_extract_video_link.js
===================================================================
--- trunk/src/lm_extract_video_link.js  2011-07-26 07:55:44 UTC (rev 156)
+++ trunk/src/lm_extract_video_link.js  2011-07-26 08:02:40 UTC (rev 157)
@@ -36,159 +36,68 @@
     }
 
     var data = this.extract_link_data;
-    var link_re = null;
 
+    var self = this;
+    var val = this.call_site_function_at_position.apply(self,[
+       "set_video_link_regex",
+       window.location.hostname]);
 
-    if (/facebook\.com/i.test(window.location.hostname))
+
+    var link_re = null;
+    var link_position = null;
+
+    if (val && typeof(val) != "boolean")
     {
-       // Found DOM object
-       if (!this.script_data)
-       {
-           link_re = new RegExp (
-               "thumb_url=(.*)&video_src=(.*)&(motion_log)=(.*)",
-               "i");
-       }
-       // Extracting from script
-       else
-       {
-           link_re = new RegExp (
-               "addVariable\\\((\\\"|\\\')video_src(\\\"|\\\'),\\\s*"+
-                   "(\\\"|\\\')([^\\\"\\\']+)(\\\"|\\\')(\\\))\\\;{1}",
-               "i");
-       }
+       link_re = val.link_re;
+       link_position = val.link_position;
     }
-    // Reuters
-    else if (/reuters\.com/i.test(window.location.hostname))
-    {
-       link_re = new RegExp (
-           "videoURL=(.*)(\\\&{1})(.*)",
-       "i");
-    }
-    // Will match com,de,es, jp etc.
-    else if (/video\.google\./i.test(window.location.hostname))
-    {
-       link_re = new RegExp (
-           "videourl=(.*)\\\&(thumbnailurl)=(.*)" ,
-           "i");
-    }
     else
     {
-       // FIXME: Regular expressions need rework to match
-       // flv|mp4|other|something_else|...mp3|audio
-       // 26.02.2011 added streamer| before |file. Fixes
-       // jwak.net. The file part matches resource on 8081 port which
-       // is not accessible.
        link_re = new RegExp (
            "\\\{{0}.*(video|flv_ur|streamer|file|moviepath|videourl|"+
-               "mediaurl|sdurl|videopath|flv|url|ms|nextmovie|flvaddress)"+
+               "mediaurl|sdurl|videopath|flv|url|ms|"+
+               "nextmovie|flvaddress)"+
                "(\\\"|\\\')*\\\s*(\\\=|\\\:|\\\,)\\\s*(\\\"|\\\')*"+
-               (/clipovete\.com/i.test(window.location.hostname)
-                ? "(.*)\\\&(video_id)=(.*)" :
                 "(.*\\\."+
-                // Metacafe switched to mp4 for some videos.
-                // FIXME: We need a general way to match mp4 and other stuff
-                (/metacafe\.com/i.test(window.location.hostname) ?
-                 "(mp4|flv)" :"flv")+"((\\\?|\\\&)?\\\w+\\\=[A-Za-z0-9_\\\-]+"+
-                "\\\&?)*)(?!\\\.)"),
+               "(flv|mp4)"+ // Add other extensions here
+               "((\\\?|\\\&)?\\\w+\\\=[A-Za-z0-9_\\\-]+"+
+               "\\\&?)*)(?!\\\.)",
            "i");
     }
 
-    var link = unescape(data).match(link_re);
-
-    // Extra debug for metacafe, because it changes often
-    if (/metacafe\.com/i.test(window.location.hostname))
+    if (link_position == null ||
+       typeof(link_position) == "undefined")
     {
-       this.log("LinternaMagica.extract_link:\n"+
-                "Unescaped metacafe.com data: "+unescape(data),5);
+       link_position = 4;
     }
 
-    if (link && link[link.length-3])
+    var link = unescape(data).match(link_re);
+
+    if (link && link[link.length-link_position])
     {
-       if (!/metacafe\.com/i.test(window.location.hostname))
-       {
-           link = unescape(link[link.length-3]);
-       }
-       else
-       {
-           link = unescape(link[link.length-4]);
-       }
+       link = unescape(link[link.length-link_position]);
 
-       // Used in Metacafe. Unescape is not helping.
+       // Used in Metacafe. Unescape is not helping. Small and not
+       // significant to be exported in src/lm_site_metacafe.js
        link = link.replace(/\\\//g, "/");
 
-       if (/facebook\.com/i.test(window.location.hostname))
-       {
-           // For som reason they use Unicode escape character, that
-           // could not be converted by decodeURIComponent or
-           // unescape directly. This workaround might break
-           // non-ASCII strings in the link
-           link = unescape(link.replace(/\\u0025/g, "%"));
-       }
+       var self = this;
+       var val = this.call_site_function_at_position.apply(self,[
+           "process_extracted_link",
+           window.location.hostname, link]);
 
-       if (/metacafe\.com/i.test(window.location.hostname))
+       if (val && typeof(val) != "boolean")
        {
-           if (/flv/i.test(link))
-           {
-               link = link.replace(/&gdaKey/i, "?__gda__");
-           }
-           else
-           {
-               var key_re = new RegExp(
-                   link.slice(link.length-15).replace(/\\\./g,"\\\\\\.")+
-                       "\\\"\\\,\\\"key\\\"\\\:\\\"([0-9A-Za-z\\\_]+)\\\"",
-                   "i");
-               var key = unescape(data).match(key_re);
-
-               // Set the key
-               link = link+"?__gda__="+key[key.length-1];
-           }
-
-           // Escape. We cannot use escape()
-           // because it will break the link and we have to
-           // fix manualy characters like = : ?
-           link = link.replace("[", "%5B").
-               replace(" ", "%20").replace("]", "%5D");
+           link = val;
        }
 
-       if (/clipovete\.com/i.test(window.location.hostname))
-       {
-           link =  "http://storage.puiako.com/clipovete.com/videos/"+
-               link +".flv";
-       }
+       var self = this;
+       var val = this.call_site_function_at_position.apply(self,[
+           "do_not_clean_amps_in_extracted_link",
+           window.location.hostname]);
 
-       // The link is not a full path and is missing a slash.
-       if (/tv7\.bg/i.test(window.location.hostname))
+       if (val)
        {
-           link = "/"+link;
-       }
-       
-       // Must be just the path part othe link
-       if (/mqsto\.com/i.test(window.location.hostname) &&
-           !/^http/i.test(link))
-       {
-           link = "http://mqsto\.com/video/"+link;
-       }
-
-       // The link is not full path
-       if (/friends\.bg/i.test(window.location.hostname))
-       {
-           link = "/files/video/flv/"+link;
-       }
-
-       // Amps are not required everywhere
-       var keep_amp_in_hosts_re = new RegExp (
-           // Will match com de etc.
-           "video\\\.google\\\.|"+
-               ".*facebook\\\.",
-           // this used to be cleared. now the logic is reverse
-           // "i-kat\\\.org|video\\\.fensko\\\.com|mqsto\\\.com"+
-           //  "|fun-6\\\.com|videoclipsdump\\\.com|boomclips\\\.com"+
-           //  "|lucidclips\\\.com|reuters\\\.com|failo\\\.bg|5min\\\.com|"+
-           //  "mediashare\\\.bg|ted\\\.com",
-           "i");
-
-       if (!keep_amp_in_hosts_re.exec(window.location.hostname))
-       {
            // The parameters are for the player and with them the
            // video is no accessible
            link = link.split("&")[0];
@@ -197,14 +106,21 @@
                     " Link split at the first ampersand",3);
 
            // Abrowser/Firefox is not loading i-kat.org link
-           // with two slashes. Strange.
+           // with two slashes. Strange!
            link = link.replace(/[^:]\/\//, "/");
        }
 
-       if (/ted\.com/i.test(window.location.hostname))
-       {
-           link = this.create_tedcom_link(link);
-       }
+       // // Amps are not required everywhere
+       // var keep_amp_in_hosts_re = new RegExp (
+       //     // Will match com de etc.
+       //     "video\\\.google\\\.|"+
+       //      ".*facebook\\\.",
+       //     // this used to be cleared. now the logic is reverse
+       //     // "i-kat\\\.org|video\\\.fensko\\\.com|mqsto\\\.com"+
+       //     //       "|fun-6\\\.com|videoclipsdump\\\.com|boomclips\\\.com"+
+       //     //       
"|lucidclips\\\.com|reuters\\\.com|failo\\\.bg|5min\\\.com|"+
+       //     //       "mediashare\\\.bg|ted\\\.com",
+       //     "i");
 
        this.log("LinternaMagica.extract_link:\n"+
                 " Extracted link: "+link,1);
@@ -236,31 +152,38 @@
     data = "&"+data;
 
     var video_id_re = null;
+    var match_site = null;
+    var video_id_position = null;
 
-    if (/blip\.tv/i.test(window.location.hostname) ||
-       /blip\.tv/i.test(data))
+    if (/blip\.tv/i.test(data))
     {
        // Blip.tv has a JSONP API that could be used in remote
        // sites. That is why we cant search for blip.tv directly in
        // the data.
        // http://wiki.blip.tv/index.php/Extract_metadata_from_our_embed_code
-       video_id_re = new RegExp(
-           "blip\\\.tv\\\/(play|rss\\\/flash)\\\/([0-9A-Za-z_%-]+)&*",
-           "i");
+
+       match_site = "blip.tv";
     }
     else
     {
-       // 06.07.2010 Update  for vidoemo.com video3 and \\\/
-       // slashes before and after might create bugs
-       // 18.12.2010 Update is for vimeo.com : vimeo_clip_
-       // 12.02.2011 Update for myvideo.de. php&ID and \\\. This migth break
-       // 25.02.2011 Update for videoclipsdump.com
-       // player_config\\\.php\\\ must be after vid|
-       // 11.06.2011 Update for theonion.com 
-       // \\\/video_embed\\\/...
+       match_site = window.location.hostname;
+    }
+
+    var self = this;
+    var val = this.call_site_function_at_position.apply(self,[
+       "set_video_id_regex",
+       match_site]);
+
+    if (val && typeof(val) !== "boolean")
+    {
+       video_id_re = val.video_id_re;
+       video_id_position = val.video_id_position;
+    }
+    else
+    {
        video_id_re = new RegExp (
-           
"(\\\"|\\\'|\\\&|\\\?|\\\;|\\\/|\\\.|\\\=)(itemid|clip_id|video_id|"+
-               "vid|player_config\\\.php\\\?v|"+
+           "(\\\"|\\\'|\\\&|\\\?|\\\;|\\\/|\\\.|\\\=)(itemid|"+
+               "clip_id|video_id|vid|player_config\\\.php\\\?v|"+
                "videoid|media_id|vkey|video3|_videoid|"+
                "vimeo_clip_|php&ID|\\\/video_embed\\\/\\\?id)"+
                "(\\\"|\\\')*(\\\=|\\\:|,|\\\/)\\\s*(\\\"|\\\')*"+
@@ -268,11 +191,17 @@
        "i");
     }
 
+    if (video_id_position == null ||
+       typeof(video_id_position) == "undefined")
+    {
+       video_id_position = 1;
+    }
+
     var video_id =data.match(video_id_re);
 
     if (video_id)
     {
-       video_id = video_id[video_id.length-1];
+       video_id = video_id[video_id.length-video_id_position];
 
        this.log("LinternaMagica.extract_video_id:\n"+
                 "Extracted video id : "+video_id,1);

Modified: trunk/src/lm_init_options.js
===================================================================
--- trunk/src/lm_init_options.js        2011-07-26 07:55:44 UTC (rev 156)
+++ trunk/src/lm_init_options.js        2011-07-26 08:02:40 UTC (rev 157)
@@ -75,12 +75,12 @@
        // delete: Just delete the cookies.
        // restore: Extract and restore cookies.
        "cookies": "restore",
-       // Timeout before background processing starts in Dailymotion in
+       // Timeout before background processing (XHR) starts  in
        // milliseconds. 1 s = 1000 ms. If you have problems increase the
        // value.
        // off/no/disabled/false/0: Don't wait (defult)
         // <integer>: Wait for <integer> milliseconds.
-       "wait_dm": "off",
+       "wait_xhr": "off",
        // Preferred video quality.
        //
        // low/medium/high: Automatically select the link for

Modified: trunk/src/lm_remove_plugin_install_warning.js
===================================================================
--- trunk/src/lm_remove_plugin_install_warning.js       2011-07-26 07:55:44 UTC 
(rev 156)
+++ trunk/src/lm_remove_plugin_install_warning.js       2011-07-26 08:02:40 UTC 
(rev 157)
@@ -102,7 +102,6 @@
 
                // video.fensko.com has ancor and text node that share
                // the text. Leaving it is just irritating
-
                if (/^a$/i.test(node.localName) &&
                    node.nextSibling &&
                    node.nextSibling.nodeType === 3 &&
@@ -121,29 +120,30 @@
            }
        }
 
-       // FIXME Temporary fix for Blip.tv. Will replace the HTML5
-       // player, otherwise two are visible.  14.06.2011 With the
-       // changes in Blip.tv design and logic, I am unable to find
-       // how to turn HTML5 and test this. I always get the flash
-       // player.
-       if (/blip\.tv/i.test(window.location.hostname))
+       var self = this;
+       var val = this.call_site_function_at_position.apply(self,[
+           "plugin_install_warning_loop",
+           window.location.hostname, node]);
+
+       if (val && typeof(val) != "boolean")
        {
-           if (node.parentNode)
-           {
-               node.parentNode.removeChild(node);
-           }
+           // Useless for now. The place where it is used
+           // (lm_site_bliptv.js) just removes the node on condition. 
+           node = val;
        }
-       
+
        node = new_node;
     }
 
-    // Not a plugin warning, but the best place for this. Remove div
-    // element blocking the new object.
+    var self = this;
+    var val = this.call_site_function_at_position.apply(self,[
+       "plugin_install_warning",
+       window.location.hostname, node]);
 
-    if (/clipovete\.com/i.test(window.location.hostname))
+    if (val && typeof(val) != "boolean")
     {
-       var ads = document.getElementById('ads_video');
-       if (ads)
-           ads.parentNode.removeChild(ads);
+       // Useless for now. The place where it is used
+       // (lm_site_clipovetecom.js) does not change the node.
+       node = val;
     }
 }

Modified: trunk/src/lm_site_bliptv.js
===================================================================
--- trunk/src/lm_site_bliptv.js 2011-07-26 07:55:44 UTC (rev 156)
+++ trunk/src/lm_site_bliptv.js 2011-07-26 08:02:40 UTC (rev 157)
@@ -89,3 +89,88 @@
     this.create_video_object(object_data);
 }
 
+LinternaMagica.prototype.sites["blip.tv"] = new Object();
+
+// Reference
+LinternaMagica.prototype.sites["www.blip.tv"] = "blip.tv";
+
+LinternaMagica.prototype.sites["blip.tv"].set_video_id_regex = function()
+{
+    var result = new Object();
+
+    result.video_id_re = new RegExp(
+       "blip\\\.tv\\\/(play|rss\\\/flash)\\\/([0-9A-Za-z_%-]+)&*",
+       "i");
+
+    // Captured video_id position from left to right. Will be
+    // subtracted from the matched arrays's lenght;
+    result.videoid_position = 1;
+
+    return result;
+}
+
+LinternaMagica.prototype.sites["blip.tv"].plugin_install_warning_loop =
+function(node)
+{
+    // FIXME Temporary fix for Blip.tv. Will replace the HTML5
+    // player, otherwise two are visible.  14.06.2011 With the
+    // changes in Blip.tv design and logic, I am unable to find
+    // how to turn HTML5 and test this. I always get the flash
+    // player.
+    if (node.parentNode)
+    {
+        node.parentNode.removeChild(node);
+    }
+
+    return null;
+}
+
+LinternaMagica.prototype.sites["blip.tv"].prepare_xhr =
+function(object_data)
+{
+    // Will be called if (when) blip.tv changes the code they use to
+    // embed clips in blip.tv. Now the JSONP method is used.
+    var result= new Object();
+
+    result.address = "/rss/flash/"+object_data.video_id;
+
+    return result;
+}
+
+LinternaMagica.prototype.sites["blip.tv"].process_xhr_response =
+function(args)
+{
+    var client = args.client;
+    var object_data = args.object_data;
+
+    var xml = client.responseXML;
+
+    // All the data is available in the XML, but it is not a
+    // good idea to support the site in two places. JSON is
+    // easier. The drawback is two requests.
+    try
+    {
+       var embed_id =
+           xml.getElementsByTagName("embedLookup");
+
+       // Firefox
+       if (embed_id && typeof(embed_id[0]) == "undefined")
+       {
+           embed_id = 
+               xml.getElementsByTagName("blip:embedLookup");
+       }
+
+       object_data.video_id = embed_id[0].textContent;
+       this.request_bliptv_jsonp_data(object_data);
+    }
+    catch(e)
+    {
+       this.log("LinternaMagica.prototype.request_video"+
+                "_link_parse_response:\n"+
+                "Exception in Blip.tv while parsing XML",1);
+    }
+
+    // Do not process the XHR anymore. The video object will not be
+    // created.
+    return null;
+}

Copied: trunk/src/lm_site_boozhocom.js (from rev 156, 
branches/task-11216/src/lm_site_boozhocom.js)
===================================================================
--- trunk/src/lm_site_boozhocom.js                              (rev 0)
+++ trunk/src/lm_site_boozhocom.js      2011-07-26 08:02:40 UTC (rev 157)
@@ -0,0 +1,56 @@
+//  @licstart The following is the entire license notice for the
+//  JavaScript code in this page (or file).
+//
+//  This file is part of Linterna Mágica
+//
+//  Copyright (C) 2010, 2011  Ivaylo Valkov <address@hidden>
+//  Copyright (C) 2010  Anton Katsarov <address@hidden>
+//
+//  The JavaScript code in this page (or file) is free software: you
+//  can redistribute it and/or modify it under the terms of the GNU
+//  General Public License (GNU GPL) as published by the Free Software
+//  Foundation, either version 3 of the License, or (at your option)
+//  any later version.  The code is distributed WITHOUT ANY WARRANTY
+//  without even the implied warranty of MERCHANTABILITY or FITNESS
+//  FOR A PARTICULAR PURPOSE.  See the GNU GPL for more details.
+//
+//  As additional permission under GNU GPL version 3 section 7, you
+//  may distribute non-source (e.g., minimized or compacted) forms of
+//  that code without the copy of the GNU GPL normally required by
+//  section 4, provided you include this license notice and a URL
+//  through which recipients can access the Corresponding Source.
+//
+//  @licend The above is the entire license notice for the JavaScript
+//  code in this page (or file).
+//
+// @source http://linterna-magica.nongnu.org
+
+// END OF LICENSE HEADER
+
+LinternaMagica.prototype.sites["boozho.com"] = new Object();
+
+// Reference
+LinternaMagica.prototype.sites["www.boozho.com"] = "boozho.com";
+
+LinternaMagica.prototype.sites["boozho.com"].prepare_xhr =
+function(object_data)
+{
+    var result = new Object();
+    result.address = "/player_playlist.php?v="+object_data.video_id;
+
+    return result;
+}
+
+LinternaMagica.prototype.sites["boozho.com"].process_xhr_response =
+function(args)
+{
+    var client = args.client;
+    var object_data = args.object_data;
+
+    var xml = client.responseXML;
+
+    var rel_url = xml.getElementsByTagName("movie_path")[0].textContent;
+    object_data.link = "http://www.boozho.com/"+rel_url;
+
+    return object_data;
+}

Copied: trunk/src/lm_site_clipovetecom.js (from rev 156, 
branches/task-11216/src/lm_site_clipovetecom.js)
===================================================================
--- trunk/src/lm_site_clipovetecom.js                           (rev 0)
+++ trunk/src/lm_site_clipovetecom.js   2011-07-26 08:02:40 UTC (rev 157)
@@ -0,0 +1,65 @@
+//  @licstart The following is the entire license notice for the
+//  JavaScript code in this page (or file).
+//
+//  This file is part of Linterna Mágica
+//
+//  Copyright (C) 2010, 2011  Ivaylo Valkov <address@hidden>
+//  Copyright (C) 2010  Anton Katsarov <address@hidden>
+//
+//  The JavaScript code in this page (or file) is free software: you
+//  can redistribute it and/or modify it under the terms of the GNU
+//  General Public License (GNU GPL) as published by the Free Software
+//  Foundation, either version 3 of the License, or (at your option)
+//  any later version.  The code is distributed WITHOUT ANY WARRANTY
+//  without even the implied warranty of MERCHANTABILITY or FITNESS
+//  FOR A PARTICULAR PURPOSE.  See the GNU GPL for more details.
+//
+//  As additional permission under GNU GPL version 3 section 7, you
+//  may distribute non-source (e.g., minimized or compacted) forms of
+//  that code without the copy of the GNU GPL normally required by
+//  section 4, provided you include this license notice and a URL
+//  through which recipients can access the Corresponding Source.
+//
+//  @licend The above is the entire license notice for the JavaScript
+//  code in this page (or file).
+//
+// @source http://linterna-magica.nongnu.org
+
+// END OF LICENSE HEADER
+
+LinternaMagica.prototype.sites["clipovete.com"] = new Object();
+
+// Reference
+LinternaMagica.prototype.sites["www.clipovete.com"] = "clipovete.com";
+
+LinternaMagica.prototype.sites["clipovete.com"].set_video_link_regex =
+function()
+{
+    var result = new Object();
+    result.link_re =  new RegExp (
+       "\\\&video=(.*)\\\&(video_id)=(.*)",
+       "i");
+
+    result.link_position = 3;
+
+    return result;
+}
+
+LinternaMagica.prototype.sites["clipovete.com"].process_extracted_link = 
function(link)
+{
+    return  "http://storage.puiako.com/clipovete.com/videos/"+link +".flv";
+}
+
+LinternaMagica.prototype.sites["blip.tv"].plugin_install_warning =
+function(node)
+{
+    // Not a plugin warning, but the best place for this. Remove div
+    // element blocking the new object.
+    var ads = document.getElementById('ads_video');
+    if (ads)
+    {
+       ads.parentNode.removeChild(ads);
+    }
+
+    return null;
+}

Modified: trunk/src/lm_site_dailymotion.js
===================================================================
--- trunk/src/lm_site_dailymotion.js    2011-07-26 07:55:44 UTC (rev 156)
+++ trunk/src/lm_site_dailymotion.js    2011-07-26 08:02:40 UTC (rev 157)
@@ -68,3 +68,137 @@
 
     return null;
 }
+
+LinternaMagica.prototype.sites["dailymotion.com"] = new Object();
+
+// Reference
+LinternaMagica.prototype.sites["www.dailymotion.com"] = "dailymotion.com";
+
+LinternaMagica.prototype.sites["dailymotion.com"].no_flash_plugin_installed =
+function()
+{
+    this.request_video_link({video_id: window.location.pathname});
+    return true;
+}
+
+LinternaMagica.prototype.sites["dailymotion.com"].process_cookies =
+function()
+{
+    // Dailymotion is processed twice. Once with .dailymotion.com. The
+    // second time with www.dailymotion.com. They set cookies very
+    // strange.  Also they use host= which is not documented anywhere
+    // (DOM 0,1...).
+    return "; domain=.dailymotion.com; path=/; 
host="+window.location.hostname+"; ";
+}
+
+LinternaMagica.prototype.sites["dailymotion.com"].do_not_force_iframe_detection
 =
+function()
+{
+    // If Flashblock is installed, it will replace an iframe that has
+    // something to do with Twitter. We have to replace the Flashblock
+    // blocked object. Returning, false will make the logic in
+    // lm_detect_flash.js not detect the iframe as swf.
+    return false;
+}
+
+LinternaMagica.prototype.sites["dailymotion.com"].skip_video_id_extraction =
+function ()
+{
+    // Can't extract video_id from script when flash is not
+    // isntalled. The video id is always the pathname.
+    var extracted_data = new Object();
+    extracted_data.video_id = window.location.pathname;
+    return  extracted_data;
+}
+
+LinternaMagica.prototype.sites["dailymotion.com"].
+    libswfobject_skip_video_id_extraction =
+function()
+{
+    this.log("LinternaMagica.sites.libswfobject_skip_video_"+
+            "id_extraction:\n"+
+            "Video id forced to "+window.location.pathname,1);
+
+    return window.location.pathname;
+}
+
+LinternaMagica.prototype.sites["dailymotion.com"].prepare_xhr =
+function(object_data)
+{
+    var result = new Object();
+
+    // The video_id is forced to an address. See
+    // LinternaMagica.prototype.sites["dailymotion.com"].
+    // libswfobject_skip_video_id_extraction
+    result.address = object_data.video_id;
+
+    this.extract_cookies();
+    this.expire_cookies();
+
+    return result;
+}
+
+LinternaMagica.prototype.sites["dailymotion.com"].process_xhr_response =
+function(args)
+{
+    var client = args.client;
+    var object_data = args.object_data;
+
+    if (!this.plugin_is_installed &&
+       !object_data.linterna_magica_id && 
+       !object_data.parent)
+    {
+       // In Dailymotion the script that creates the flash
+       // object replaces itself. The work around here is to
+       // request the page and process it. 
+
+       // Dailymotion uses pseudo-random ids for some DOM
+       // elements of interest. We replace the body HTML with
+       // the one returned by the XHR. Then scripts are
+       // processed. The script extraction code matches the
+       // correct ID for the parentNode in DOM, that will
+       // hold the video object. The original body is
+       // restored, because some data is missing in the body
+       // data from XHR. After all data is collected, the
+       // parentNode (object_data.parent), where the video
+       // object will be inserted is replaced with the one in
+       // the original body.  Custom function to match the
+       // parent by CSS class is used, because getElementById
+       // does not support regular expressions.
+
+       var body_data = 
+           client.responseText.split("<body")[1].
+           replace(/>{1}/,"__SPLIT__").
+           split("__SPLIT__")[1];
+
+       var body = document.getElementsByTagName("body")[0];
+       var original_body_data = body.innerHTML;
+
+       body.innerHTML = body_data;
+
+       this.script_data = client.responseText;
+       object_data = this.extract_object_from_script_swfobject();
+
+       body.innerHTML = original_body_data;
+
+       object_data.parent = 
+           this.get_first_element_by_class("dmpi_video_playerv[0-9]+");
+
+       if (!object_data.parent)
+       {
+           return null;
+       }
+    }
+
+    var hd_links = this.extract_dailymotion_links(client.responseText);
+    object_data.link = hd_links ? hd_links[hd_links.length-1].url : null;
+    object_data.hd_links = hd_links.length ? hd_links : null;
+
+    // See "A note on cookies"
+    if (/restore/i.test(this.process_cookies))
+    {
+       this.restore_cookies();
+    }
+
+    return object_data;
+}

Modified: trunk/src/lm_site_facebook.js
===================================================================
--- trunk/src/lm_site_facebook.js       2011-07-26 07:55:44 UTC (rev 156)
+++ trunk/src/lm_site_facebook.js       2011-07-26 08:02:40 UTC (rev 157)
@@ -58,3 +58,73 @@
        this.create_video_object(object_data);
     }
 }
+
+LinternaMagica.prototype.sites["facebook.com"] = new Object();
+
+// Reference
+LinternaMagica.prototype.sites["www.facebook.com"] = "facebook.com";
+
+LinternaMagica.prototype.sites["facebook.com"].
+    replace_extracted_object_from_script =
+function(object_data)
+{
+    if (!this.facebook_flash_upgrade_timeout)
+    {
+       this.log("LinternaMagica.sites.replace_extracted_"+
+                "object_from_script:\n"+
+                "Delaying video object creation in Facebook.",3);
+       this.facebook_flash_upgrade_counter = 0;
+       var data = object_data;
+       var self = this;
+       this.facebook_flash_upgrade_timeout =
+           setInterval(function() {
+               self.detect_facebook_flash_upgrade.
+                   apply(self,[data]);
+           }, 500);
+    }
+
+    return false;
+}
+
+LinternaMagica.prototype.sites["facebook.com"].set_video_link_regex =
+function()
+{
+    var result = new Object();
+
+    // Found DOM object
+    if (!this.script_data)
+    {
+       result.link_re = new RegExp (
+           "thumb_url=(.*)&video_src=(.*)&(motion_log)=(.*)",
+           "i");
+
+       result.link_position = 3;
+    }
+    // Extracting from script
+    else
+    {
+       result.link_re = new RegExp (
+           "addVariable\\\((\\\"|\\\')video_src(\\\"|\\\'),\\\s*"+
+               "(\\\"|\\\')([^\\\"\\\']+)(\\\"|\\\')(\\\))\\\;{1}",
+           "i");
+
+       result.link_position = 3;
+    }
+
+    return result;
+}
+
+LinternaMagica.prototype.sites["facebook.com"].process_extracted_link = 
function(link)
+{
+    // For some reason they use Unicode escape character, that
+    // could not be converted by decodeURIComponent or
+    // unescape directly. This workaround might break
+    // non-ASCII strings in the link
+    link = unescape(link.replace(/\\u0025/g, "%"));
+
+    return link;
+}
+
+// Reference. Just returns false
+LinternaMagica.prototype.sites["facebook.com"].
+    do_not_clean_amps_in_extracted_link = "video.google.com";

Copied: trunk/src/lm_site_google_video.js (from rev 156, 
branches/task-11216/src/lm_site_google_video.js)
===================================================================
--- trunk/src/lm_site_google_video.js                           (rev 0)
+++ trunk/src/lm_site_google_video.js   2011-07-26 08:02:40 UTC (rev 157)
@@ -0,0 +1,68 @@
+//  @licstart The following is the entire license notice for the
+//  JavaScript code in this page (or file).
+//
+//  This file is part of Linterna Mágica
+//
+//  Copyright (C) 2010, 2011  Ivaylo Valkov <address@hidden>
+//  Copyright (C) 2010  Anton Katsarov <address@hidden>
+//
+//  The JavaScript code in this page (or file) is free software: you
+//  can redistribute it and/or modify it under the terms of the GNU
+//  General Public License (GNU GPL) as published by the Free Software
+//  Foundation, either version 3 of the License, or (at your option)
+//  any later version.  The code is distributed WITHOUT ANY WARRANTY
+//  without even the implied warranty of MERCHANTABILITY or FITNESS
+//  FOR A PARTICULAR PURPOSE.  See the GNU GPL for more details.
+//
+//  As additional permission under GNU GPL version 3 section 7, you
+//  may distribute non-source (e.g., minimized or compacted) forms of
+//  that code without the copy of the GNU GPL normally required by
+//  section 4, provided you include this license notice and a URL
+//  through which recipients can access the Corresponding Source.
+//
+//  @licend The above is the entire license notice for the JavaScript
+//  code in this page (or file).
+//
+// @source http://linterna-magica.nongnu.org
+
+// END OF LICENSE HEADER
+
+LinternaMagica.prototype.sites["video.google.com"] = new Object();
+
+// References to al Google Video domains
+// http://en.wikipedia.org/wiki/Google_Videos#International
+LinternaMagica.prototype.sites["video.google.com.au"] = "video.google.com";
+LinternaMagica.prototype.sites["video.google.com.br"] = "video.google.com";
+LinternaMagica.prototype.sites["video.google.ca"] = "video.google.com";
+LinternaMagica.prototype.sites["video.google.cn"] = "video.google.com";
+LinternaMagica.prototype.sites["video.google.fr"] = "video.google.com";
+LinternaMagica.prototype.sites["video.google.de"] = "video.google.com";
+LinternaMagica.prototype.sites["video.google.it"] = "video.google.com";
+LinternaMagica.prototype.sites["video.google.nl"] = "video.google.com";
+LinternaMagica.prototype.sites["video.google.pl"] = "video.google.com";
+LinternaMagica.prototype.sites["video.google.es"] = "video.google.com";
+LinternaMagica.prototype.sites["video.google.co.uk"] = "video.google.com";
+LinternaMagica.prototype.sites["video.google.com.ar"] = "video.google.com";
+LinternaMagica.prototype.sites["video.google.ru"] = "video.google.com";
+
+LinternaMagica.prototype.sites["video.google.com"].set_video_link_regex =
+function()
+{
+    var result = new Object();
+
+    result.link_re = new RegExp (
+       "videourl=(.*)\\\&(thumbnailurl)=(.*)" ,
+       "i");
+
+    result.link_position = 3;
+
+    return result;
+}
+
+LinternaMagica.prototype.sites["video.google.com"].
+    do_not_clean_amps_in_extracted_link =
+function()
+{
+    // Just return false (reverse logic)
+    return false;
+}

Copied: trunk/src/lm_site_jwaknet.js (from rev 156, 
branches/task-11216/src/lm_site_jwaknet.js)
===================================================================
--- trunk/src/lm_site_jwaknet.js                                (rev 0)
+++ trunk/src/lm_site_jwaknet.js        2011-07-26 08:02:40 UTC (rev 157)
@@ -0,0 +1,52 @@
+//  @licstart The following is the entire license notice for the
+//  JavaScript code in this page (or file).
+//
+//  This file is part of Linterna Mágica
+//
+//  Copyright (C) 2010, 2011  Ivaylo Valkov <address@hidden>
+//  Copyright (C) 2010  Anton Katsarov <address@hidden>
+//
+//  The JavaScript code in this page (or file) is free software: you
+//  can redistribute it and/or modify it under the terms of the GNU
+//  General Public License (GNU GPL) as published by the Free Software
+//  Foundation, either version 3 of the License, or (at your option)
+//  any later version.  The code is distributed WITHOUT ANY WARRANTY
+//  without even the implied warranty of MERCHANTABILITY or FITNESS
+//  FOR A PARTICULAR PURPOSE.  See the GNU GPL for more details.
+//
+//  As additional permission under GNU GPL version 3 section 7, you
+//  may distribute non-source (e.g., minimized or compacted) forms of
+//  that code without the copy of the GNU GPL normally required by
+//  section 4, provided you include this license notice and a URL
+//  through which recipients can access the Corresponding Source.
+//
+//  @licend The above is the entire license notice for the JavaScript
+//  code in this page (or file).
+//
+// @source http://linterna-magica.nongnu.org
+
+// END OF LICENSE HEADER
+
+LinternaMagica.prototype.sites["jwak.net"] = new Object();
+
+// Reference
+LinternaMagica.prototype.sites["www.jwak.net"] = "jwak.net";
+
+LinternaMagica.prototype.sites["jwak.net"].set_video_link_regex =
+function()
+{
+    // The default regex extracts a links on port 8081 that is not
+    // working. Theoreticaly the default regex could extract the right
+    // link (one row after the wrong one), but it is not a good
+    // solution. It should have worked in r137 (branch task-11216).
+    var result = new Object();
+
+    result.link_re = new RegExp (
+       "addVariable\\\((\\\"|\\\')streamer(\\\"|\\\'),\\\s*"+
+           "(\\\"|\\\')([^\\\"\\\']+)(\\\"|\\\')(\\\))\\\;{1}",
+       "i");
+
+    result.link_position = 3;
+
+    return result;
+}

Copied: trunk/src/lm_site_metacafe.js (from rev 156, 
branches/task-11216/src/lm_site_metacafe.js)
===================================================================
--- trunk/src/lm_site_metacafe.js                               (rev 0)
+++ trunk/src/lm_site_metacafe.js       2011-07-26 08:02:40 UTC (rev 157)
@@ -0,0 +1,64 @@
+//  @licstart The following is the entire license notice for the
+//  JavaScript code in this page (or file).
+//
+//  This file is part of Linterna Mágica
+//
+//  Copyright (C) 2010, 2011  Ivaylo Valkov <address@hidden>
+//  Copyright (C) 2010  Anton Katsarov <address@hidden>
+//
+//  The JavaScript code in this page (or file) is free software: you
+//  can redistribute it and/or modify it under the terms of the GNU
+//  General Public License (GNU GPL) as published by the Free Software
+//  Foundation, either version 3 of the License, or (at your option)
+//  any later version.  The code is distributed WITHOUT ANY WARRANTY
+//  without even the implied warranty of MERCHANTABILITY or FITNESS
+//  FOR A PARTICULAR PURPOSE.  See the GNU GPL for more details.
+//
+//  As additional permission under GNU GPL version 3 section 7, you
+//  may distribute non-source (e.g., minimized or compacted) forms of
+//  that code without the copy of the GNU GPL normally required by
+//  section 4, provided you include this license notice and a URL
+//  through which recipients can access the Corresponding Source.
+//
+//  @licend The above is the entire license notice for the JavaScript
+//  code in this page (or file).
+//
+// @source http://linterna-magica.nongnu.org
+
+// END OF LICENSE HEADER
+
+LinternaMagica.prototype.sites["metacafe.com"] = new Object();
+
+// Reference
+LinternaMagica.prototype.sites["www.metacafe.com"] = "metacafe.com";
+
+LinternaMagica.prototype.sites["metacafe.com"].process_extracted_link =
+function(link)
+{
+    // It is set in the extract_link() function.
+    var data = this.extract_link_data;
+
+    if (/flv/i.test(link))
+    {
+       link = link.replace(/&gdaKey/i, "?__gda__");
+    }
+    else
+    {
+       var key_re = new RegExp(
+           link.slice(link.length-15).replace(/\\\./g,"\\\\\\.")+
+               "\\\"\\\,\\\"key\\\"\\\:\\\"([0-9A-Za-z\\\_]+)\\\"",
+           "i");
+       var key = unescape(data).match(key_re);
+
+       // Set the key
+       link = link+"?__gda__="+key[key.length-1];
+    }
+
+    // Escape. We cannot use escape()
+    // because it will break the link and we have to
+    // fix manualy characters like = : ?
+    link = link.replace("[", "%5B").
+       replace(" ", "%20").replace("]", "%5D");
+
+    return link;
+}

Copied: trunk/src/lm_site_mqstocom.js (from rev 156, 
branches/task-11216/src/lm_site_mqstocom.js)
===================================================================
--- trunk/src/lm_site_mqstocom.js                               (rev 0)
+++ trunk/src/lm_site_mqstocom.js       2011-07-26 08:02:40 UTC (rev 157)
@@ -0,0 +1,63 @@
+//  @licstart The following is the entire license notice for the
+//  JavaScript code in this page (or file).
+//
+//  This file is part of Linterna Mágica
+//
+//  Copyright (C) 2010, 2011  Ivaylo Valkov <address@hidden>
+//  Copyright (C) 2010  Anton Katsarov <address@hidden>
+//
+//  The JavaScript code in this page (or file) is free software: you
+//  can redistribute it and/or modify it under the terms of the GNU
+//  General Public License (GNU GPL) as published by the Free Software
+//  Foundation, either version 3 of the License, or (at your option)
+//  any later version.  The code is distributed WITHOUT ANY WARRANTY
+//  without even the implied warranty of MERCHANTABILITY or FITNESS
+//  FOR A PARTICULAR PURPOSE.  See the GNU GPL for more details.
+//
+//  As additional permission under GNU GPL version 3 section 7, you
+//  may distribute non-source (e.g., minimized or compacted) forms of
+//  that code without the copy of the GNU GPL normally required by
+//  section 4, provided you include this license notice and a URL
+//  through which recipients can access the Corresponding Source.
+//
+//  @licend The above is the entire license notice for the JavaScript
+//  code in this page (or file).
+//
+// @source http://linterna-magica.nongnu.org
+
+// END OF LICENSE HEADER
+
+LinternaMagica.prototype.sites["mqsto.com"] = new Object();
+
+// Reference
+LinternaMagica.prototype.sites["www.mqsto.com"] = "mqsto.com";
+
+LinternaMagica.prototype.sites["mqsto.com"].process_extracted_link =
+function(link)
+{
+    // Must be just the path part othe link
+    if (!/^http/i.test(link))
+    {
+       link = "http://mqsto\.com/video/"+link;
+    }
+
+    return link;
+}
+
+LinternaMagica.prototype.sites["mqsto.com"].css_fixes =
+function(object_data)
+{
+    // Move the facebook comment frame in mqsto.com 100px
+    // down. overlaps the player.
+    var move_down_fb_frame = 100;
+
+    object_data.parent.style.setProperty("height",
+                                        (parseInt(object_data.height)+
+                                         26+move_down_fb_frame+
+                                        // borders 1px x 2
+                                        2+
+                                        (this.controls ? 24 : 0))+"px",
+                                        "important");
+
+    return false;
+}

Modified: trunk/src/lm_site_myvideode.js
===================================================================
--- trunk/src/lm_site_myvideode.js      2011-07-26 07:55:44 UTC (rev 156)
+++ trunk/src/lm_site_myvideode.js      2011-07-26 08:02:40 UTC (rev 157)
@@ -66,3 +66,60 @@
 
     return link;
 }
+
+LinternaMagica.prototype.sites["myvideo.de"] = new Object();
+
+// // Reference
+LinternaMagica.prototype.sites["www.myvideo.de"] = "myvideo.de";
+
+// Function reference
+LinternaMagica.prototype.sites["myvideo.de"].flash_plugin_installed = 
"theonion.com";
+
+LinternaMagica.prototype.sites["myvideo.de"].skip_xhr_if_video_id =
+function(object_data)
+{
+    // See the comments for this function. There is no way to access
+    // the video URL via XHR, but there is a pattern to create the
+    // video link
+    object_data.link = this.create_myvideode_link();
+
+    // Now that we have a link remove the video_id
+    // so it is not processed
+    if (object_data.link)
+    {
+       object_data.video_id = null;
+    }
+
+    return object_data ;
+}
+
+LinternaMagica.prototype.sites["myvideo.de"].prepare_xhr =
+function(object_data)
+{
+    var result = new Object();
+
+    result.address = "/watch/"+object_data.video_id+"/";
+
+    return result;
+}
+
+LinternaMagica.prototype.sites["myvideo.de"].process_xhr_response =
+function(args)
+{
+    var object_data = args.object_data;
+    var client = args.client;
+
+    try
+    {
+       var thumb_url = client.responseText.split(/image_src/)[1];
+       thumb_url = thumb_url.split(/\/\>/)[0].split(/\'/)[2];
+
+       object_data.link = this.create_myvideode_link(thumb_url);
+    }
+    catch(e)
+    {
+       return null;
+    }
+
+    return object_data;
+}

Copied: trunk/src/lm_site_reuters.js (from rev 156, 
branches/task-11216/src/lm_site_reuters.js)
===================================================================
--- trunk/src/lm_site_reuters.js                                (rev 0)
+++ trunk/src/lm_site_reuters.js        2011-07-26 08:02:40 UTC (rev 157)
@@ -0,0 +1,71 @@
+//  @licstart The following is the entire license notice for the
+//  JavaScript code in this page (or file).
+//
+//  This file is part of Linterna Mágica
+//
+//  Copyright (C) 2010, 2011  Ivaylo Valkov <address@hidden>
+//  Copyright (C) 2010  Anton Katsarov <address@hidden>
+//
+//  The JavaScript code in this page (or file) is free software: you
+//  can redistribute it and/or modify it under the terms of the GNU
+//  General Public License (GNU GPL) as published by the Free Software
+//  Foundation, either version 3 of the License, or (at your option)
+//  any later version.  The code is distributed WITHOUT ANY WARRANTY
+//  without even the implied warranty of MERCHANTABILITY or FITNESS
+//  FOR A PARTICULAR PURPOSE.  See the GNU GPL for more details.
+//
+//  As additional permission under GNU GPL version 3 section 7, you
+//  may distribute non-source (e.g., minimized or compacted) forms of
+//  that code without the copy of the GNU GPL normally required by
+//  section 4, provided you include this license notice and a URL
+//  through which recipients can access the Corresponding Source.
+//
+//  @licend The above is the entire license notice for the JavaScript
+//  code in this page (or file).
+//
+// @source http://linterna-magica.nongnu.org
+
+// END OF LICENSE HEADER
+
+LinternaMagica.prototype.sites["reuters.com"] = new Object();
+
+// Reference
+LinternaMagica.prototype.sites["www.reuters.com"] = "reuters.com";
+
+LinternaMagica.prototype.sites["reuters.com"].set_video_link_regex =
+function()
+{
+    var result = new Object();
+    result.link_re =  new RegExp (
+       "videoURL=(.*)(\\\&{1})(.*)",
+       "i");
+
+    result.link_position = 3;
+
+    return result;
+}
+
+LinternaMagica.prototype.sites["reuters.com"].css_fixes =
+function(object_data)
+{
+    // Extra height for reuters.com. Otherwise the controlls are
+    // hidden.
+    var extra_height = 100;
+
+    var fourth_parent = object_data.parent.parentNode.parentNode.parentNode;
+    if (fourth_parent)
+    {
+       fourth_parent.style.setProperty("overflow", "visible", "important");
+       fourth_parent.style.
+           setProperty("height", 
+                       (parseInt(object_data.height)+26+
+                        extra_height+
+                        // borders 1px x 2
+                        2+
+                        (this.controls ? 24 : 0)  )+"px",
+                       "important");
+    }
+
+    return false;
+}
+

Modified: trunk/src/lm_site_tedcom.js
===================================================================
--- trunk/src/lm_site_tedcom.js 2011-07-26 07:55:44 UTC (rev 156)
+++ trunk/src/lm_site_tedcom.js 2011-07-26 08:02:40 UTC (rev 157)
@@ -35,11 +35,11 @@
     {
        // Clean the junk
        relative_link = relative_link.replace(/ms|hs|ls/,"").
-           replace(/\"/g,"").replace(":","").replace("=","").
-           replace(",","");
+           replace(/\"/g,"").replace("mp4:","").replace(":","").
+           replace("=","").replace(",","");
 
-       var link = "http://video.ted.com/"+
-           relative_link;
+       var link = "http://video.ted.com/"+relative_link;
+
        return link;
     }
 
@@ -49,13 +49,16 @@
 LinternaMagica.prototype.extract_tedcom_hd_links = function(data)
 {
     var links_re = new RegExp (
-       "(?:\\\&)*\\\w{2}(\\\=|\\\:)*\\\s*(\\\"|\\\')*(.*\\\.flv)(\\\&|\\\",$)",
+       "(?:\\\&)*\\\w{2}(\\\=|\\\:)*\\\s*(\\\"|\\\')*"+
+           "(.*\\\.(flv|mp4))(\\\&|\\\",$)",
        "img");
 
     var links = unescape(data).match(links_re);
 
     if (!links)
-       return;
+    {
+       return false;
+    }
 
     // Work-around for links extracted from <param> of a DOM object
     // There is a problem with generalized regular expression
@@ -79,7 +82,7 @@
        var link = new Object();
 
        link.url = this.create_tedcom_link(links[lnk]);
-       var label = link.url.match(/-(\w+)\.flv/);
+       var label = link.url.match(/-(\w+)\.(flv|mp4)/);
 
        // Make some labels just in case the match does not work
        if (!label)
@@ -90,7 +93,7 @@
        {
            // Capitalize the first letter because it is all lowercase
            // (Low/Hight/Medium)
-           label = label[label.length-1];
+           label = label[label.length-2];
            label = label.slice(0,1).toUpperCase() + label.slice(1);
        }
 
@@ -106,3 +109,64 @@
 
     return null;
 }
+
+LinternaMagica.prototype.sites["ted.com"] = new Object();
+
+// Reference
+LinternaMagica.prototype.sites["www.ted.com"] = "ted.com";
+
+LinternaMagica.prototype.sites["ted.com"].before_options_init = function()
+{
+     // Skip ted.com at the front page. With Gnash installed the flash
+    // object is created. The flashvars attrubute value is 24 KB
+    // (kilo*bytes*) and Firefox and forks block 
+    if(!/[A-Za-z0-9]+/i.test(window.location.pathname))
+    {  
+          this.log("LinternaMagica.sites.before_options_init:\n"+
+                   "Skipping TED front page!"+
+                   " Blocks Firefox and forks.");
+
+       return false;
+    }
+
+    return true;
+}
+
+LinternaMagica.prototype.sites["ted.com"].extract_hd_links_from_dom_if_link =
+function(data)
+{
+    this.log("LinternaMagica.sites.extract_hd_links_from_dom_if_link:\n"+
+            "Trying to extract ted.com HQ links ",1);
+    return this.extract_tedcom_hd_links(data);
+}
+
+LinternaMagica.prototype.sites["ted.com"].extract_hd_links_from_script_if_link 
=
+function()
+{
+    var data = this.extract_link_data;
+
+    this.log("LinternaMagica.sites.extract_hd_links_from_script_if_link:\n"+
+            "Trying to extract ted.com HQ links ",1);
+    return this.extract_tedcom_hd_links(data);
+}
+
+LinternaMagica.prototype.sites["ted.com"].skip_script_processing =
+function()
+{
+    if (this.script_data.length >= 15000)
+    {
+       this.log("LinternaMagca.sites.skip_script_processing:\n"+
+                "Skipping script processing, because it is too big.");
+       // Skip the script is too big and will bloat Firefox
+       return false;
+    }
+
+    return true;
+}
+
+LinternaMagica.prototype.sites["ted.com"].process_extracted_link =
+function(link)
+{
+    link = this.create_tedcom_link(link);
+    return link;
+}

Modified: trunk/src/lm_site_theonion.js
===================================================================
--- trunk/src/lm_site_theonion.js       2011-07-26 07:55:44 UTC (rev 156)
+++ trunk/src/lm_site_theonion.js       2011-07-26 08:02:40 UTC (rev 157)
@@ -28,8 +28,14 @@
 
 // Support for The Onion dot com
 
+LinternaMagica.prototype.sites["theonion.com"] = new Object();
+
+// Reference
+LinternaMagica.prototype.sites["www.theonion.com"] = "theonion.com";
+
 // Extracts data for the flash object in The Onion dot com from a script
-LinternaMagica.prototype.extract_object_from_script_theonion = function()
+LinternaMagica.prototype.sites["theonion.com"].extract_object_from_script =
+function()
 {
     var player_container = document.getElementById("player_container");
 
@@ -141,3 +147,34 @@
     }
 }
 
+LinternaMagica.prototype.sites["theonion.com"].flash_plugin_installed =
+function()
+{
+    // Call the default when no plugin is installed. Examine scripts.
+    this.log("LinternaMagica.sites.flash_plugin_installed:\n",
+            "Calling default function to extract scripts");
+    return this.sites.__no_flash_plugin_installed.apply(this, [arguments]);
+}
+
+LinternaMagica.prototype.sites["theonion.com"].prepare_xhr =
+function(object_data)
+{
+    var result = new Object();
+
+    result.address = "/ajax/onn/embed/"+object_data.video_id+".json";
+
+    return result;
+}
+
+LinternaMagica.prototype.sites["theonion.com"].process_xhr_response =
+function(args)
+{
+    var client = args.client;
+    var object_data = args.object_data;
+
+   var onion_data = eval("("+client.responseText+")");
+    object_data.link = onion_data.video_url;
+    this.capture_theonion_clip_change(object_data);
+
+    return object_data;
+}

Copied: trunk/src/lm_site_tv7bg.js (from rev 156, 
branches/task-11216/src/lm_site_tv7bg.js)
===================================================================
--- trunk/src/lm_site_tv7bg.js                          (rev 0)
+++ trunk/src/lm_site_tv7bg.js  2011-07-26 08:02:40 UTC (rev 157)
@@ -0,0 +1,81 @@
+//  @licstart The following is the entire license notice for the
+//  JavaScript code in this page (or file).
+//
+//  This file is part of Linterna Mágica
+//
+//  Copyright (C) 2010, 2011  Ivaylo Valkov <address@hidden>
+//  Copyright (C) 2010  Anton Katsarov <address@hidden>
+//
+//  The JavaScript code in this page (or file) is free software: you
+//  can redistribute it and/or modify it under the terms of the GNU
+//  General Public License (GNU GPL) as published by the Free Software
+//  Foundation, either version 3 of the License, or (at your option)
+//  any later version.  The code is distributed WITHOUT ANY WARRANTY
+//  without even the implied warranty of MERCHANTABILITY or FITNESS
+//  FOR A PARTICULAR PURPOSE.  See the GNU GPL for more details.
+//
+//  As additional permission under GNU GPL version 3 section 7, you
+//  may distribute non-source (e.g., minimized or compacted) forms of
+//  that code without the copy of the GNU GPL normally required by
+//  section 4, provided you include this license notice and a URL
+//  through which recipients can access the Corresponding Source.
+//
+//  @licend The above is the entire license notice for the JavaScript
+//  code in this page (or file).
+//
+// @source http://linterna-magica.nongnu.org
+
+// END OF LICENSE HEADER
+
+LinternaMagica.prototype.sites["tv7.bg"] = new Object();
+
+// Reference
+LinternaMagica.prototype.sites["www.tv7.bg"] = "tv7.bg";
+
+LinternaMagica.prototype.sites["tv7.bg"].process_extracted_link =
+function(link)
+{
+    // The link is not a full path and is missing a slash.
+    if (!/^http/i.test(link))
+    {
+       link = "/"+link;
+    }
+
+    return link;
+}
+
+LinternaMagica.prototype.sites["tv7.bg"].css_fixes =
+function(object_data)
+{
+    // The CSS rules hide parts of our elements
+    object_data.parent.parentNode.style.
+       setProperty("height",
+                   (parseInt(object_data.height)+26+
+                    // borders 1px x 2
+                    2+
+                    (this.controls ? 24 : 0)  )+"px",
+                   "important");
+
+    object_data.parent.parentNode.style.
+       setProperty("width",
+                   (parseInt(object_data.width+2))+"px",
+                   "important");
+
+    // Fixes height and overflow of the third parent, so the
+    // replacement object is visible.
+    var third_parent = object_data.parent.parentNode.parentNode;
+    if (third_parent)
+    {
+       third_parent.style.setProperty("overflow", "visible", "important");
+       third_parent.style.
+           setProperty("height", 
+                       (parseInt(object_data.height)+26+
+                        // borders 1px x 2
+                        2+
+                        (this.controls ? 24 : 0)  )+"px",
+                       "important");
+    }
+
+
+    return false;
+}

Copied: trunk/src/lm_site_vbox7com.js (from rev 156, 
branches/task-11216/src/lm_site_vbox7com.js)
===================================================================
--- trunk/src/lm_site_vbox7com.js                               (rev 0)
+++ trunk/src/lm_site_vbox7com.js       2011-07-26 08:02:40 UTC (rev 157)
@@ -0,0 +1,57 @@
+//  @licstart The following is the entire license notice for the
+//  JavaScript code in this page (or file).
+//
+//  This file is part of Linterna Mágica
+//
+//  Copyright (C) 2010, 2011  Ivaylo Valkov <address@hidden>
+//  Copyright (C) 2010  Anton Katsarov <address@hidden>
+//
+//  The JavaScript code in this page (or file) is free software: you
+//  can redistribute it and/or modify it under the terms of the GNU
+//  General Public License (GNU GPL) as published by the Free Software
+//  Foundation, either version 3 of the License, or (at your option)
+//  any later version.  The code is distributed WITHOUT ANY WARRANTY
+//  without even the implied warranty of MERCHANTABILITY or FITNESS
+//  FOR A PARTICULAR PURPOSE.  See the GNU GPL for more details.
+//
+//  As additional permission under GNU GPL version 3 section 7, you
+//  may distribute non-source (e.g., minimized or compacted) forms of
+//  that code without the copy of the GNU GPL normally required by
+//  section 4, provided you include this license notice and a URL
+//  through which recipients can access the Corresponding Source.
+//
+//  @licend The above is the entire license notice for the JavaScript
+//  code in this page (or file).
+//
+// @source http://linterna-magica.nongnu.org
+
+// END OF LICENSE HEADER
+
+LinternaMagica.prototype.sites["vbox7.com"] = new Object();
+
+// Reference
+LinternaMagica.prototype.sites["www.vbox7.com"] = "vbox7.com";
+
+LinternaMagica.prototype.sites["vbox7.com"].prepare_xhr =
+function(object_data)
+{
+    var result = new Object();
+
+    result.address ="/play/magare.do";
+    result.method = "POST";
+    result.data = "vid="+object_data.video_id;
+    result.content= "application/x-www-form-urlencoded";
+
+    return result;
+}
+
+LinternaMagica.prototype.sites["vbox7.com"].process_xhr_response =
+function(args)
+{
+    var client = args.client;
+    var object_data = args.object_data;
+
+    object_data.link = client.responseText.split("=")[1].replace("&","");
+
+    return object_data;
+}

Copied: trunk/src/lm_site_videoclipsdumpcom.js (from rev 156, 
branches/task-11216/src/lm_site_videoclipsdumpcom.js)
===================================================================
--- trunk/src/lm_site_videoclipsdumpcom.js                              (rev 0)
+++ trunk/src/lm_site_videoclipsdumpcom.js      2011-07-26 08:02:40 UTC (rev 
157)
@@ -0,0 +1,60 @@
+//  @licstart The following is the entire license notice for the
+//  JavaScript code in this page (or file).
+//
+//  This file is part of Linterna Mágica
+//
+//  Copyright (C) 2010, 2011  Ivaylo Valkov <address@hidden>
+//  Copyright (C) 2010  Anton Katsarov <address@hidden>
+//
+//  The JavaScript code in this page (or file) is free software: you
+//  can redistribute it and/or modify it under the terms of the GNU
+//  General Public License (GNU GPL) as published by the Free Software
+//  Foundation, either version 3 of the License, or (at your option)
+//  any later version.  The code is distributed WITHOUT ANY WARRANTY
+//  without even the implied warranty of MERCHANTABILITY or FITNESS
+//  FOR A PARTICULAR PURPOSE.  See the GNU GPL for more details.
+//
+//  As additional permission under GNU GPL version 3 section 7, you
+//  may distribute non-source (e.g., minimized or compacted) forms of
+//  that code without the copy of the GNU GPL normally required by
+//  section 4, provided you include this license notice and a URL
+//  through which recipients can access the Corresponding Source.
+//
+//  @licend The above is the entire license notice for the JavaScript
+//  code in this page (or file).
+//
+// @source http://linterna-magica.nongnu.org
+
+// END OF LICENSE HEADER
+
+LinternaMagica.prototype.sites["videoclipsdump.com"] = new Object();
+
+// Reference
+LinternaMagica.prototype.sites["www.videoclipsdump.com"] = 
"videoclipsdump.com";
+
+LinternaMagica.prototype.sites["videoclipsdump.com"].prepare_xhr =
+function(object_data)
+{
+    var result = new Object();
+
+    result.address = "/player/cbplayer/settings.php?vid="+
+       object_data.video_id;
+
+    return result;
+}
+
+LinternaMagica.prototype.sites["videoclipsdump.com"].process_xhr_response =
+function(args)
+{
+    var client = args.client;
+    var object_data = args.object_data;
+    var xml = client.responseXML;
+    var path = xml.getElementsByTagName("videoPath")[0];
+
+    if (path)
+    {
+       object_data.link = path.getAttribute("value");
+    }
+
+    return object_data;
+}

Modified: trunk/src/lm_site_vimeo.js
===================================================================
--- trunk/src/lm_site_vimeo.js  2011-07-26 07:55:44 UTC (rev 156)
+++ trunk/src/lm_site_vimeo.js  2011-07-26 08:02:40 UTC (rev 157)
@@ -27,6 +27,11 @@
 
 // END OF LICENSE HEADER
 
+LinternaMagica.prototype.sites["vimeo.com"] = new Object();
+
+// Reference 
+LinternaMagica.prototype.sites["www.vimeo.com"] = "vimeo.com";
+
 // Detect vimeo browser upgrade warning (no flash & h264) .This is
 // called withing setInterval. It is needed because when the elements
 // with the warning are inserted all our data that has been added
@@ -83,7 +88,7 @@
 
 // Extract object data in Vimeo. This makes Firefox and forks to work
 // without plugin and without HTML5 (missing H264)
-LinternaMagica.prototype.extract_object_from_script_vimeo = function()
+LinternaMagica.prototype.sites["vimeo.com"].extract_object_from_script = 
function()
 {
     var player_element_re = new RegExp(
        "player[0-9]+_[0-9]+_element\\\s*=\\\s*"+
@@ -141,3 +146,194 @@
 
     return null;
 }
+
+LinternaMagica.prototype.sites["vimeo.com"].prepare_xhr =
+function(object_data)
+{
+    var result = new Object();
+
+    result.address = "/moogaloop/load/clip:"+object_data.video_id;
+    
+    // Remove cookies and fetch page again. See "A note on
+    // cookies".
+    // this.extract_cookies();
+    // this.expire_cookies();
+
+    return result;
+}
+
+LinternaMagica.prototype.sites["vimeo.com"].process_xhr_response =
+function(args)
+{
+    var object_data = args.object_data;
+    var client = args.client;
+    var xml = client.responseXML;
+
+    var rq_sig = xml.getElementsByTagName("request_signature");
+
+    rq_sig = rq_sig[0].textContent;
+
+    var rq_exp = xml.getElementsByTagName(
+       "request_signature_expires")[0].textContent;
+    var id = xml.getElementsByTagName("video")[0];
+    id= id.getElementsByTagName("nodeId")[0].textContent;
+
+    object_data.link = "http://www.vimeo.com/moogaloop/play/clip:"+
+       id+"/"+rq_sig+"/"+rq_exp+"/?q=sd";
+
+    // Check if there is HD clip
+    var is_hd = xml.getElementsByTagName("isHD");
+    if (is_hd && is_hd[0] && is_hd[0].textContent)
+    {
+       try
+       {
+           is_hd=parseInt(is_hd[0].textContent);
+       }
+       catch(e)
+       {
+           is_hd=0;
+       }
+    }
+
+    // HD links support only for clips that have it
+    if (is_hd)
+    {
+       object_data.hd_links = new Array();
+       var hd_link = new Object();
+
+       // Translate?
+       hd_link.label = "Low quality";
+       hd_link.url = object_data.link;
+       object_data.hd_links.unshift(hd_link);
+
+       hd_link = new Object();
+       // Translate?
+       hd_link.label = "High quality";
+       hd_link.url = object_data.link.replace(/q=sd/, "q=hd");
+       object_data.hd_links.unshift(hd_link);
+    }
+
+    // Vimeo web server sends the clips as
+    // video/mp4. totemNarrowSpace plugin (plays video/mp4)
+    // sends custom UA. This prevents the video to load. Must
+    // use video/flv, so totemCone plugin could start and send
+    // UA of the browser.  totemNarrowSpace/QuickTime plugin
+    // have other issues as well. Could be forced to
+    // video/flv, but there is a better fix in
+    // create_video_object();
+    object_data.mime = "video/mp4";
+
+    return object_data;
+}
+
+LinternaMagica.prototype.sites["vimeo.com"].insert_object_after_xhr =
+function(object_data)
+{
+
+    // Just return true and let the default code do its job. A special
+    // attention is needed when no plugin is installed.
+    if (this.plugin_is_installed)
+    {
+       return true;
+    }
+    
+    if (!this.vimeo_browser_upgrade_timeout)
+    {
+       this.vimeo_browser_upgrade_counter = 0;
+       var data = object_data;
+       var self = this;
+       this.vimeo_browser_upgrade_timeout = setInterval(
+           function() {
+               self.detect_vimeo_browser_upgrade.apply(self,[data]);
+           }, 500);
+    }
+
+    return false;
+}
+
+LinternaMagica.prototype.sites["vimeo.com"].css_fixes = function(object_data)
+{
+    // The thumbnail image overlaps the toggle plugin button after our
+    // changes. This way our button is visible.
+    if (object_data.parent.firstChild)
+    {
+       // The first child should be a div with thumbnail as
+       // background. Reduce it's size so it will not overlap our
+       // button.
+       object_data.parent.firstChild.style.
+           setProperty("height", parseInt(object_data.height)+"px",
+                       "important");
+    }
+
+    // Show HD links list. 
+    object_data.parent.style.
+       setProperty("overflow", "visible", "important");
+
+    object_data.parent.parentNode.style.
+       setProperty("overflow", "visible", "important");
+       
+    // No idea what this fixes.
+    var object_tag = 
+       document.getElementById("linterna-magica-video-object-"+
+                               object_data.linterna_magica_id);
+
+    object_tag.style.setProperty("position","relative","important");
+
+    // Fixes the height of the third parent element.  Fixes
+    // replacement object visibility.
+    var third_parent = object_data.parent.parentNode.parentNode;
+
+    if (third_parent)
+    {
+       third_parent.style.setProperty("overflow", "visible",
+                                      "important");
+       third_parent.style.setProperty("height", 
+                                      (parseInt(object_data.height)+26+
+                                       // borders 1px x 2
+                                       2+
+                                       (this.controls ? 24 : 0)  )+"px",
+                                      "important");
+    }
+
+    // Fixes the height of the fourth parent. Fixes replacement object
+    // visibility.
+    var fourth_parent = object_data.parent.parentNode.
+       parentNode.parentNode;
+
+    if (fourth_parent)
+    {
+       fourth_parent.style.setProperty("overflow", "visible",
+                                       "important");
+       fourth_parent.style.setProperty("height", 
+                                       (parseInt(object_data.height)+26+
+                                        // borders 1px x 2
+                                        2+
+                                        (this.controls ? 24 : 0)  )+"px",
+                                       "important");
+    }
+
+    // Fix displacement of toggle_plugin link/button in vimeo
+    var toggle_plugin = 
+       document.getElementById("linterna-magica-toggle-plugin-"+
+                               object_data.linterna_magica_id);
+
+    if (toggle_plugin)
+    {
+       toggle_plugin.style.setProperty("top",
+                                       parseInt(object_data.height)+10+
+                                       "px", "important");
+    }
+
+    // The CSS rules hide parts of our elements
+    object_data.parent.parentNode.style.
+       setProperty("height", (parseInt(object_data.height)+26+
+                    // borders 1px x 2
+                    2+
+                    (this.controls ? 24 : 0)  )+"px", "important");
+
+    object_data.parent.parentNode.style.
+       setProperty("width", (parseInt(object_data.width+2))+"px",
+                   "important");
+
+    return false;
+}

Modified: trunk/src/lm_site_youtube.js
===================================================================
--- trunk/src/lm_site_youtube.js        2011-07-26 07:55:44 UTC (rev 156)
+++ trunk/src/lm_site_youtube.js        2011-07-26 08:02:40 UTC (rev 157)
@@ -167,9 +167,80 @@
     }
 }
 
+// Extract links data for youtube from fmt_url_map
+LinternaMagica.prototype.extract_youtube_fmt_url_map = function(data)
+{
+    var fmt_re = new RegExp (
+       "(\\\"|\\\'|\\\&)fmt_url_map"+
+           "(\\\"|\\\')*(\\\=|\\\:|,)\\\s*(\\\"|\\\')*"+
+           "([a-zA-Z0-9\\\-\\\_\\\%\\\=\\\/,\\\\\.\|:=&%\?]+)");
 
+    var fmt = data.match(fmt_re);
+
+    if (fmt)
+    {
+
+       // For debug level 1
+       this.log("LinternaMagica.extract_youtube_fmt_url_map:\n"+
+                "Extracted fmt_url_map.",1);
+
+       // Hash with keys fmt_ids and values video URLs
+       var map = new Object();
+
+       // There was unescape here but it broke the split by ,. How it
+       // worked it is not clear. Maybe YT changed something.
+       fmt = fmt[fmt.length-1].replace(/\\\//g, "/");
+
+       fmt = fmt.split(/,/);
+
+       for (var url=0; url<fmt.length; url++) 
+       {
+           // fmt_id|link
+           var m = fmt[url].split(/\|/);
+           map[m[0]] =  m[1];
+       }
+
+       return map;
+    }
+    else
+    {
+       this.log("LinternaMagica.extract_youtube_fmt_url_map:\n"+
+                "No fmt_url_map parameter found. ",1);
+    }
+
+    return null;
+}
+
+LinternaMagica.prototype.sites["youtube.com"] = new Object();
+
+// Reference
+LinternaMagica.prototype.sites["www.youtube.com"] = "youtube.com";
+LinternaMagica.prototype.sites["www.youtube-nocookie.com"] = "youtube.com";
+LinternaMagica.prototype.sites["youtube-nocookie.com"] = "youtube.com";
+
+LinternaMagica.prototype.sites["youtube.com"].set_cookies_domain =
+function()
+{
+    return ".youtube.com";
+}
+
+LinternaMagica.prototype.sites["youtube.com"].skip_link_extraction = function()
+{
+    // Link extraction bloats FF in youtube:
+    // LinternaMagica.extract_link_from_param_list: 
+    // Trying to extract a link from param/attribute "flashvars"
+    // at www.youtube.com time: ***14:58:59:999***
+    // LinternaMagica.extract_link: No link found. at
+    // www.youtube.com time: ***15:12:21:356***
+    this.log("LinternaMagica.sites.skip_link_extraction:\n"+
+            "Skipping link extraction in YouTube. Might bloat "+
+            "GNU IceCat and other forks and versions of Firefox.",4);
+    return false;
+}
+
 // Extracts data for the flash object in youtube from a script
-LinternaMagica.prototype.extract_object_from_script_youtube = function()
+LinternaMagica.prototype.sites["youtube.com"].extract_object_from_script =
+function()
 {
     var data = this.script_data;
     if (!data.match(/var\s*swfConfig/))
@@ -259,46 +330,175 @@
     return object_data;
 }
 
-// Extract links data for youtube from fmt_url_map
-LinternaMagica.prototype.extract_youtube_fmt_url_map = function(data)
+LinternaMagica.prototype.sites["youtube.com"].
+    stop_if_one_extracted_object_from_script =
+function()
 {
-    var fmt_re = new RegExp (
-       "(\\\"|\\\'|\\\&)fmt_url_map"+
-           "(\\\"|\\\')*(\\\=|\\\:|,)\\\s*(\\\"|\\\')*"+
-           "([a-zA-Z0-9\\\-\\\_\\\%\\\=\\\/,\\\\\.\|:=&%\?]+)");
+    this.log("LinternaMagica.sites.stop_if_"+
+            "one_extracted_object_from_script:\n"+
+            "Found one object in YouTube. Stopping script processing",3);
+    return false;
+}
 
-    var fmt = data.match(fmt_re);
+// Just return true or false. The function must be defined, so the
+// default code will not be executed. YouTube's object is created
+// after XHR.
+LinternaMagica.prototype.sites["youtube.com"].
+    replace_extracted_object_from_script = 
+function()
+{
+    return false;
+}
 
-    if (fmt)
+LinternaMagica.prototype.sites["youtube.com"].prepare_xhr =
+function(object_data)
+{
+    var result = new Object();
+
+    var location_href = window.location.href;
+
+    var uri_args = null;
+    // Some clips require &skipcontrinter=1. Other might require
+    // something else.
+    if (/&/i.test(location_href))
     {
+       uri_args = location_href.split(/&/);
+       // This is the host and path (http://...). We do not need
+       // it.
+       delete uri_args[0];
+       uri_args = uri_args.join("&");
+    }
 
-       // For debug level 1
-       this.log("LinternaMagica.extract_youtube_fmt_url_map:\n"+
-                "Extracted fmt_url_map.",1);
+    result.address = "/watch?v="+object_data.video_id+
+       (uri_args ? ("&"+uri_args) : "");
 
-       // Hash with keys fmt_ids and values video URLs
-       var map = new Object();
+    // Remove cookies and fetch page again. See "A note on
+    // cookies".
+    this.extract_cookies();
+    this.expire_cookies();
 
-       // There was unescape here but it broke the split by ,. How it
-       // worked it is not clear. Maybe YT changed something.
-       fmt = fmt[fmt.length-1].replace(/\\\//g, "/");
+    return result;
+}
 
-       fmt = fmt.split(/,/);
+LinternaMagica.prototype.sites["youtube.com"].process_xhr_response =
+function(args)
+{
+    var client = args.client;
+    var object_data = args.object_data;
 
-       for (var url=0; url<fmt.length; url++) 
-       {
-           // fmt_id|link
-           var m = fmt[url].split(/\|/);
-           map[m[0]] =  m[1];
-       }
+    var fmt = this.extract_youtube_fmt_parameter(client.responseText);
+    var maps = this.extract_youtube_fmt_url_map(client.responseText);
 
-       return map;
+    var hd_links = this.create_youtube_links(fmt, maps);
+    object_data.link = hd_links ? hd_links[hd_links.length-1].url : null;
+    object_data.hd_links = hd_links.length ? hd_links : null;
+
+    // See "A note on cookies"
+    if (/restore/i.test(this.process_cookies))
+    {
+       this.restore_cookies();
     }
-    else
+
+    return object_data;
+}
+
+LinternaMagica.prototype.sites["youtube.com"].
+    process_duplicate_object_before_xhr =
+function(object_data)
+{
+    this.log("LinternaMagica.sites.process_duplicate_object_before_xhr:\n"+
+            "Removing/hiding duplicate object ",1);
+
+    this.hide_flash_video_object(object_data.linterna_magica_id,
+                                object_data.parent);
+
+    return false;
+}
+
+LinternaMagica.prototype.sites["youtube.com"].insert_object_after_xhr =
+function(object_data)
+{
+    // Just return true and let the default code do its job. A special
+    // attention is needed when no plugin is installed.
+    if (this.plugin_is_installed)
     {
-       this.log("LinternaMagica.extract_youtube_fmt_url_map:\n"+
-                "No fmt_url_map parameter found. ",1);
+       return true;
     }
 
-    return null;
+    if (!this.youtube_flash_upgrade_timeout)
+    {
+       this.youtube_flash_upgrade_counter = 0;
+       var data = object_data;
+       var self = this;
+
+       this.youtube_flash_upgrade_timeout = setInterval(
+           function() {
+               self.detect_youtube_flash_upgrade.apply(self,[data]);
+           }, 500);
+    }
+    
+    return false;
 }
+
+LinternaMagica.prototype.sites["youtube.com"].css_fixes = function(object_data)
+{
+    if (document.getElementById("playnav-playview"))
+    {
+       // In channels/user pages in YouTube the web controlls are
+       // overlapped by few elements.
+
+       var el =        document.getElementById("playnav-playview");
+       el.style.setProperty("margin-top", "50px", "important");
+
+       var user_nav = document.getElementById("user_playlist_navigator");
+
+       if (user_nav)
+       {
+           user_nav.style.setProperty("overflow", "visible", "important");
+           var height = document.defaultView.getComputedStyle(user_nav).
+               getPropertyValue("height");
+
+           user_nav.style.setProperty("height",
+                                      (parseInt(height)+50)+"px",
+                                      "important");
+       }
+
+       var playnav_body = document.getElementById("playnav-body");
+
+       if (playnav_body)
+       {
+           playnav_body.style.setProperty("overflow",
+                                          "visible", "important");
+
+           // A top border of 1px fixes the top displacement. Why?!
+           var color = document.defaultView.getComputedStyle(user_nav).
+               getPropertyValue("background-color");
+
+           color = color ? color : "#999999";
+
+           playnav_body.style.setProperty("border-top",
+                                          "1px solid "+color,  "important");
+       }
+
+       var playnav_play_content =
+           document.getElementById("playnav-play-content");
+
+       if (playnav_play_content)
+       {
+           var height = document.defaultView.
+               getComputedStyle(playnav_play_content).
+               getPropertyValue("height");
+
+           playnav_play_content.style.
+               setProperty("height",
+                           (parseInt(height)+50)+"px",
+                           "important");
+       }
+    }
+
+     // Bug #33504 https://savannah.nongnu.org/bugs/?33504
+    object_data.parent.style.setProperty("overflow", "visible", "important");
+
+
+    return false;
+}

Copied: trunk/src/lm_sites.js (from rev 156, 
branches/task-11216/src/lm_sites.js)
===================================================================
--- trunk/src/lm_sites.js                               (rev 0)
+++ trunk/src/lm_sites.js       2011-07-26 08:02:40 UTC (rev 157)
@@ -0,0 +1,368 @@
+//  @licstart The following is the entire license notice for the
+//  JavaScript code in this page (or file).
+//
+//  This file is part of Linterna Mágica
+//
+//  Copyright (C) 2011  Ivaylo Valkov <address@hidden>
+//
+//  The JavaScript code in this page (or file) is free software: you
+//  can redistribute it and/or modify it under the terms of the GNU
+//  General Public License (GNU GPL) as published by the Free Software
+//  Foundation, either version 3 of the License, or (at your option)
+//  any later version.  The code is distributed WITHOUT ANY WARRANTY
+//  without even the implied warranty of MERCHANTABILITY or FITNESS
+//  FOR A PARTICULAR PURPOSE.  See the GNU GPL for more details.
+//
+//  As additional permission under GNU GPL version 3 section 7, you
+//  may distribute non-source (e.g., minimized or compacted) forms of
+//  that code without the copy of the GNU GPL normally required by
+//  section 4, provided you include this license notice and a URL
+//  through which recipients can access the Corresponding Source.
+//
+//  @licend The above is the entire license notice for the JavaScript
+//  code in this page (or file).
+//
+// @source http://linterna-magica.nongnu.org
+
+// END OF LICENSE HEADER
+
+// Holds all the site specific config and function
+LinternaMagica.prototype.sites = new Object();
+
+// A function returns false/null, if the calling function should
+// exit/return after this function is executed.  Otherwise it should
+// return true.
+
+// Take an action before options initialisation. This is the
+// earliest position where site-specific action could be
+// taken. The default config is to keep processing.
+//
+// For example, ted.com requires a different approach.
+LinternaMagica.prototype.sites.__before_options_init = function ()
+{
+    return true;
+}
+
+// Take an action when no flash plugin is installed
+LinternaMagica.prototype.sites.__no_flash_plugin_installed = function()
+{
+    this.log("LinternaMagica.sites.__no_flash_plugin_installed:\n"+
+            "Examining scripts.", 4);
+
+    // video.google.* bloats in this function. It takes around 1 min
+    this.extract_objects_from_scripts();
+
+    return true;
+}
+
+// Take an action when flash plugin is installed. For example
+// myvideo.de and theonion.com have custom function.
+LinternaMagica.prototype.sites.__flash_plugin_installed = function()
+{
+    return true;
+}
+
+// Set the domain used to process (expire) cookies. Not required for
+// most sites. See lm_site_youtube.js:set_cookies_domain.
+LinternaMagica.prototype.sites.__set_cookies_domain = function()
+{
+    return true;
+}
+
+// Take an action while processing cookies. This is executed for every
+// cookie object. Duplicates normal cookies processing. Not needed
+// form most sites. It should return a string with domain, path and
+// other values. See lm_site_dailymotion.js:prcoess_cookies.
+LinternaMagica.prototype.sites.__process_cookies = function()
+{
+    return true;
+}
+
+// Used to skip detection (as swf) of iframes. Not used in most
+// sites. See lm_site_dailymotion.js:do_not_force_iframe_detection.
+LinternaMagica.prototype.sites.__do_not_force_iframe_detection =
+function()
+{
+    return true;
+}
+
+// Set the video_id to the returned value and skip extraction from DOM
+// object attributes. The true return value for this default function
+// does not stop extraction. See comments after
+// LinternaMagica.prototype.sites. See
+// lm_site_dailymotion.js:skip_video_id_extraction
+LinternaMagica.prototype.sites.__skip_video_id_extraction = function()
+{
+    return true;
+}
+
+// Take an action if video_id is extracted, but link extraction could
+// not happen with XHR. See lm_site_myvideode.js:skip_xhr_if_id. The
+// true return value for this default function does not stop XHR. See
+// comments after LinternaMagica.prototype.sites.
+LinternaMagica.prototype.sites.__skip_xhr_if_video_id = function(object_data)
+{
+    return true;
+}
+
+// Do not extract video link. The true return value for this default
+// function does not stop link extraction. See comments after
+// LinternaMagica.prototype.sites. See
+// lm_site_youtube.js:skip_link_extraction
+LinternaMagica.prototype.sites.__skip_link_extraction = function()
+{
+    return true;
+}
+
+// Extract HD/HQ links from DOM with site specific function and code if a link
+// is extracted. See
+// lm_site_tedcom.js:extract_hd_links_from_dom_if_link. See comments
+// after LinternaMagica.prototype.sites. See
+LinternaMagica.prototype.sites.__extract_hd_links_from_dom_if_link =
+function(data)
+{
+    return true;
+}
+
+// Extract HD/HQ links from script with site specific function and code if a 
link
+// is extracted. See
+// lm_site_tedcom.js:extract_hd_links_from_dom_if_link. See comments
+// after LinternaMagica.prototype.sites. See
+LinternaMagica.prototype.sites.__extract_hd_links_from_script_if_link =
+function()
+{
+    return true;
+}
+
+// Skip script processing on a condition defined in the function and
+// return value is false (or null or undefined).
+LinternaMagica.prototype.sites.__skip_script_processing = function()
+{
+    return true;
+}
+
+// Extract object data from script
+LinternaMagica.prototype.sites.__extract_object_from_script = function()
+{
+    return true;
+}
+
+// If one video object is found, stop all further searches in scripts.
+LinternaMagica.prototype.sites.__stop_if_one_extracted_object_from_script =
+function()
+{
+    return true;
+}
+
+// Skip video_id extraction (and force it to something) in SWFObject
+// detection and extraction code.
+LinternaMagica.prototype.sites.__libswfobject_skip_video_id_extraction =
+function()
+{
+    return true;
+}
+
+// Create the replacement object. See
+// lm_site_facebook.js:replace_extracted_object_from_script
+LinternaMagica.prototype.sites.__replace_extracted_object_from_script =
+function(object_data)
+{
+    return true;
+}
+
+// Force/set the regular expression used to extract video links to
+// site specific value. Overrides the default one.
+LinternaMagica.prototype.sites.__set_video_link_regex = function()
+{
+    return true;
+}
+
+// Make some changes to or fix/clean an extracted link.
+LinternaMagica.prototype.sites.__process_extracted_link = function(link)
+{
+    return true;
+}
+
+// Extracted links have ampersands (&) in them which are usually
+// parameters for the flash player. Some sites need them. When this
+// function returns false, the cleaning does not occur. See
+// lm_site_google_video.js
+LinternaMagica.prototype.sites.__do_not_clean_amps_in_extracted_link =
+function()
+{
+    return true;
+}
+
+// Force/set the regular expression used to extract video id to
+// site specific value. Overrides the default one.
+LinternaMagica.prototype.sites.__set_video_id_regex = function()
+{
+    return true;
+}
+
+// Execute at the end of the code that removes text and image warnings
+// about missing flash plugin. See
+// lm_site_clipovetecom.js:plugin_install_warning.
+LinternaMagica.prototype.sites.__plugin_install_warning = function(node)
+{
+    return true;
+}
+
+// Run code before changing the checked DOM node to the next one in
+// the loop that removes text and image warnings about missing flash
+// plugin. See lm_site_bliptv.js:plugin_install_warning_loop
+LinternaMagica.prototype.sites.__plugin_install_warning_loop =
+function(node)
+{
+    return true;
+}
+
+// Returns the data needed to fetch a resource that has the video url.
+// Returned object 
+// {
+//     // The URL can be relative to the window.location.host. (required)
+//     address: string,
+//     // The method to be used for the request. (optional)
+//     methog: string,
+//     // The data to be send with the with the xhr.send() request :
+//     // xrh.send(data) (optional)
+//     data: string,
+//     // The Content-Type header to be used for the request. (optional)
+//     content: string,
+// }
+LinternaMagica.prototype.sites.__prepare_xhr = function(object_data)
+{
+    return false;
+}
+
+// Process the XHR response. 
+// Arguments 
+// An object:
+// {
+//     // XHR client object
+//     client: object,
+//     // The object that holds the extracted information about the flash
+//     // object
+//     object_data: object
+// }
+// Return value
+// object_data
+LinternaMagica.prototype.sites.__process_xhr_response =
+function(args)
+{
+    return true;
+}
+
+// Run a function when duplicate object is found (being already processed)
+// before XHR.  The return value does not really matter. The caller
+// function returns null after executing this code.
+LinternaMagica.prototype.sites.__process_duplicate_object_before_xhr =
+function(object_data)
+{
+    return true;
+}
+
+// Add the replacement object overriding the default code i freturn
+// value is false.
+LinternaMagica.prototype.sites.__insert_object_after_xhr = 
function(object_data)
+{
+    return true;
+}
+
+// Add syle and classes to DOM elements for various fixes.The return
+// value does not really matter. The caller function returns null
+// after executing this code. Executed after the replacement object is
+// inserted. CSS classes and DOM ids are accessible.
+LinternaMagica.prototype.sites.__css_fixes = function(object_data)
+{
+    return true;
+}
+
+// Check if site specific config and function exists and call it. If
+// it doesn't, call the general/default function.  A function returns
+// false/null, if the calling function should exit/return after this
+// function is executed. Otherwise it should return true.
+LinternaMagica.prototype.call_site_function_at_position =
+function (position_name, match_site, data)
+{
+    var self = this;
+
+    var debug_level  =  6;
+
+    if (position_name == "process_cookies" ||
+       position_name == "extract_object_from_script" || 
+       position_name == "skip_script_processing")
+    {
+       // These functions are called inside a loop and
+       // prints too much information.
+       debug_level = 7;
+    }
+
+    if (this.sites[match_site])
+    {
+       // Recursion is used to handle references to strings.
+
+       if (typeof(this.sites[match_site]) == "object" &&
+           typeof(this.sites[match_site][position_name]) == "function")
+       {
+           // Defined site and function
+
+           this.log("LinternaMagica.call_site_function_at_position:\n"+
+                    "Calling function "+position_name+
+                    " for site (both site and function defined)",debug_level);
+
+           return this.sites[match_site][position_name].apply(self,[data]);
+       }
+       else if (typeof(this.sites[match_site]) == "object" &&
+                typeof(this.sites[match_site][position_name]) == "string")
+       {
+           // Reference to a function of another site
+
+           var ref_to = this.sites[match_site][position_name];
+
+           this.log("LinternaMagica.call_site_function_at_position:\n"+
+                    "Calling referenced function "+
+                    position_name+" (site defined,"+
+                    " function reference): "+match_site+" -> 
"+ref_to,debug_level);
+
+           return this.call_site_function_at_position.apply(self, [
+               position_name, ref_to, data]);
+       }
+       else if (typeof(this.sites[match_site]) == "string")
+       {
+           // Reference to a another site
+
+           var ref_to = this.sites[match_site];
+
+           // Don't make calls to a reference if it's function is not
+           // defined and the default one will be called anyway.
+           if (typeof(this.sites[ref_to][position_name]) != "undefined")
+           {
+               this.log("LinternaMagica.call_site_function_at_position:\n"+
+                        "Using another site config (reference) for function "+
+                        position_name+": "+match_site+" -> 
"+ref_to,debug_level);
+
+               return this.call_site_function_at_position.apply(self, [
+                   position_name, ref_to, data]);
+           }
+       }
+    }
+
+    // MUST be in separate if block. Don't merge with previous
+    // one. The first if (this.sites[match_site]) will be accessed
+    // before this one.
+    if ((this.sites[match_site] &&
+        !this.sites[match_site][position_name]) ||
+       !this.sites[match_site])
+    {
+       // General-purpose / default function.
+
+       this.log("LinternaMagica.call_site_function_at_position:\n"+
+                "Using default function "+position_name+
+                " (no site specific config)",debug_level);
+
+       return this.sites["__"+position_name].apply(self, [data]);
+    }
+
+    return true;
+}

Modified: trunk/src/lm_xhr.js
===================================================================
--- trunk/src/lm_xhr.js 2011-07-26 07:55:44 UTC (rev 156)
+++ trunk/src/lm_xhr.js 2011-07-26 08:02:40 UTC (rev 157)
@@ -56,123 +56,28 @@
        this.log("LinternaMagica.request_video_link:\n"+
                 "Video with id  "+video_id+
                 " is being processed. Skipping this request."+host,1);
-       if (/youtube\.com/i.test(window.location.hostname) ||
-           /youtube-nocookie\.com/i.test(window.location.hostname))
-       {
-           this.log("LinternaMagica.request_video_link:\n"+
-                    "Removing/hiding duplicate object ",1);
 
-           this.hide_flash_video_object(object_data.linterna_magica_id,
-                                        object_data.parent);
-       }
+       var self = this;
+       var val = this.call_site_function_at_position.apply(self,[
+           "process_duplicate_object_before_xhr",
+           host, object_data]);
 
        return null;
     }
 
-    if (/vbox7\.com/i.test(host))
-    {
-       address ="/play/magare.do";
-       method = "POST";
-       data = "vid="+video_id;
-       content= "application/x-www-form-urlencoded";
-    }
+    var self = this;
+    var val = this.call_site_function_at_position.apply(self,[
+       "prepare_xhr",
+       host, object_data]);
 
-    if (/vimeo\.com/i.test(host))
+    if (val && typeof(val) != "boolean")
     {
-       address = "/moogaloop/load/clip:"+video_id;
-
-       // Remove cookies and fetch page again. See "A note on
-       // cookies".
-       // this.extract_cookies();
-       // this.expire_cookies();
+       address = val.address ? val.address : address ;
+       method = val.method ? val.method : method;
+       data = val.data ? val.data : data;
+       content = val.content ? val.content : content;
     }
 
-    if (/4videosharing\.com/i.test(host))
-    {
-       address = "/player/vConfig.php?vkey="+video_id;
-    }
-
-    // We should not be entering here anyway. It seems most objects
-    // have the mediaURL variable)
-    // if (/metacafe\.com/i.test(host))
-    // {
-    //         address = "/fplayer.php?itemID="+video_id+"&t=embedded";
-    // }
-
-    if (/vbox\.bg/i.test(host))
-    {
-       address = "/extras/player/play.php?id="+video_id;
-    }
-
-    if (/boozho\.com/i.test(host))
-    {
-       address = "/player_playlist.php?v="+video_id;
-    }
-
-    // We have two options:
-    // 1) Use address http://embed.vidoemo.com/player/vidoemo4.php?id=
-    // and extract the flv link, then change &f= parameter fo HD links
-    // 2) Use address http://www.vidoemo.com/videodownload.php?e=
-    // and extract all links and use the FLV (if match as main link)
-    // Links differ in key and path (v3.php -dw  /v7.php -play)
-    if (/vidoemo\.com/i.test(host))
-    {
-       // Using option 2
-       address = "/videodownload.php?e="+video_id;
-    }
-
-    if (/youtube\.com/i.test(host) || 
-       /youtube-nocookie\.com/i.test(host))
-    {
-       var uri_args = null;
-       // Some clips require &skipcontrinter=1. Other might require
-       // something else.
-       if (/&/i.test(location_href))
-       {
-           uri_args = location_href.split(/&/);
-           // This is the host and path (http://...). We do not need
-           // it.
-           delete uri_args[0];
-           uri_args = uri_args.join("&");
-       }
-
-       address = "/watch?v="+video_id +(uri_args ? ("&"+uri_args) : "");
-
-       // Remove cookies and fetch page again. See "A note on
-       // cookies".
-       this.extract_cookies();
-       this.expire_cookies();
-    }
-
-    if (/myvideo\.de/i.test(host))
-    {
-       address = "/watch/"+video_id+"/";
-    }
-
-    if (/dailymotion\.com/i.test(host))
-    {
-       this.extract_cookies();
-       this.expire_cookies();
-       // Forced this way! See lm_extract_dom_objects.js
-       // LinternaMagica.extract_objects_from_dom();
-       address = object_data.video_id;
-    }
-
-    if (/videoclipsdump\.com/i.test(host))
-    {
-       address = "/player/cbplayer/settings.php?vid="+video_id;
-    }
-
-    if (/theonion\.com/i.test(host))
-    {
-       address = "/ajax/onn/embed/"+video_id+".json";
-    }
-
-    if (/blip\.tv/i.test(host))
-    {
-       address="/rss/flash/"+video_id;
-    }
-
     var self = this;
     client.onreadystatechange = function() {
        var client = this;
@@ -186,12 +91,18 @@
        return null;
     }
 
-    address = protocol+"//"+host+address;
+    // Only set the address if it is relative
+    if (!/^http/i.test(address))
+    {
+       address = protocol+"//"+host+address;
+    }
 
     client.open(method,address ,true);
 
     if (content)
+    {
        client.setRequestHeader("Content-Type", content);
+    }
 
     client.send(data);
 }
@@ -211,313 +122,39 @@
        var host = window.location.hostname;
        var url;
        var mime= "video/flv";
-       var xml;
-       var hd_links = new Array();
 
-       if (client.responseXML)
-           xml = client.responseXML;
+       var self = this;
+       var val = this.call_site_function_at_position.apply(self,[
+           "process_xhr_response",
+           host, {client: client, object_data:object_data}]);
 
-       if (/vbox7\.com/i.test(host))
-           url = client.responseText.split("=")[1].replace("&","");
-
-       if (/vimeo\.com/i.test(host))
+       if (!val ||  typeof(val) == "boolean" || (val && !val.link))
        {
-           var rq_sig = xml.getElementsByTagName("request_signature");
-
-           rq_sig = rq_sig[0].textContent;
-
-           var rq_exp = xml.getElementsByTagName(
-               "request_signature_expires")[0].textContent;
-           var id = xml.getElementsByTagName("video")[0];
-           id= id.getElementsByTagName("nodeId")[0].textContent;
-
-           url = "http://www.vimeo.com/moogaloop/play/clip:"+
-               id+"/"+rq_sig+"/"+rq_exp+"/?q=sd";
-
-           // Check if there is HD clip
-           var is_hd = xml.getElementsByTagName("isHD");
-           if (is_hd && is_hd[0] && is_hd[0].textContent)
-           {
-               try
-               {
-                   is_hd=parseInt(is_hd[0].textContent);
-               }
-               catch(e)
-               {
-                   is_hd=0;
-               }
-           }
-
-           // HD links support only for clips that have it
-           if (is_hd)
-           {
-               var hd_link = new Object();
-
-               // Translate?
-               hd_link.label = "Low quality";
-               hd_link.url = url;
-               hd_links.unshift(hd_link);
-
-               hd_link = new Object();
-               // Translate?
-               hd_link.label = "High quality";
-               hd_link.url = url.replace(/q=sd/, "q=hd");
-               hd_links.unshift(hd_link);
-           }
-
-           // Vimeo web server sends the clips as
-           // video/mp4. totemNarrowSpace plugin (plays video/mp4)
-           // sends custom UA. This prevents the video to load. Must
-           // use video/flv, so totemCone plugin could start and send
-           // UA of the browser.  totemNarrowSpace/QuickTime plugin
-           // have other issues as well. Could be forced to
-           // video/flv, but there is a better fix in
-           // create_video_object();
-           mime = "video/mp4";
+           return null;
        }
-
-       if (/4videosharing\.com/i.test(host))
+       else
        {
-           var video_tag = xml.getElementsByTagName("video")[0];
-           url = video_tag.getElementsByTagName("src")[0].textContent;
+           object_data = val;
        }
 
-       // We should not be entering here anyway. It seems most
-       // objects have the mediaURL variable)
-       // if (/metacafe\.com/i.test(host))
-       // {
-       //     // The Content-type is not correct
-       //     xml = (new DOMParser()).
-       //      parseFromString(client.responseText,"application/xml");
-       //     var item = xml.getElementsByTagName("item")[0];
-       //     url = item.getAttribute("url");
-       // }
-
-       if (/vbox\.bg/i.test(host))
+       if (!object_data.mime)
        {
-           url = xml.getElementsByTagName("clip")[0].
-               getAttribute("url");
+           object_data.mime = mime;
        }
 
-       if (/boozho\.com/i.test(host))
-       {
-           var rel_url = xml.getElementsByTagName("movie_path")[0].
-               textContent;
-           url = "http://www.boozho.com/"+rel_url;
-       }
+       var self = this;
+       var val = this.call_site_function_at_position.apply(self,[
+           "insert_object_after_xhr",
+           host, object_data]);
 
-       if (/vidoemo\.com/i.test(host))
+       if (val)
        {
-           var links_re = new RegExp(
-               "\\\<a.*href=\\\"([^\\\"]+).*\\\>Download\\\s*"+
-                   "(.*)\\\s*of\\\s*video",
-               "ig");
-
-           var links;
-           while (links = links_re.exec(client.responseText))
-           {
-               var hd_link = new Object();
-               hd_link.label = links[2];
-               hd_link.url = links[1];
-               hd_links.push(hd_link);
-
-               if (/flv/i.test(hd_link.label))
-               {
-                   url = hd_link.url;
-               }
-           }
-       }
-
-       if (/youtube\.com/i.test(host) ||
-           /youtube-nocookie\.com/i.test(host))
-       {
-           var fmt =
-               this.extract_youtube_fmt_parameter(client.responseText);
-           var maps =
-               this.extract_youtube_fmt_url_map(client.responseText);
-
-           hd_links = this.create_youtube_links(fmt, maps);
-           url = hd_links ? hd_links[hd_links.length-1].url : null;
-           // See "A note on cookies"
-           if (/restore/i.test(this.process_cookies))
-           {
-               this.restore_cookies();
-           }
-       }
-
-       if (/dailymotion\.com/i.test(host))
-       {
-           if (!this.plugin_is_installed &&
-               !object_data.linterna_magica_id && 
-               !object_data.parent)
-           {
-               // In Dailymotion the script that creates the flash
-               // object replaces itself. The work around here is to
-               // request the page and process it. 
-
-               // Dailymotion uses pseudo-random ids for some DOM
-               // elements of interest. We replace the body HTML with
-               // the one returned by the XHR. Then scripts are
-               // processed. The script extraction code matches the
-               // correct ID for the parentNode in DOM, that will
-               // hold the video object. The original body is
-               // restored, because some data is missing in the body
-               // data from XHR. After all data is collected, the
-               // parentNode (object_data.parent), where the video
-               // object will be inserted is replaced with the one in
-               // the original body.  Custom function to match the
-               // parent by CSS class is used, because getElementById
-               // does not support regular expressions.
-
-               var body_data = 
-                   client.responseText.split("<body")[1].
-                   replace(/>{1}/,"__SPLIT__").
-                   split("__SPLIT__")[1];
-
-               var body = document.getElementsByTagName("body")[0];
-               var original_body_data = body.innerHTML;
-
-               body.innerHTML = body_data;
-
-               this.script_data = client.responseText;
-               object_data = this.extract_object_from_script_swfobject();
-
-               body.innerHTML = original_body_data;
-
-               object_data.parent = 
-                   this.get_first_element_by_class("dmpi_video_playerv[0-9]+");
-
-               if (!object_data.parent)
-               {
-                   return null;
-               }
-           }
-
-           hd_links = this.extract_dailymotion_links(client.responseText);
-           url = hd_links ? hd_links[hd_links.length-1].url : null;
-
-           // See "A note on cookies"
-           if (/restore/i.test(this.process_cookies))
-           {
-               this.restore_cookies();
-           }
-       }
-
-       if (/myvideo\.de/i.test(host))
-       {
-           try
-           {
-               var thumb_url = client.responseText.split(/image_src/)[1];
-               thumb_url = thumb_url.split(/\/\>/)[0].split(/\'/)[2];
-               url = this.create_myvideode_link(thumb_url);
-           }
-           catch(e)
-           {
-               return;
-           }
-       }
-
-       if (/videoclipsdump\.com/i.test(host))
-       {
-           var path = xml.getElementsByTagName("videoPath")[0];
-           if (path)
-           {
-               url = path.getAttribute("value");
-           }
-       }
-
-       if (/theonion\.com/i.test(host))
-       {
-           var onion_data = eval("("+client.responseText+")");
-           url = onion_data.video_url;
-           this.capture_theonion_clip_change(object_data);
-       }
-
-       if (/blip\.tv/i.test(host))
-       {
-           // All the data is available in the XML, but it is not a
-           // good idea to support the site in two places. JSON is
-           // easier. The drawback is two requests.
-           try
-           {
-               var embed_id =
-                   xml.getElementsByTagName("embedLookup");
-
-               // Firefox
-               if (embed_id && typeof(embed_id[0]) == "undefined")
-               {
-                   embed_id = 
-                       xml.getElementsByTagName("blip:embedLookup");
-               }
-
-               object_data.video_id = embed_id[0].textContent;
-               this.request_bliptv_jsonp_data(object_data);
-           }
-           catch(e)
-           {
-               this.log("LinternaMagica.prototype.request_video"+
-                        "_link_parse_response:\n"+
-                        "Exception in Blip.tv while parsing XML",1);
-           }
-           return null;
-       }
-
-       if (!url)
-       {
-           return;
-       }
-
-       object_data.link = url;
-       object_data.mime = mime;
-       object_data.hd_links = hd_links.length ? hd_links : null;
-
-       // FIXME HTML5 in WebKit switch like for flash plugin ?
-       // In the next release 0.0.10 ?!
-       if (!/youtube\.com/i.test(window.location.host) &&
-           !/youtube-nocookie\.com/i.test(window.location.host) &&
-           !/vimeo\.com/i.test(window.location.host) ||
-           ((/youtube\.com/i.test(window.location.host) ||
-             /youtube-nocookie\.com/i.test(window.location.host) ||
-             /vimeo\.com/i.test(window.location.host)) &&
-            this.plugin_is_installed))
-       {
            this.log("LinternaMagica.request_video_link_parse_response:\n"+
                     "Removing plugin install warning.",2);
            this.remove_plugin_install_warning(object_data.parent);
            this.log("LinternaMagica.request_video_link_parse response:\n"+
-                    "Creating video object with url: "+url,1);
+                    "Creating video object with url: "+object_data.link,1);
            this.create_video_object(object_data)
        }
-       else if ((/youtube\.com/i.test(window.location.host) ||
-                 /youtube-nocookie\.com/i.test(window.location.host))  &&
-                ! this.plugin_is_installed)
-       {
-           if (!this.youtube_flash_upgrade_timeout)
-           {
-               this.youtube_flash_upgrade_counter = 0;
-               var data = object_data;
-               var self = this;
-               this.youtube_flash_upgrade_timeout =
-                   setInterval(function() {
-                       self.detect_youtube_flash_upgrade.
-                           apply(self,[data]);
-                   }, 500);
-           }
-       }
-       else if (/vimeo\.com/i.test(window.location.host) &&
-                ! this.plugin_is_installed)
-       {
-           if (!this.vimeo_browser_upgrade_timeout)
-           {
-               this.vimeo_browser_upgrade_counter = 0;
-               var data = object_data;
-               var self = this;
-               this.vimeo_browser_upgrade_timeout =
-                   setInterval(function() {
-                       self.detect_vimeo_browser_upgrade.
-                           apply(self,[data]);
-                   }, 500);
-           }
-       }
     }
 }

Modified: trunk/utilities/linternamagica_user_config.user.js
===================================================================
--- trunk/utilities/linternamagica_user_config.user.js  2011-07-26 07:55:44 UTC 
(rev 156)
+++ trunk/utilities/linternamagica_user_config.user.js  2011-07-26 08:02:40 UTC 
(rev 157)
@@ -46,7 +46,7 @@
     "controls": "self",
     "locale": "auto",
     "cookies": "restore",
-    "wait_dm": "off",
+    "wait_xhr": "off",
 };
 
 // Do NOT edit past this line.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]