Archive

Archive for April, 2007

Yahoo!相册上传会产生重复图片问题的解决

April 6th, 2007 Fwolf No comments

注:本文的内容将适度超越标题范围,不过我仍然认为这个标题是合适滴,就是内容有些碎碎念。

目前的网上免费相册,不可以外链但是可以大容量长期存储的,不限制图片数量的,基本上就是雅虎和网易两家了,网易的由于只有windows版的客户端上传工具,所以没怎么用,最近登录过几次,觉得网易也疏于打理。雅虎相册倒是从一开始就在用,每个相册最多300张图片,单张图片不能超过5M,只能上传jpg文件,这些限制对我来说都能接受,FF上传插件当然是好用得没话说了,更主要的是它的超大容量。

最开始的时候我也和很多人一样以为雅虎相册是无限空间的,直到有一天,我的照片无法上传了,总是因为未知的原因上传失败,于是给雅虎去信询问(2006年12月),回信如下: 关于雅虎相册的第一次邮件交流

除了指出邮件有4G空间限制以外,居然建议我申请新的yahoo帐号,这是最让我气愤的,这次邮件交流往回了十几次,甚至雅虎还说要给我打电话,但我中间出差一次,后来就再也没有消息了。把帐号改成英文美国帐号的话也不行,显示一个mdb的什么错误。不久前想起来这事情,记得以前在雅虎相册用户交流论坛上的管理员凤凰播报员曾经说过雅虎相册会改版,改版之后我帐号的问题也许就能解决了,他是这么说的(原帖):

看来目前解决问题只有一个方法了,就是要重新申请一个ID,因为有一批老用户的邮箱并非无限容量,已经达到最大上限了,这个问题要等到我们下次改版时方可解决!要是着急上传还是继续注册一个吧,给您带来的不便请谅解!

不过至少让我明确了两个问题:

  • 雅虎相册是无限容量(这个是我当时的错误认识)
  • 老用户有限制,需要等改版

于是我等了几个月之后,又向雅虎发邮件询问(2007年3月),这次换了个客服,也没有建议我注册新ID,不过更加明确了4G的空间限制: 关于雅虎相册的第二次邮件交流

同时我也发现,雅虎帮助中的说明也没有说是无限空间,只是说:

雅虎相册为您提供免费的、超大的储存容量,因此雅虎相册对保存的照片总数或在该帐户建立的专辑总数是没有限制的。但是该帐户下的每一个专辑里储存的照片数最多不能超过300张,上传的单张照片最大不能超过5M。

有图为证,免得他们以后改版反悔: 雅虎相册帮助中对于空间的说明

我这才彻底失望,但同时也发现英文Yahoo!的相册和中文雅虎的不一样,也许根本就不是一个公司、一班人马运作的,或许英文Yahoo!能好些?这次我先仔细得查看英文Yahoo! Photos关于空间的帮助,这个说得很明确,是无限(We offer free, unlimited storage!)的,只是在上传的时候有一些程序上的限制,同样以图为证: 英文Yahoo! Photos关于空间容量的说明

同时英文Yahoo!相册的使用也有两个限制:

  • 每个相册下面最多只能放300张图片,和中文版是一样的
  • 每天上传的图片数量有限制,尤其是2-5M这样比较大的图片,但具体数字没有公开

英文Yahoo!相册和中文版一样,也提供了一个FF下使用的上传控件,并且相册的管理界面非常非常AJAX(这也是后来我遇到的难点部分),空间的问题暂时不用考虑,即使仍然有那4G的限制,一时也达不到,不过仍然有个小问题,就是用上传工具上传的图片总是出现重复!在上传的时候显示有的Failed有的Success,上传完一看图片倒是全部都传上去了,就是重复的很多,大概是重试的结果。

英文Yahoo!相册没有对相册内照片自动排序的功能,没有自动去除那些重复的多余照片的功能,看来要想用得舒心,还要自己下功夫,利用我的老方法,用js来协助删除重复的照片。本来还想把排序作出来的,不过在Yahoo!的代码里面转了两天,尤其是这个超级复杂的Y! Photos 3 – Core Javascript,头都大了,实在是没有心情再搞排序了,不过最大的问题也就是删除重复照片的问题差不多也够用了。

还是先公布源代码和链接,注释我没有删除,可能长了一些,源代码如下:

