[转]root完美星空S1机顶盒(亲测)

       前几天装浙江移动宽带送的,软件版本是1.08r。除了阉割得完美其他和完美没有任何关系。具体就是机顶盒没带浏览器,文件浏览器屏蔽U盘上的apk文件,不能通过U盘或网络安装第三方的安卓应用。机顶盒的应用那里没有多媒体中心,而是分开的图像、视频、音乐播放器。应用版面上的其他位置都是游戏的图标,灰色的,实际没有安装也不能安装,只是占据了位置让我们安装了第三方应用也不能显示出来。上网找了下破解方法,发现了部分网友发的老版本的完美星空破解方法都不能用,也没有找到可以刷的ROM,虽然部分省份移动都送这个,用户应该不少,但是生产商貌似非主流,真的找不到合适的ROM,不敢随便乱刷,后来自己机缘巧合找到了个破解方法,不算很完美,但是能满足需求了。

1.准备工作

电脑安装刷机精灵电脑版。其他安卓刷机工具不清楚好不好用,刷机精灵带了ADB工具,所以可以远程连接机顶盒。我没有两头都是公口的USB线,又懒得自己做,所以不能用USB把机顶盒连到电脑上,而采用了局域网内远程连接。

– r! g2 C9 O’ b4 @

( F6 ?9 u2 ]* z3 g0 F7 _, U2.电脑远程连接机顶盒的管理端口

+ _0 V3 H6 K8 `4 h% D0 [       把机顶盒和电脑连接在同一个路由器下面,在机顶盒的设置里确定机顶盒的IP地址,比如我家的是192.168.1.111。打开刷机精灵,在实用工具里打开ADB命令行。

       输入adb connect 192.168.1.111:31015
       解释:该命令让adb连接到 机顶盒的31015端口。各家的完美星空版本不一样可能端口不一样,之前网上看了几个教程有5555、32xxx几个端口的我都连不上,后来我用端口扫描工具nmap扫描了机顶盒开放的所有TCP端口,对每个端口进行连接测试,发现这个端口是可用的管理端口。大家连不上31015端口的自己扫描了去试试别的端口吧。 

! A4 S, A0 b” |1 n2 s, h! ^’ X       输入上面的命令后adb会显示连接成功,英文的,不截图了。

3.确认连接是否成功建立;

! F8 Y* R  r! z- O, O2 u       再输入adb devices

回车后会显示当前adb存在的所有连接,如果显示最后面的是device这个单词表示连上了,如果是offline表示设备端口连上了但是连接未正常建立, 如果你机顶盒版本和我一样,是能成功的。没成功的参考第2步后半部分。

0 K& v” q- w1 _       成功后电视画面上会显示刷机精灵的界面。但是电视遥控操作不了的,不用管。

 

4.ROOT机顶盒

目的是使机顶盒可以安装第三方应用。

& D* e, u: M, b8 ^       用刷机精灵的一键ROOT,我试了大概2次,第一次不知道为什么没成功,成功的话就一下子。

% D6 E  n7 ^1 I! b8 [4 N- h       root后就可以安装第三方安卓软件了。
$ Z8 _4 J3 A* N/ B

8 C/ F% H+ s% m7 T5 \5.安装应用

我个人的需求是安装泰捷和VST来看电视直播,另外装了一个沙发管家。电脑上网下过来泰捷的apk安装文件,改名为tj.apk放到电脑C盘。


1 s7 a& l$ S( b7 F$ ]       adb下输入命令:

, J1 k/ E# [& j1 K” q       adb install c:/tj.apk


; a, r9 g4 w! k  q* v5 }       命令执行后会上传安装包到机顶盒并安装


显示如下:

pkg:/data/local/tmp/st.apk

过会儿显示success,表示安装成功。

那么到这一步为止,我们已经安装上了泰捷视频。任何第三方应用以后都可以这么装上去,可以在机顶盒的/data/app下查看到已安装的app。那么之前说过,这个版本的完美星空S1,在应用那个界面,用灰色的图标把APP的格子都占满了,我们装上去的应用无法在机顶盒的操作界面点击运行,怎么办呢?往下看:

6.准备工作

下载安装7zip、 JDK、 AXMLPrinter2.jar

确认在console下可以运行java

 

7.反编译apk,获得应用包名和程序入口

拿泰捷的安装文件来举例,就是我们之前保存在C盘的tj.apk。

用7z解压tj.apk,在根目录下有个AndroidManifest.xml,是这个app的配置文件。

把AXMLPrinter2.jar跟 AndroidManifest.xml放在同一个目录下,运行:

java -jar AXMLPrinter2.jar AndroidManifest.xml > aaa.xml

 

 

用NotePad打开aaa.xml,在这个文件很上面,一般是第二行,有一个“package=xxxxx”,这个xxxxx就是应用包的名字,比如泰捷是com.togic.livevideo。

再找一下android.intent.action.MAIN和android.intent.category.LAUNCHER这两个字符串,(他们属于同一个Activity)。我们可以看到这个Activity有个android:name属性,它的属性值就是程序入口的Activity名。它有可能是相对路径,比如沙发管家就是 .ShafaHomeAct 表示它的全路径要在前面加上package,就变成了: com.shafa.market.ShafaHomeAct

 

8.运行app

搞清楚package跟 Activity后就简单了,进入adb shell,然后运行:

am start -n {$package_name}/{$activity_name}

比如启动沙发管家:
am start -n com.shafa.market/com.shafa.market.ShafaHomeAct

% k* y# j9 \- {( J/ Y: F运行后就可以在电视上看到沙发管家了!后面想干啥干啥。


9.后期设置

装沙发桌面,在 刷机精灵 中冻结原来的移动自带桌面(考虑到以后可能还要把这机器还原,交还给移动,就不卸载了),这样就只有一个桌面了,然后再在沙发桌面里面设置开机启动。

这样开机后就到沙发桌面了,后面想怎么弄都行。

 

) r& C/ b2 ?# J

[转]移动完美星空S1机顶盒破解教程

以下方法一本人已试验成功,方法二未验证。
方法一 

1.准备工作  电脑安装刷机精灵电脑版。其他安卓刷机工具不清楚好不好用,刷机精灵带了ADB工具,所以可以远程连接机顶盒。我没有两头都是公口的USB线,又懒得自己做,所以不能用USB把机顶盒连到电脑上,而采用了局域网内远程连接。
2.电脑远程连接机顶盒的管理端口  把机顶盒和电脑连接在同一个路由器下面,在机顶盒的设置里确定机顶盒的IP地址,比如我家的是192.168.1.111。打开刷机精灵,在实用工具里打开ADB命令行。          输入adb connect 192.168.1.111:31015  解释:该命令让adb连接到 机顶盒的31015端口。各家的完美星空版本不一样可能端口不一样,之前网上看了几个教程有5555、32xxx几个端口的我都连不上,后来我用端口扫描工具nmap扫描了机顶盒开放的所有TCP端口,对每个端口进行连接测试,发现这个端口是可用的管理端口。大家连不上31015端口的自己扫描了去试试别的端口吧。  输入上面的命令后adb会显示连接成功,
3.确认连接是否成功建立  再输入adb devices  回车后会显示当前adb存在的所有连接,如果显示最后面的是device这个单词表示连上了,如果是offline表示设备端口连上了但是连接未正常建立, 如果你机顶盒版本和我一样,是能成功的。没成功的参考第2步后半部分。

4.ROOT机顶盒  目的是使机顶盒可以安装第三方应用。  用刷机精灵的一键ROOT,我试了大概2次,第一次不知道为什么没成功,成功的话就一下子。  root后就可以安装第三方安卓软件了。  如果一直root不成功,也可以继续下面的步骤。

5.安装应用  网上搜索“沙发桌面”,是安卓系统的应用文件,apk格式的。  下载后改名sf.apk放到电脑C盘根目录。  adb下输入命令:  adb install c:/sf.apk  命令执行后会上传安装包到机顶盒并安装  显示如下:xx kb/s        pkg:/data/local/tmp/sf.apk  过会儿显示success,表示安装成功。         那么到这一步为止,我们已经安装上了应用文件。任何第三方应用以后都可以这么装上去,可以在机顶盒的/data/app下查看到已安装的app。那么之前说过,这个版本的完美星空S1,在应用那个界面,用灰色的图标把APP的格子都占满了,我们装上去的应用无法在机顶盒的操作界面点击运行,怎么办呢?怎么把它运行起来呢,下面如此:
 6.准备工作  百度下,下载安装JDK,这个是java运行环境,apktool要用的。下载apktool,这个是反编译apk的工具。注意!!请自行查看apktool的教程,按照要求设置jdk的系统环境变量。具体不说了,网上教程都是。什么都写我也没精力。

7.反编译apk,获得应用包名和程序入口  安装完JDK,设置完环境变量,就可以运行apktool反编译sf.apk,就是我们之前保存在C盘的。具体请自己仔细阅读百度到的教程,非常简单,很多人其实怕的只是“陌生”而已。在反编译获得的文件夹根目录下有个AndroidManifest.xml,是这个app的配置文件。用NotePad打开,(我用的是NotePad这个软件,估计很多文件软件都能打开正常显示吧),在这个文件很上面,一般是第二行,有一个“package=xxxxx”,这个xxxxx就是应用包的名字,在找一下android.intent.action.MAIN和android.intent.category.LAUNCHER这两个字符串,他们属于同一个Activity,我们可以看到
这个Activity有个android:name属性,它的属性值就是程序入口的Activity名。这段打了很多字,但是对有些朋友看来还不是很清楚,麻烦你们自己稍微花点时间弄弄明白,不在家里没法截图,回头我抽空补上吧,先凑合。  这样我们就得到了sf.apk的在系统中的应用包名称和应用包启动名(就是Activity名)
8.运行app  在已经用第2步的方法连上机顶盒管理端口的情况下,  在adb下输入命令:  adb shell  就获得了机顶盒的操作系统的shell命令执行权限,进入了机顶盒的shell环境。shell环境的的#后面可以输入命令,  输入am start -n 应用包名/入口Activity名  就可以运行app了。  比如沙发桌面的就是  am start -n com.safa.livevideo/com.safa.launcher.SplashActivity  (名称可能有不同,以你得到了sf.apk的在系统中的应用包名称和应用包Activity名为准)  运行后就可以在电视上看到启动起来的沙发桌面!

这个时候我们就可以进行一些常规的操作了,千万先不要重新启动,要先删除系统自带的几个应用程序,没有root的先下载root程序安装,可以插入U盘正常安装任意的程序了,在沙发桌面上可以操作。  让沙发桌面成为唯一的一个桌面应用程序后,下次开机就进入的是沙发桌面了。

 

现在你的盒子就完全不是定制机了,和市面上买来的一样了。可以自由安装和删除程序。  这个教程的本质就是启动一个另外的桌面程序,避开本来设了种种限制的桌面程序,重新让我们掌控我们的盒子。

方法二: 
还有一种更加简单的方法,插入无线键盘与鼠标,开机后按WIN+B键,就会打开浏览器,接下去就想装什么都行了。注意:安装的软件一定要设置一个为开机启动。

天猫魔盒无损阻止升级(20131121版本),给已经root的朋友

前置条件:
一。目前确认的可行版本为20131121
二。确认可以正常取得了root权限
三。有windows版本的adb包

方法A:

一。 遥控器查看,设置\网络\IP地址 (如果已经提示升级也没有关系,按遥控器主页键回到桌面,然后查看IP地址,千万不能确认升级)

二。在能连通猫的电脑上进入adb 目录(或把adb设置在path中)操作一下命令。

1. adb.exe connect  你盒子的IP:5555

2. adb shell

3. su (在盒子的界面里面确认给予root权限)

4. rm -f /cache/osupdate/com.yunos.osupdate.FOTA_UPDATE/*

5. chmod 000 /cache/osupdate/com.yunos.osupdate.FOTA_UPDATE

6. reboot

OK, 盒子提示“下载出错”。

恢复升级功能:

1.adb.exe connect  你盒子的IP:5555
2.adb shell
3.su
4.chmod 700 /cache/osupdate/com.yunos.osupdate.FOTA_UPDATE
5.reboot

OK, 盒子可以正常升级。

 

 

 

 

方法B:

编辑hosts文件,在里面输入,遥控器输入很费劲,建议直接用天猫手机遥控器输入“127.0.0.1 osfota.cdn.aliyun.com”

[转] 终于将1.70强行root了(TTL)

最近搞了个5.1,原以为可以passthrough,用功放解码DTS,发现希望落空,于是只能通过root。但是发现升级了1.7,查遍网络都没有可用的root方法。但是看到网上有人说居然有ttl,于是今天搞了一把,虽然走了不少弯路,但是搞定了!
注意,以下所述全部建立在拆机连接TTL的前提下!
TTL接线序:GND Tx Rx VCC

下面说一下个人觉得最简便的方法:
由于从ttl进去天猫魔盒后,默认便是root用户,所以可以直接刷ctk-recovery,论坛上都有,不细讲。

  1. flash_image recovery recovery.img
  2. reboot recovery

然后在讲一下我的折腾过程,相当曲折。
进ttl后发现直接就是root,于是想走捷径,直接将su和superuser.apk放到系统中不就成了?
于是mount -o remount,rw /dev/block/system /system 将系统盘挂载为可读写。
但是这时候发现,xx的居然在system/bin和xbin下有一个叫su的文件夹,权限不对,想删掉不行,而且后来在init.rc中发现有启动时创建su文件夹的script,想改掉除非重新编译boot。
于是这一条路走不通,也试过mount bind的方法,但是superuser不吃这一套,直接提示找不到su二进制。

于是看到1.6短接的方法,各种大大都说1.7不能用这套,于是就放弃。手边也有spi flash烧录工具,就想既然短接没用,我烧进去还不行么。于是动手,处于保险考虑,先将flash dump出来。然后开烧,结果烧完检验不通过,n次尝试都失败,顿时冷汗!变砖了,uboot挂了!

死马当活马医,用那个短接工具做了启动盘,插上TF后真能启动,但是却说找不到环境变量,停在了USBBurn Mode。

更换为我备份的那个4M大小的u-boot.bin后,正常启动。
然后启动是不停按Enter,进入uboot CLI。使用以下命令

  1. mmcinfo     <– 此命令一定要运行,看短接教程里面的那个script似乎没有这条命令,真不知道是怎么成功的
  2. fatload mmc 0:1 82000000 recovery.img
  3. bootm 82000000

启动到ctk-recovery,刷机,拿root权限,此时已经相当easy。

uboot挂了,总不能一直用mmc启动吧,查了网络,终于找到了uboot的烧写命令,如下:

  1. m6_mbx_g32#mmcinfo
  2. sdio_detect return 1
  3. Device: SDIO Port B
  4. Manufacturer ID: 0
  5. OEM: 0
  6. Name: Tran Speed: 40000000
  7. Rd Block Len: 512
  8. SD version 2.0
  9. High Capacity: Yes
  10. Capacity: 16007561216
  11. Boot Part Size: 0
  12. Bus Width: 4-bit
  13. m6_mbx_g32#fatload mmc 0:1 82000000 uboot.bin
  14. reading uboot.bin
  15. 4194304 bytes read
  16. m6_mbx_g32#sf probe 2
  17. SPI NOR Flash NO write protect!!!, So I will enable it…
  18. 4096 KiB S25FL032A at 0:2 is now current device
  19. m6_mbx_g32#sf erase 0 400000
  20. m6_mbx_g32#sf write 82000000 0 400000
  21. m6_mbx_g32#reset

拔掉TF卡,成功启动。

完~

天猫魔盒2.1 root(降级到1.7)

以下都为转载,非本人原创,转自YUNOS论坛
天猫魔盒降级方法
声明:次教程仅适合 tmb100a tmb100c tmb100e 用户,V2.1系统!由于降级须带电短接,所以有风险,后果自负,实施请谨慎!
1. 下载FOXROM recovery包

2. 制作SD卡
解压Recovery包,“启动卡制作工具”目录里面会有4个文件:

把SD卡接入电脑,打开SDcardMaker.exe,选择sd卡对应的盘符(注意:如果这里不能选择盘符,请关闭后用管理员身份重新运行SDcardMaker.exe)


选择解压目录下uboot.bin文件,点击“制作启动卡”
按顺序,选择“开始”或“确认”按钮,直至制作完成:


然后把解压目录下的其他的recovery.img文件拷贝到此sd卡中!
3. 下载天猫魔盒V1.7rom:
然后把下载的ROM文件拷贝到此sd卡中,并改文件名为update.zip
4. 把魔盒拆开,并把SD卡插入魔盒


5. 断电,开始短接
TMB100E短接图:

TMB100A短接图:


TMB100C短接图:


6. 上电5秒后停止短接,盒子会自动进入FOXROM-recovery界面。依次选择最后两项进行双清:


7. 然后选择“apply update from EXT”


8. 接着选择SD目录下的”update.zip”,并选择“YES”


9. 等待一会儿更新完毕后,选择’YES’重启盒子,恭喜你从V2.1降级到V1.7 rooted版了!

刚刚亲测成功,刷机需要一定的安卓刷机经验,希望各位盒子爱好者多多交流,不要发一些没有意义的回复,谢谢!~~
天猫魔盒V2.1降级方法.apk 远程安装当贝市场 (7.47 MB, 下载次数: 230) 教程原版,后缀名改为docx即可

有几位盒友说刷入不成功,第一:看看短接时间是否正确。第二:换个储存卡试试,不要硬刷,慢慢来。
成砖的请自行查找救砖帖

使用GWT的第一个程序

source: http://blog.csdn.net/qq7342272/article/details/6924065

 

今天头一次接触GWT写了一个welcome页面,感觉GWT不是特别难。只不过缺点是没有中文的API哭  (我也不懂英文,,肿么办?  google翻译呗。。)  还有刚刚编译的时候死慢。。 不过修改代码后直接刷新页面后就可以看到新的效果了。对于这点洒家还是比较满意的。生气至少不用每次都经过漫长的编译过程。。  好了不多说废话了。下面就开始我们的GWT之旅。

第一步

1、eclipse 我的是3.7

2、eclipse插件

至于怎么安装ecli[se我就不说了 百度一搜一堆

下面说说具体怎么装gwt的插件。

1、安装eclipse的GWT插件:打开eclipse–help–Insall New Software  点击Add 然后填写Name(这个随便了。。我写的是GWT)Location写http://dl.google.com/eclipse/plugin/3.7填写后点击确定出现一堆要选择的插件。。具体选哪个我也不晓得 只能全选上了- –  点击Next然后等待漫长的下载。。

2、安装GWT的SDK:这个需要去google自行下载了。。。要根据eclipse的版本去下载。  这个是地址:http://code.google.com/intl/zh-CN/eclipse/docs/download.html 可以用google浏览器翻译成中文。。  google浏览器对不懂英语的童鞋是一大福利啊。下载后解压任意目录。。

3、下载GWT的插件:GWT的插件需要有WST插件的支持,可以到eclipse官方下载WST插件。下载完成后把zip中的features和plugins子目录解压到eclipse的安装目录的dropins目录即可。

4、配置:以上工作完成后,启动eclipse程序 选择windows–Perferences菜单 弹出Perferences对话框 咱开google–Web Toolkit配置节点点击Add 弹出添加SDK对话框,输入SDK解压目录 然后给SDK起一个唯一的名称

点击OK 重启eclipse

—————————华丽的分割线———————————–

到这里gwt的插件已经配置完成了。

下面我们做gwt的第一个程序。

安装完成后eclipse的工具栏会多出几个gwt的工具。 如图

选择那个蓝色的 google Development Tools–New Web Appliction Project 新建gwt项目

然后项目名啊 包名啊什么的就不说了 直接finish完成

删除src下client下的GreetingService.java、GreetingServiceAsync.java和server目录

war下的web.xml中servlet和servlet-mapping也要删除

打开war目录下的WelcomeGwt.html 简化成一个普通的html文件

注意 里面有个javascript的引用,这个不需要删除。

打开src–zhy–client下的welcomeGwt.java删除所有内容(清空类内的所有代码)编写代码

  1. package zhy.client;
  2. import com.google.gwt.core.client.EntryPoint;
  3. import com.google.gwt.event.dom.client.ClickEvent;
  4. import com.google.gwt.event.dom.client.ClickHandler;
  5. import com.google.gwt.user.client.Window;
  6. import com.google.gwt.user.client.ui.Button;
  7. import com.google.gwt.user.client.ui.RootPanel;
  8. public class WelcomeGwt implements EntryPoint {
  9.     //这个是页面加载时执行的代码
  10.     @Override
  11.     public void onModuleLoad() {
  12.         Button btn=new Button(“我的第一个GWT按钮”);  //新建一个按钮
  13.         //给按钮添加单击事件
  14.         btn.addClickHandler(new ClickHandler() {
  15.             @Override
  16.             public void onClick(ClickEvent event) {
  17.                 Window.alert(“你好”);//调用windows的弹窗
  18.             }
  19.         });
  20.         RootPanel.get().add(btn);  //把按钮添加到页面中
  21.     }
  22. }

 

点击Run As 选择Run As–Web Appliction启动

然后就是漫长的编译过程 eclipse输出这个的时候 右键 open

自己可以配置一下eclipse的默认浏览器。  我选的是google

到这里就完成第一个gwt程序了。 后续继续更新gwt其他的文章  觉得好的话就赞一下吧。。 一步一步的截图 打字 好累的说。。。

Empty image src can destroy your site

Empty image src can destroy your site
Posted at November 30, 2009 11:20 am by Nicholas C. Zakas
Tags: HTML, PHP, Web Development
This is a problem I’ve come across frequently, and since it has come up again recently, I thought I’d explore this issue in the hope that it will save others some trouble. There are so many problems that this one issue can lead to that it’s baffling browsers still behave this way. The issue? An HTML image, either via <img> tag or JavaScript Image object, that has its src set to “” (an empty string).

The offending code

There are basically two patterns to identify. The first pattern is just straight HTML:

<img src=”” >
The second pattern is JavaScript and involves the dynamic setting of the src property on either a newly created image or an existing one:

var img = new Image();
img.src = “”;
Both patterns cause the same effect: another request is made to your server. There are two different ways that browsers do this.

Internet Explorer makes a request to the directory in which the page is located. For example, if you have a page running at http://www.example.com/dir/mypage.htm that has one of these patterns, IE makes a request to http://www.example.com/dir/ to fill in the image.
Safari and Chrome make a request to the actual page itself. So the page running at http://www.example.com/dir/mypage.htm results in a second request to http://www.example.com/dir/mypage.htm to fill in the image.
You’ll note that Opera and Firefox aren’t mentioned at all. Opera behaves as you might expect: it doesn’t do anything when an empty image src is encountered; the attribute is ignored. Firefox 3 and earlier behave the same as Safari and Chrome, but Firefox 3.5 addressed this issue and no longer sends a request (related bug).

Both cases, of course, are problematic because it’s an image making a request for a document. You can easily see this behavior using an HTTP debugging proxy (I highly recommend Fiddler).

The problems

There are two basic problems that this browser behavior causes. The first is a traffic spike. Imagine that have <img src=””> on the page at http://www.example.com/. The big problem is that each instance of <img src=””> makes a request to / in all browsers, which is the homepage of the domain. Congratulations, you’ve effectively doubled your traffic to the homepage.

For small sites, this may not be that big of a deal; jumping from 10,000 to 20,000 page views probably isn’t going to raise any flags for you or your host. If you’re a page that gets millions of page views per day, and probably have a lot of machines to handle that load, doubling or tripling traffic can be crippling. You can very easily run out of capacity.

Another issue with the traffic increase is the computing power needed to generate that homepage. If the page is personalizable or is updated with some regular frequency, you could be wasting computing cycles creating a page that will never be viewed by anyone.

The second problem is user state corruption. If you’re tracking state in the request, either by cookies or in another way, you have the possibility of destroying data. Even though the image request doesn’t return an image, all of the headers are read and accepted by the browser, including all cookies. While the rest of the response is thrown away, the damage may already be done.

How does this code happen?

The first time I encountered this problem, I naively thought that it was a bad developer writing crappy code. Had this been 2000 or earlier, I probably would have been right. In today’s web development world, however, I’m mostly wrong. Today, there are so many templating engines and content management systems responsible for constructing pages on-the-fly that it’s quite possible for good developers to end up producing pages with this code. All it takes is something as simple as this PHP:

<img src=”$imageUrl” >
If some other part of the code is responsible for filling in $imageUrl, and that code fails, then the offending code gets output to the browser.

In today’s web development world, we’re all doing something along these lines, whether we know it or not. Download a new WordPress theme? Make sure you’ll filled in all default arguments. Using a CMS at work? Make sure all your image URL fields are validated. It’s frightening easy to end up with this bad code on your page.

Other tags with problems

Before getting too angry at browser vendors, I think it’s fair to take a look at the HTML 4 specification, specifically the part defining images. Even though the specification indicates that the src attribute should contain a URI, it fails to define the behavior when src doesn’t contain a URI. Of course, images aren’t the only tags that reference an external resource, and so it should come as no surprise that there are other tags with the same problem.

As it turns out, Internet Explorer is the most sane browser out there. It’s problems are thankfully limited to images with an empty src attribute. It does make for this by making it a pain to detect, but that will be discussed later.

For other browsers, there are two additional problem scenarios: <script src=””> and <link href=””>. Chrome, Safari, and Firefox all initiate another request.

Thankfully, no browser has a problem with <iframe src=””>, as all correctly do not make another request.

What can be done?

Of course, the best thing to do is eliminate the offending code from your pages whenever possible. That’s fixing the problem at the source. If you can’t do that, though, your next best option is to attempt to detect it on the server and abort any further execution.

For browsers other than IE, it’s not too difficult to detect what’s going on from the server side. Since the request comes back to the exact same location that contains the offending code, there are two things you can do. First, you can check the request’s referrer. A request resulting from this issue coming from http://www.example.com/dir/mypage.htm will have a referrer of http://www.example.com/dir/mypage.htm. Assuming that there are no valid situations under which your page links to itself, this is a fairly safe way to detect these requests on the server-side.

Internet Explorer throws a wrench into the works by sending the request to the directory of the page instead of the page itself. If you’re only using path URLs (i.e., nothing with a file extension), then the effect is the same and you can use the same referrer detect. Some sample code for use with PHP:

<?php
//Works for IE only when using path URLs and not file URLs

//get the referrer
$referrer = isset($_SERVER[‘HTTP_REFERER’]) ? $_SERVER[‘HTTP_REFERER’] : ”;

//current URL (assuming HTTP and default port)
$url = “http://” . $_SERVER[‘HTTP_HOST’]Â . $_SERVER[‘REQUEST_URI’];

//make sure they’re not the same
if ($referrer == $url){
exit;
}
?>
The goal here is to detect that the page refers to itself and then exit immediately to prevent the server from doing anything additional. Another option, and probably a good idea, is to log that this has happened so it shows up on a dashboard for evaluation.

Another way to attempt to detect this type of request on the server is by looking at the HTTP Accept header. All browsers except IE send different HTTP Accept headers for image requests than they do for HTML requests. As an example, Chrome sends the following Accept header for an HTML request:

Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Compare this to the Accept header that is sent for an image, script, or style sheet request:

Accept: */*
Firefox, Safari, and Opera all send roughly the same Accept header for HTML requests, meaning that you can check for an individual part, such as “text/html”, to determine if the request is an HTML request or something else. Unfortunately, IE only sends the latter Accept header for all requests, so there is no way to differentiate this on the server. For browsers other than IE, you can use something like the following:

<?php
//Warning: Doesn’t work for IE!

//make sure the Accept header has ‘text/htmnl’ in it
if (strpos($_SERVER[‘HTTP_ACCEPT’], ‘text/html’) === false){
exit;
}
?>
This check is a little safer than the previous, but its big downside is that it doesn’t work in IE.

Why does this happen?

The real problem is the way that URI resolution is performed in browsers. This behavior is defined in RFC 3986 – Uniform Resource Identifiers. When an empty string is encountered as a URI, it’s considered a relative URI and is resolved according to the algorithm defined in section 5.2. This specific example, an empty string, is listed in section 5.4. Firefox, Safari, and Chrome are all resolving an empty string correctly per the specification, while Internet Explorer is resolving it incorrectly, apparently in line with an earlier version of the specification, RFC 2396 – Uniform Resource Identifiers (this was obsoleted by RFC 3986). So technically, the browsers are doing what they’re supposed to do to resolve relative URIs. The problem is that in this context, the empty string is clearly unintentional.

It’s time to fix this

This is a serious flaw in browsers, and I’m not sure you can look at it in any way where it’s not considered a bug. The inconsistent behavior, from Opera completely ignoring all invalid external references, to IE falling victim only for <img> tags while others do the same for <script> and <link> as well, seem to indicate a bug in browsers. Though browsers seem to be following correct URI resolution (except IE), I think this is a case where common sense must win over the letter of the specification. There is no way that an image can possibly render an HTML page, and the same goes for <script> and <link>. This bug has cost web developers hundreds of lost hours and has potentially brought down sites, pushing servers over capacity. Enough is enough. It’s time for the browser vendors to fix this bug. I’ve taken the liberty of filing or locating bugs:

Firefox: Bug 531327
WebKit (Safari/Chrome): Bug 30303
Please show support for fixing these bugs, as I don’t see any reason why we should still be dealing with this browser behavior. And if anyone can get the note to Microsoft so they can address IE, we’d all greatly appreciate it.

HTML5 to the rescue

HTML5 adds to the description of the <img> tag’s src attribute to instruct browsers not to make an additional request in section 4.8.2:

The src attribute must be present, and must contain a valid URL referencing a non-interactive, optionally animated, image resource that is neither paged nor scripted. If the base URI of the element is the same as the document’s address, then the src attribute’s value must not be the empty string.

Hopefully, browsers won’t have this problem in the future. Unfortunately, there is no such clause for <script src=””> and <link href=””>. Maybe there’s still time to make that adjustment to ensure browsers don’t accidentally implement this behavior.

Update (2 Dec 2009): It appears that <img src=””> has been patched in Firefox 3.5 (bug 444931). Problems with <script src=””> and <link href=””> still remain. Also, added a reference to the HTML5 section that aims to help this issue.

Disclaimer: Any viewpoints and opinions expressed in this article are those of Nicholas C. Zakas and do not, in any way, reflect those of my employer, my colleagues, Wrox Publishing, O’Reilly Publishing, or anyone else. I speak only for myself, not for them.