javascript:void((function(){var p_displayed = ddh.photoItems.length;var p_pagetotal = ddh.pageSize[ddh.page];s = '已显示图片' + p_displayed + "张\\n";s += "本页共有图片" + p_pagetotal + "张\\n";s += "强制显示剩下的" + (p_pagetotal - p_displayed) + "张\\n";for (i=p_displayed; i<p_pagetotal; i++){pm._apiBlockSize = pm.apiBlockSize;/*pm.apiBlockSize = pm.ppp;*/ddh.loadPhotoData(ddh.page, i, (ddh.createWholeEntirePage));pm.apiBlockSize = pm._apiBlockSize;}/*selector.checkPhotoRange(p_displayed, p_pagetotal);*//*Check duplicate*/p_had = '';i_dup =0;tray = trayController;for (i=0; i<ddh.photoItems.length; i++){/*Got image caption*//*<LI id="photo-template"*/o = ddh.photoItems[i].oPP.parentNode.parentNode.parentNode;/*<DIV class="controls"><DL> ... <dt>*/o = o.getElementsByTagName('dt');/*Got the input*/name = o.item(0).firstChild.value;/*Check*/if (0 <= p_had.indexOf('{' + name + '}')){/*Duplicate*//* Added in, but did't displayed.*/d=new DragDropItem(ddh.photoItems[i]);tray.addItemByObject(d);/*s += name + "is duplicated.\\n";*/i_dup ++;}else{p_had += '{' + name + '}';}}s += i_dup + '张重复的照片。';alert(s);/*alert(s);*/})());

链接在这里:

Y!删重图

完整的源代码:

javascript:void((function(){
var p_displayed = ddh.photoItems.length;
var p_pagetotal = ddh.pageSize[ddh.page];
s = '已显示图片' + p_displayed + "张\\n";
s += "本页共有图片" + p_pagetotal + "张\\n";
s += "强制显示剩下的" + (p_pagetotal - p_displayed) + "张\\n";
for (i=p_displayed; i<p_pagetotal; i++){
    pm._apiBlockSize = pm.apiBlockSize;
/*  pm.apiBlockSize = pm.ppp;*/
    ddh.loadPhotoData(ddh.page, i, (ddh.createWholeEntirePage));
    pm.apiBlockSize = pm._apiBlockSize;
}
/*selector.checkPhotoRange(p_displayed, p_pagetotal);*/
/*Check duplicate*/
p_had = '';
i_dup =0;
tray = trayController;
for (i=0; i<ddh.photoItems.length; i++)
{
    /*Got image caption*/
    /*<LI id="photo-template"*/
    o = ddh.photoItems[i].oPP.parentNode.parentNode.parentNode;
    /*<DIV class="controls"><DL> ... <dt>*/
    o = o.getElementsByTagName('dt');
    /*Got the input*/
    name = o.item(0).firstChild.value;
    /*Check*/
    if (0 <= p_had.indexOf('{' + name + '}'))
    {
        /*Duplicate*/
        /* Added in, but did't displayed.*/
        d=new DragDropItem(ddh.photoItems[i]);
        tray.addItemByObject(d);
        /*s += name + "is duplicated.\\n";*/
        i_dup ++;
    }
   else
    {
        p_had += '{' + name + '}';
    }
} 
s += i_dup + '张重复的照片。';
alert(s);
/*alert(s);*/
})());

使用方法如下:

  • 打开Yahoo! Photos,打开要去除重复图片的相册,选择显示所有图片
  • 默认只显示能看见的照片,点一下“Y!删重图”,会把所有图片都显示出来,页面会闪烁几下,等待即可
  • 等待图片都显示出来,也可以手工向下拉让它自己调用显示
  • 再点一下“Y!删重图”,会把重复的图片放到处理区中,提示重复的图片数量,不过处理区中不会显示
  • 在AJAX菜单中选择Edit->Photos->Delete,确认删除即可

注:仅在FF2下测试,不保证完全可靠,丢失数据不要找我。。。

写累了,不过还是再介绍一下我的实现思路:

  • 首先显示所有图片是通过已有的全局变量ddh.photoItems来实现的
  • 显示的方法也是:ddh.loadPhotoData,照页面加载是的代码改编的
  • 在DOM树中根据ddh.photoItems[i]也就是每张图片找到他们的标题(caption)
  • 如果caption以前没有处理过,就记录到字符串中
  • 如果caption处理过,说明是重复的照片,trayController.addItemByObject(DragDropItem(ddh.photoItems[i])把它添加到处理区中
  • 手工删除处理区中的照片(虽然不显示,但确实加进去了,为何不显示,我也不明白)

Yahoo! DOM树中图片的标题,也就是我判断图片唯一性的标记caption(我没有重命名数码照片的习惯),隐藏的真深,翻了半天才翻出来,再次对Yahoo!恐怖的JS代码表示敬畏。

Update @ 2007-04-11

当当前显示照片数超过300张时,此功能不好用,请逐百张处理,然后再用显示全部300张的功能。在某些时候,上传不太灵光的情况下,向相册中上传不超过300张照片的时候,实际会显示相册中有400到500张的图片,当然大多数都是重复的,这也正是这个工具的用处所在。

Related posts

Categories: Internet, Tools Tags:

CSS裸奔节之强制脱衣

April 5th, 2007 Fwolf 2 comments

今天是CSS裸奔节,所谓CSS裸奔,就是把网站的所有css去掉,这样所有的显示格式什么的就都没有了,只剩下html实体显示出来,起源好像是比较无聊的想法,就是剥去css的外衣,让大家看看你的(x)html代码是否工整。

不过今天偶不打算裸奔,而是告诉大家一个可以看到任何网站裸奔形象的方法,参考我以前写的用js丰富你的书签功能,创建一个书签,也可以放到书签工具栏上,内容如下:

javascript:void((function(){var style=document.getElementsByTagName('style');for (i=0; i<style.length; i++)style.item(i).disabled=true;var link = document.getElementsByTagName('link');for (i=0; i<link.length; i++)if ('text/css' == link.item(i).type)link.item(i).disabled=true;var obj = document.getElementsByTagName('*');for (i=0; i<obj.length; i++){obj1 = obj.item(i);if (obj1.attributes.getNamedItem('style')){obj1.attributes.getNamedItem('style').value = '';}}})());

注意一定要是一行才行,作为书签地址就可以了,然后打开任何一个网站,点这个书签,是不是把css全部都脱掉了?懒人也可以直接把这个链接拖到工具栏上使用:

CSS裸奔

公布源代码如下,没有太复杂的地方,有了DOM说明,知道各个对象的方法和属性之后,把stylelink全部禁用,然后把inline的style=""的value全部设置为空串就可以了:

javascript:void((function(){
/* 用style方式引用的css */
var style=document.getElementsByTagName('style');
var s='Style:' + style.length;
for (i=0; i<style.length; i++)
{
    /*s += style.item(i) + '|';*/
    style.item(i).disabled=true;
}
/* 用link方式引用的css */
var link = document.getElementsByTagName('link');
s += 'Link:' + link.length;
for (i=0; i<link.length; i++)
    if ('text/css' == link.item(i).type)
        {
            /*s += link.item(i).href + "|\\n";*/
            link.item(i).disabled=true;
        }
/* 任意对象的style="" */
var obj = document.getElementsByTagName('body').item(0).childNodes;
var obj = document.getElementsByTagName('*');
s += 'Obj:' + obj.length;
for (i=0; i<obj.length; i++)
{   
    obj1 = obj.item(i);
    if (obj1.attributes.getNamedItem('style'))
    {
        s += obj1.nodeName + obj1.attributes.getNamedItem('style').value + "\\n";
        obj1.attributes.getNamedItem('style').value = "";
    }
}
/*alert(s);*/
})());

这个文件删除掉注释以后,可以用下面这个命令转换为一行:

cat css1.js |tr -d \\\\n |sed -r -e 's/$/\\n/' -e 's/\\t//g'

这样就得到了上面那段源代码。

javascript程序调试比较麻烦,以前我的方法是在vim中编辑,然后用命令转化为一行,再手工粘贴到书签的地址中,执行,然后有错误再回到编辑。不过今天发现一个好方法,其实也就是脑子转个弯儿的事,创建一个html文件,在里面把javascript代码调试好,然后再转换为可以用在书签中的形式。

另外Firefox2的Error Console虽然能够监测js错误,但是如果不小心点了上面的“Messages”,就会发现错误不显示了,需要再点“All”查看所有信息,今天为这是纳闷了半天,因为切换显示错误分类的时候没有任何征兆。

参考:

Related posts

Categories: Web Frontend Tags: , , ,

Xargs用法一例

April 5th, 2007 Fwolf 1 comment

起因要从Tomboy和同步说起,想同步两台电脑上tomboy的数据,“Start page”冲突也就算了,我用其他的,要命的是数据文件同步之后,tomboy必须要重新启动才能重新读取数据文件,所以要用ps x找出tomboy进程,杀掉再重新启动,如果是使用默认的applet方式,gnome会自动提示是否重新加载的。总的ps x命令如下:

ps x|grep -m1 tomboy|awk '{print $1}'| xargs -I'{}' kill '{}'

功能解释如下

  • ps x就不用说了
  • grep是用来查找进程列表中带有tomboy文字的,-m1是只找出第一个匹配,因为第二个匹配会是ps x本身
  • awk是用来打印第一列的
  • xargs中的-I指定用'{}'kill命令中来代表输入参数,在本例中可以省略的。

以上命令组合起来就可以比较“智能”的完成任务了,和find -exec有些类似。

另外我发现tomboy的“Start Here”是不让删除的,不过把标题改一下就可以删了。。。

PS1: 发现hexdump可以以16进制形式显示文件内容,比如一个内容为01234567890的文件:

$ hexdump a
0000000 3130 3332 3534 3736 3938 0a30          
000000c

注意这种默认的输出方式,字的高位可低位是反的,比如代表0的30就排在代表1的31的后面。也可以通过参数指定输出的方式,比如-b是逐字节按8进制输出:

$ hexdump a -b
0000000 060 061 062 063 064 065 066 067 070 071 060 012                
000000c

-c是逐字符输出,转义字符会输出为\n这种形式:

$ hexdump a -c
0000000   0   1   2   3   4   5   6   7   8   9   0  \\n                
000000c

-C是16进制逐字输出,后面还显示原始字符,有点像Ultraedit里面的那种感觉:

$ hexdump a -C
00000000  30 31 32 33 34 35 36 37  38 39 30 0a              |01234567890.|
0000000c

PS2: 今天在公交车上看新闻联播的时候在想,cctv的新闻联播有版权么?应该是有,那为何那么多地方电视台天天“转播”新闻联播,他们都交版权费了么?同样的还有纯洁春节晚会,天气预报,焦点访谈等等,都收点钱的话央视又能大赚一笔。

Update @ 2007-05-06

上述用xargs实现kill指定进程的方式纯属演示xargs的功能,杀指定进程用pkill pattern更方便,甚至还支持正则表达式,感谢fcicq

Related posts

Categories: Linux Tags:

把DH主机上的mysql字符集倒腾为utf8

April 2nd, 2007 Fwolf No comments

很久没有倒腾过mysql的字符集了,都疏忽了,以致于为LP安装Dreamhost上主机的时候,居然没有修改mysql数据库的字符集。也是由于mysql这东西,即使字符集设置错了,也是吃啥吐啥,拿错误的字符集就往数据库里存,所以外面根本看不出来。今天给LP写了个自动备份脚本,才发现导出的sql中全是乱码,岂能容忍?遂解决之~

首先还是放松了警惕,走了个弯路,我习惯使用的dump脚本是:

mysqldump --add-drop-table --default-character-set=utf8 -h mysql.mydomain.com --user=fwolf --password=mypasswd --extended-insert=false fwolf_db > mydomain.com_db.sql

可是dump出来的sql一看中文全是乱码,于是去掉--default-character-set=utf8再dump,数据依旧,一时没想过来,用iconv把dump出来的sql左转换右转换怎么也是不对,后来才想明白,DH上mysql字符集的默认设置是这样的:

mysql> show variables where variable_name like 'char%';
+--------------------------+--------------------------------------------+
| Variable_name            | Value                                      |
+--------------------------+--------------------------------------------+
| character_set_client     | latin1                                     |
| character_set_connection | latin1                                     |
| character_set_database   | latin1                                       |
| character_set_filesystem | binary                                     |
| character_set_results    | latin1                                     |
| character_set_server     | latin1                                     |
| character_set_system     | utf8                                       |
| character_sets_dir       | /data/mysql/ovadilla/share/mysql/charsets/ |
+--------------------------+--------------------------------------------+
8 rows in set (0.00 sec)

数据库服务器字符集是latin1,也就是mysql默认的latin1_swedish_ci,而系统的默认字符集则是utf8,所以不带--default-character-set=utf8参数dump的数据的时候,其实和带上这个参数是一样的!想通这个问题,又知道了mysql吃啥吐啥的特性之后,解决方法就简单了,记住如果WordPress和mysql都是默认设置的情况下,如果你能夠正常浏览中文,则说明配置就是错误的,因为WordPress默认也不是utf8字符集的。

首先,按latin1字符集导出sql:

mysqldump --add-drop-table --default-character-set=latin1 -h mysql.mydomain.com --user=fwolf --password=mypasswd --extended-insert=false fwolf_db > mydomain.com_db.sql

这样导出的sql中的中文应该都是正确的了,现在修改导出的sql文件,把其中的latin1全部替换为utf8,然后再重新导入数据库,导入的时候强制指定字符集为utf8:

mysql --default-character-set=utf8 fwolf_db -h mysql.mydomain.com -u fwolf -pmypasswd < mydomain.com_db.sql

这样,如果直接用mysql查询数据的话,如果不使用set names 'utf8',中文应该是乱码的,而如果你的数据库字符集仍然是默认的latin1的话,会是相反的情况:不使用set names 'utf8',中文正常,使用之后反而乱码。确认数据库字符集调整正确之后,再来搞定WordPress,这个就简单多了,编辑文件WP/wp-includes/wp-db.php,大概66行,在$this->select($dbname);前面,加上:

$this->query('set names utf8');

这样就全部搞定了,数据库和Wordpress的字符集全部调整为万国码utf8。

参考:

PS1: DH主机ssh、svn、cron、php-cli、fsocketopen什么的全部支持,太爽了,怪不得那么多人喜爱,就是ssh的速度慢了些。

PS2: 一个和mysql吃啥吐啥有关的笑话,不太雅:你来到医院,向医生说:我近来很不正常,吃什么拉什么,吃黄豆拉黄豆,吃西瓜拉西瓜,你问医生怎样才能恢复正常,医生沉默了一阵说:你吃屎吧!

Update @ 2007-07-20

mt主机上的mysql是4.1版本,查服务器配置变量的sql好像略微有些不同,不用where了:

show variables  like 'char%';

Related posts

Categories: Database Tags:

Ubuntu中Apache反向代理的使用

April 1st, 2007 Fwolf No comments

环境:Ubuntu 6.10 edgy, Apache 2.55

正常启用的方法很简单,首先要启用apache的proxy模块:

a2enmod proxy

然后在apache的conf中进行相应配置即可,比如我把/ubuntu反向代理到内网的另外一台主机,对公网进行服务:

<Location /ubuntu>
    ProxyPass http://svr5/ubuntu
    ProxyPassReverse http://svr5/ubuntu
</Location>

这样当公网用户访问我的主机的/ubuntu子目录时(注意/ubuntu这个Alias无需定义),Apache就会从访问内网服务器svr5的相应内容,并返回给用户。

以上是正常定义方式,不过在ubuntu下调用时却出现403错误,查看apache的error.log发现:

[Sun Apr 01 19:35:57 2007] [error] [client 121.*.*.*] client denied by server configuration: proxy:http://svr5/ubuntu/

查看svr5的log没有访问记录,就是本服务器的配置中的问题,再查看/etc/apache/mods-avaliable/proxy.conf,发现如下内容:

<IfModule mod_proxy.c>

    #turning ProxyRequests on and allowing proxying from all may allow 
    #spammers to use your proxy to send email.

ProxyRequests Off

<Proxy *>
    Order deny,allow
    Deny from all
    #Allow from .your_domain.com
</Proxy>

为了避免spammer使用服务器发送垃圾邮件,proxy模块启用后默认是关闭所有访问的,真想不通反向代理怎么就能够发送垃圾邮件了,不过找到问题之后,解决方法就有了,就是修改这个/etc/apache/mods-avaliable/proxy.conf文件,把#Allow from .your_domain.com修改为Allow from 用户地址,虽然可以用211.24来代表一定ip范围的用户,还是麻烦,干脆Allow from all也是可以的。如果觉得修改这个文件麻烦,也可以在httpd.conf中写上类似代码:

<proxy>
    Order deny,allow
    Allow from all
</proxy>

参考:

Related posts

Categories: Apache, Linux Tags: