彼岸网

 找回密码
 立即注册
搜索
热搜: 活动

tag 标签: 文章

相关帖子

版块 作者 回复/查看 最后发表

没有相关内容

相关日志

分享 如何向用户推送通知
热度 3 天香公主 2017-6-24 01:46 PM
如何向用户推送通知
本文旨在讨论网友a1980提出的问题: 希望如果有新的文章,只要開啟瀏覽器,不論有沒有進到我們的網站,他都會在右下角通知讀者有新文章 http://www.75271.com/3375.html 网友介绍的文章用的是HTML5里的网络通知功能 (Web Notifications API),参见( 链接 和 链接 )。 其实Discuz的代码里就使用过这个功能:在 template/default/common/footer.htm 里有下面这段代码,它的作用是当用户有新提醒或新消息时,在屏幕右下角就会出现一个通知窗口: 但是至少我从没在用Discuz造的网站里看到过这个窗口。其原因是实现这个功能的代码(在文件 static/js/html5notification.js 里)用的是早期由谷歌自创的网络通知API,语法和现在的国际标准有些不同,较新的服务器已经不支持它了。但是不难把这个文件用当前的标准改写,这样我们就能在较新的Firefox和Chrome浏览器里看到这个功能了( 下载链接 )。 但是这种做法只在用户接触站内的某个网页时才会触发,它没法在网站有需要时(如网站里发了一篇新文章),主动向用户发送通知。要达到那样的效果,需要另外两个HTML5里的功能:网络推送API(Push API),以及服务工人(Service Worker),参见( 链接 和 链接 )。 要实现这个功能,对网站有些要求。首先网站必须使用HTTPS,这是Service Worker的要求。其次网站用的PHP版本至少得是 5.6 而且要支持gmp,这是我用的一个第三方类库 web-push-php 的要求。同时用户的浏览器不能是IE,而需要是较新版本的Firefox,Chrome,Safari,或Edge (我的测试环境是 Firefox54和Chrome59),这是Push API和Service Worker的要求。因此这个功能在现阶段不能用来完全替代Discuz里传统的消息传递方式,但可以成为一个有益的补充。 要实现网站向用户推送通知,光靠网站服务器和用户浏览器的力量还不够,还需要一个第三方提供推送服务(push service)。这是因为网站和浏览器的联系是由浏览器向网站发请求而开始,又由网站发回复给浏览器而结束。网站无法主动和某个浏览器联系。所以网站向浏览器推送通知的方法是它把通知的内容发给由浏览器决定的提供push service的服务器,再由这个服务器将内容转给浏览器。每种浏览器都使用一个提供push service的服务器。浏览器在启动那刻起就和提供push service的服务器保持着联系,直到浏览器停止运行为止。所以提供push service的服务器可以随时送通知给浏览器,而不需要用户去打开发通知的那个网站的网页。如果提供push service的服务器收到要传送的通知时,要送达的那个浏览器没在运行或不在线上,它会将通知保存,等浏览器上线后和它联系时再送达通知。 Service Worker是在浏览器里运行的不同于UI线程(thread)的单独的线程。它由浏览器依据网站的需要产生,运行网站提供的代码,完成网站要做的事。它的最常见的用途是在浏览器离线状态时,将浏览器对网站的请求用本地资源来满足,从而让用户在离线时继续使用该网站。在网络推送里它起的作用是当浏览器收到推送通知后,它会发给和该网站对应的Service Worker,由Service Worker运行网站提供的代码来显示通知。 要实现推送,需要两部分的工作。第一部分是一次性的准备工作 1)要征得用户对显示通知窗口的同意。用户会看到一个征得同意的窗口 2)网站要准备一个service worker要做的事的js代码文件,并向浏览器注册一个service worker来做这些事 3)由该service worker向浏览器使用的push service订阅推送,这样网站才能把要推送的内容发给push service传递。网站需要提供一个代表它的应用服务器的 VAPID public key,push service会回给一个专用的url,称为endpoint,来供网站发给它要传送的通知 4)将订阅成功后得到的信息包括push service提供的 endpoint,还有浏览器提供的代表它的客户 public key和token,送到服务器去保存。当网站要发通知时,需要这些信息 第二部分是发送和接受通知 1)网站在要发通知时,找到所有要发通知的浏览器的订阅信息 2)给每个订阅信息提供的endpoint发经过加密的通知,发的格式由web push protocol决定的。这部分protocol比较复杂,所以我用了第三方提供的类库 web-push-php 3)浏览器收到push service传送的通知后,会交给和网站对应的service worker来处理 4)该service worker会运行网站提供的处理代码来显示通知窗口 要进一步了解web push的原理和流程,建议阅读Matthew Gaunt的书( 链接 ) 和他的示范代码( 链接 )。上面说的两部分工作也可以用他书中的两副插图来说明: xmp { white-space: pre-wrap; display: block; border: 1px solid lightgrey; padding: 5px;} 下面介绍下我在Discuz网站里使用web push的尝试。目的不在于给Discuz提供一个完整的新的通知机制,而在于摸索和了解它的可行性。 界面的变化 1)用户在登录后,如果浏览器支持web push的话,在首页的左上方会出现一个"不收推送通知"链接,代表当前用户还没有同意接收通知。点击后这个链接会变成"接收推送通知",这时用户就可以收到网站推送的通知了。如果不想收到推送通知了,就再次点击这个链接。这个toggle过程类似于网站上已有的隐身/在线功能。 2)当浏览器收到通知后会在右下方的窗口里显示。作为测试,加了两类通知 a)当网站发布新文章时发通知给所有订阅通知的用户 b)当博主发新日志时,发通知给所有订阅通知的好友 用户点击通知窗口后就进入了该文章/日志页 数据库的修改 要添加一个新的数表来记载推送的订阅信息。如果在安装网站时给数表设置无前缀的话,可以用下述语句产生该数表: CREATE TABLE `ext_push_subscription` ( `id` smallint(6) unsigned NOT NULL AUTO_INCREMENT, `uid` mediumint(8) unsigned NOT NULL DEFAULT '0', `subscription` mediumtext NOT NULL, `dateline` int(10) unsigned NOT NULL, PRIMARY KEY (`id`), KEY `uid` (`uid`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; 如果在安装网站时给数表设置了前缀的话,得给这个的新数表也加上同样的前缀。比如如果数表名都以pre_作为前缀(如pre_common_admingroup),那么新数表的名字就得改成pre_ext_push_subscription。 代码的修改 主干部分是下面这些新文件和文件夹: push-setup.js 在浏览器里运行负责为浏览器订阅推送 push-service-worker.js 记载service-worker要做的时,包括如何显示收到的通知 push-subscription.php 接受浏览器递交的推送订阅信息 push-message.php 在网站上负责发通知的函数 source/class/table/ table_ext_push_subscription.php 负责管理保存推送订阅的数表 web-push-php 网上下载的帮助将通知发给 push service 的类库 ( 链接 ) push service 用 VAPID keys 来确认要向用户推送通知的网站就是让用户订阅推送的网站。每个网站应该使用自己的VAPID keys。访问网页 https://web-push-codelab.appspot.com 就能得到自己的VAPID keys。然后将它们替换文件pub-message.php里的 VAPID_PUBLIC_KEY 和 VAPID_PRIVATE_KEY,以及文件 push-setup.js 里的 VAPID_PUBLIC_KEY 其次需要修改现有的文件 1。在语言包里添加要用的汉字字符串 修改文件 source/language/lang_template.php,在其中加入 '您的好友{author}刚发了新日志,快去看看吧', 2。修改界面使得用户可以接收推送通知 修改文件 template/default/common/header.htm, 在下面这句话 后加入 var FORM_HASH = "{FORMHASH}"; var ALLOW_PUSH_LABEL = "{lang allow_push}"; var FORBID_PUSH_LABEL = "{lang forbid_push}"; setUpSubscriptionSwitch($("subsriptionswitch"), $_G ); 注意在上面代码里和a间的空格要去掉 3。在网站有新文章时通知用户 修改文件 source/include/portalcp/portalcp_article.php, 在下面这句话 1)); 后加入 include_once libfile('function/home'); $pic = $setarr ; if ($pic) $pic = pic_get($pic, '', $setarr , $setarr , 1, 1); include_once(DISCUZ_ROOT.'push-message.php'); sendPushMessage('new-article', lang('template', 'newarticle_push_title'), $setarr , $summary, $pic, 'portal.php?mod=view&aid='.$aid, null); 4。当发新日志时,给日志作者的好友发通知 修改文件 source/function/function_blog.php, 在下面这句话 $POST )); 后加入 $blogarr )), $blogarr , $summary, $picurl, 'home.php?mod=space&uid='.$blogarr .'&do=blog&id='.$blogid, $frienduids); } } 测试网站: https://ngcorner.com/dz32wp ,用户 test1/123451, test2/123451, test3/123451。可以用一个ID发日志,再用另一个好友ID看通知 下载链接: http://www.bian-wang.com/discuz/data/userupload/10005/webpush_discuz.zip
个人分类: Discuz|3370 次阅读|33 个评论
分享 给微博添加收藏功能
热度 2 天香公主 2016-5-21 06:57 PM
给微博添加收藏功能
Discuz提供了一个收藏功能,类似于浏览器里的收藏夹。它可以用来收藏版块,帖子,日志,相册和文章。用户可以在相关内容的网页里看到'收藏'按钮或超链点击后来将内容加入收藏,并在快捷导航里点击'收藏'图标来进入收藏网页里看到所有加入收藏的内容(网站要在管理中心的界面->导航设置->快捷导航里将'收藏'设为可用)。网友sesemule希望能收藏微博/记录,所以写本文讨论下如何实现这个功能。所有代码都是效仿现有的其它内容收藏的相关代码。 pre, xmp { white-space: pre-wrap; display: block; border: 1px solid darkgrey; background-color: lightgrey; } 1)在记录页里给每个记录(不包括回复)加收藏链接 在文件 template/default/home/space_doing.htm 里的下面这句 {lang reply} | 后加入 {lang favorite} | 2)将用户决定收藏的记录存入数据库。 所有的收藏都存在数表 home_favorite 里,其中的表列 idtype 记载了收藏内容的类型, id记载了在该类型内的内容的primary key的值。 2a)将文件 source/include/spacecp/spacecp_favorite.php 里的下面这句 $_GET = in_array($_GET , array("thread", "forum", "group", "blog", "album", "article", "all")) ? $_GET : 'all'; 改为 $_GET = in_array($_GET , array("thread", "forum", "group", "blog", "album", "doing", "article", "all")) ? $_GET : 'all'; 2b)并在同一文件里的下面这段 fetch($id, $spaceuid); $title = $result ; $icon = ' '; break; 后加入 fetch($id); $title = ($doinginfo == $spaceuid) ? $doinginfo : ''; $icon = ' '; break; 3)显示用户收藏的记录 3a)在文件 source/language/home/lang_template.php 里加入 '记录', 3b)将文件 source/include/space/space_favorite.php 里的下面这句 'aid'); 改为 'aid'); 3c)并在同一文件里的下面这句 ' ', 后加入 ' ', 3d)再在同一文件里的下面这段 case 'albumid': $url = 'home.php?mod=space&uid='.$spaceuid.'&do=album&id='.$id; break; 后加入 case 'doid': $url = 'home.php?mod=space&uid='.$spaceuid.'&do=doing&doid='.$id; break; 3e)在文件 template/default/home/space_favorite.htm 里的下面这句 {lang favorite_album} 后加入 {lang favorite_doing} 3f)并在同一文件里的下面这句 {lang favorite_album} 后加入 {lang favorite_doing} 5/27/2016补充:答网友问如何象论坛主题贴那样在日志,相册和记录收藏按钮/链接处显示收藏次数。 1)在显示相关网页时在脚本文件里要从数据库里找出收藏次数 1a)日志: 在文件 source/include/space/space_blog.php 里的下面这段 if(!empty($_G ) && empty($_G )) { helper_antitheft::check($id, 'bid'); } 后加上 count_by_id_idtype($id, 'blogid'); 1b)相册: 在文件 source/include/space/space_album.php 里的下面这段 delete($id); showmessage('to_view_the_photo_does_not_exist', "home.php?mod=space&uid=$album &do=album&view=me"); } 后加上 count_by_id_idtype($id, 'albumid'); 1c)记录: 在文件 source/include/space/space_doing.php 里的下面这段 fetch_all_search($start, $perpage, 1, $uids, '', $searchkey, '', '' ,'', 1, $doid, $f_index); foreach($query as $value) { if($value == 0 || $value == $_G || $_G == 1) { $doids ; 后加上 count_by_id_idtype($value , 'doid'); 2)在显示网页的模板文件里加上显示收藏次数的地方 2a)日志: 将文件 template/default/home/space_blog_view.htm 里的下面这行 {lang favorite} 改为 {lang favorite} $fav_count 2b)相册: 将文件 template/default/home/space_album_view.htm 里的下面这行 {lang favorite} 改为 {lang favorite} $fav_count 2c)记录: 将文件 template/default/home/space_doing.htm 里的下面这行 {lang favorite} | 改为 {lang favorite} $dv | 3)在用户确认要收藏后要实时更新收藏次数 3a)将文件 template/default/home/spacecp_favorite.htm 里的下面这行 改为 3b) 在文件 static/js/home.js 里添加下面的函数: function favoriteupdate(id) { var obj = $('favoritenumber'); if (!obj) obj = $('favoritenumber_' + id); if (obj) { obj.style.display = ''; obj.innerHTML = parseInt(obj.innerHTML) + 1; } } 注:本文中的代码里的<符号后和a相连时加了一个不应该有的空格,以避免Discuz在保存日志时自动改变日志内容。
个人分类: Discuz|2030 次阅读|19 个评论
分享 Discuz功能改进:论坛日志记录文章的一键帖
热度 5 天香公主 2016-5-13 09:02 AM
Discuz功能改进:论坛日志记录文章的一键帖
Discuz功能改进:支持论坛日志记录文章的一键帖 过去写的一篇介绍在记录里将用户填写的图片和油管地址在显示时自动转换成对应的图片和嵌入油管视频的方法(称为一键贴)的博文( 链接 )近来受到了几位网友的认可和兴趣,所以在这里我把类似的对多种多媒体资源由地址转换成嵌入资源的函数贴出来和网友交流,并介绍下如何在日志,文章和论坛里使用它。 这个函数叫 url2html,它将地址转换成html元素,所以自然第一个参数是地址,第二个参数取值0或1代表了被嵌入的区域的类型。我将区域分成主要区域(日志正文,文章正文,论坛主题贴和跟贴),和次要区域(日志评论,文章评论,记录正文和回复),因为不同的区域类型各有各的合理显示方式,比如一个pdf文件地址在日志正文里应该显示成嵌入pdf显示在日志内,而在记录里因为空间的限制也许显示成超链接更恰当。 1)支持的资源类别,视频网页地址,视频地址 资源类型 备注 举例 图片 以.gif, .jpeg, .jpg, .png结尾的文件 http://budgetstockphoto.com/samples/pics/stones.jpg PDF 以.pdf结尾的文件 http://www.pdf995.com/samples/pdf.pdf 音乐 以.mp3, .wav, .wma结尾的文件 http://www.tonycuffe.com/mp3/tail%20toddle.mp3 http://www.music.helsinki.fi/tmt/opetus/uusmedia/esim/a2002011001-e02.wav http://www.theflute.co.uk/media/BachCPE_SonataAmin_1.wma 视频 以.mp4, .webm, .ogv, .swf, .flv, .wmv结尾的文件 http://techslides.com/demos/sample-videos/small.mp4 http://techslides.com/demos/sample-videos/small.webm http://techslides.com/demos/sample-videos/small.ogv http://www.flashppt.com/images/tangramone.swf http://techslides.com/demos/sample-videos/small.flv http://www.educationalquestions.com/video/ELL_PART_5_768k.wmv YouTube视频 视频网页地址 https://www.youtube.com/watch?v=MD5bFCDfySc https://m.youtube.com/watch?v=MD5bFCDfySc https://youtu.be/MD5bFCDfySc 视频地址 https://www.youtube.com/embed/MD5bFCDfySc https://www.youtube.com/v/MD5bFCDfySc DailyMotion视频 视频网页地址 http://www.dailymotion.com/video/x4xvnz_the-funny-crash-compilation_fun http://dai.ly/x4xvnz 视频地址 http://www.dailymotion.com/embed/video/x4xvnz Vimeo视频 视频网页地址 https://vimeo.com/110145104 视频地址 https://player.vimeo.com/video/110145104 我乐视频 视频网页地址 http://www.56.com/u75/v_MTE3ODg5ODgw.html 视频地址 http://www.56.com/iframe/MTE3ODg5ODgw 哔哩哔哩视频 视频网页地址 http://www.bilibili.com/video/av1286985 http://www.bilibili.com/video/av1286985/index_2.html Flash视频地址 http://static.hdslb.com/miniloader.swf?aid=1286985page=2 凤凰视频 视频网页地址 http://v.ifeng.com/documentary/figure/201605/0362ac12-fd5d-4a16-b836-378c61543ca0.shtml Flash视频地址 ( 寻找方法 ) http://v.ifeng.com/include/exterior.swf?guid=0362ac12-fd5d-4a16-b836-378c61543ca0AutoPlay=false 爱奇艺视频 Flash视频地址 ( 寻找方法 ) http://player.video.qiyi.com/4b40896a102b47584f9573b76b093fa3/0/0/v_19rrlty944.swf-albumId=482534600-tvId=482534600-isPurchase=0-cnId=25 酷6视频 视频网页地址 http://v.ku6.com/show/Es8Bn14RwCZKOS7Lz4ts3Q...html?hpsrc=1_25_1_2_0# http://v.ku6.com/special/show_2562886/SoGnlFVxjStPTJmQ.html Flash视频地址 ( 寻找方法 ) http://player.ku6.com/refer/Es8Bn14RwCZKOS7Lz4ts3Q../v.swf 腾讯视频 视频网页地址 http://v.qq.com/page/q/v/6/q0149bzkuv6.html http://v.qq.com/cover/4/44q2pgwf0tb6hsq.html?vid=y0016wcg0ot http://m.v.qq.com/play/play.html?coverid=vid=z0197m8xrv3 视频地址 http://v.qq.com/iframe/player.html?vid=q0149bzkuv6 新浪视频 视频网页地址 http://video.sina.com.cn/view/250587748.html Flash视频地址 ( 寻找方法 ) http://video.sina.com.cn/share/video/250587748.swf 搜弧视频 Flash视频地址 ( 寻找方法 ) http://share.vrs.sohu.com/3029619/v.swftopBar=1autoplay=falseplid=1000083pub_catecode=0from=page 土豆视频 视频网页地址 http://www.tudou.com/programs/view/xGgArUMPw9I http://www.tudou.com/listplay/Q0MiBE2DPCs/NQjV-Amh1ac.html Flash视频地址 http://www.tudou.com/programs/view/html5embed.action?code=xGgArUMPw9I http://www.tudou.com/l/Q0MiBE2DPCs/iid=132813935resourceId=0_04_05_99/v.swf 优酷视频 视频网页地址 http://v.youku.com/v_show/id_XMTgyMzE0NzE2.html Flash视频地址 ( 寻找方法 ) http://player.youku.com/player.php/sid/XMTgyMzE0NzE2/v.swf 对内容里不符合上述规律的其它地址,我们都转换成了超链接。在不支持Flash的机器如iPad和iPhone上,Flash地址也转换成超链接而不是嵌入资源。 对大多数视频网站,我们可以通过对视频网页的地址的解析找到对应的视频地址。对这样网站,用户只需填写视频网页的地址。但也有些网站,我们需要用户在视频网页上找到对应的视频地址,一般这个信息可以点击网页上的'分享'找到,我文中加了些各个网站的图示。 2)对Discuz代码的修改来使用这个函数,两种方式(用和不用mejs) xmp { white-space: pre-wrap; display: block; background-color: lightgrey; border: 1px solid darkgrey; } table { border-color: darkgrey; } a) 在论坛里支持一键贴 在文件 source/function/function_discuzcode.php 修改函数parseurl $length) { $text = substr($url, 0, intval($length * 0.5)).' ... '.substr($url, - intval($length * 0.3)); } return ' '.$text.' '; } else { $url = substr($url, 1); if(substr(strtolower($url), 0, 4) == 'www.') { $url = 'http://'.$url; } $url = !$scheme ? $_G .$url : $url; return ' '.$text.' '; } } 将原来贴子在显示时的自动加链机制去掉,加上我们的一键贴: function parseurl($url, $text, $scheme) { global $_G; if(!$url && preg_match("/((https?|ftp|gopher|news|telnet|rtsp|mms|callto|bctp|thunder|qqdl|synacast){1}:\/\/|www\.) +/i", trim($text), $matches)) { $url = $matches ; } else { $url = substr($url, 1); if(substr(strtolower($url), 0, 4) == 'www.') { $url = 'http://'.$url; } $url = !$scheme ? $_G .$url : $url; } require_once libfile('function/url2html'); return url2html_url($url, 0); } b) 在日志正文里支持一键贴 在文件 source/include/space/space_blog.php 下面这段代码 require_once libfile('function/blog'); $blog = blog_bbcode($blog ); 后加入 require_once libfile('function/url2html'); $blog = url2html($blog , 0); c) 在日志评论里支持一键贴 c1) 在文件 source/include/space/space_blog.php 下面这段代码 fetch_all_by_id_idtype($id, 'blogid', $start, $perpage, $cid); foreach($query as $value) { 后加入 require_once libfile('function/url2html'); $value = url2html($value ); c2) 在文件 source/include/misc/misc_ajax.php 下面这段代码 fetch_latest_by_authorid($_G , $cid); 后加入 require_once libfile('function/url2html'); $value = url2html($value ); c3) 为支持一键贴,需要去掉Discuz在评论储存前对URL的自动加链的功能因为将在显示前加:在文件 source/class/class_bbcode.php 里的函数 bbcode2html 的下面这段的最后一句去掉 search_exp \s*( +?)\s*\ /ies"; $this->replace_exp = "/\ \s*( +?)\s*\ /ies"; $this->replace_exp .text); } 并在函数 comment_add 里的下面这段 x.get('home.php?mod=misc&ac=ajax&op=comment&inajax=1&cid='+id, function(s){ newdl.innerHTML = s; 后加入 runScript(newdl); 类似的在函数 comment_edit 里的下面这段 x.get('home.php?mod=misc&ac=ajax&op=comment&inajax=1&cid='+ cid, function(s){ obj.innerHTML = s; 后加入 runScript(obj); d) 在文章正文里支持一键贴 在文件 source/module/portal/portal_view.php 下面这段代码 require_once libfile('function/blog'); $content = blog_bbcode($content ); 后加入 require_once libfile('function/url2html'); $content = url2html($content , 0); e) 在文章评论里支持一键贴 e1) 在文件 source/module/portal/portal_view.php 里下面这段代码 $hash = md5($article ."\t".$article ); 之前加入 $value) { $commentlist = url2html($value ); } e2) 我们要控制一下评论里贴图的最大宽度,这可以在风格文件template/default/common/common.css里实现,也可以仿照日志里的做法在文件 template/default/portal/view.htm 的底部下面这句代码 上面加入: resizeImg('comment_ul','450'); 代码下载 1)利用了mejs的一键贴 (Discuz3.2): http://www.bian-wang.com/discuz/data/userupload/10005/url2html_with_mejs.zip (02/07/2017更新) 更新记录: 02/07/2017: 加入对PHP7的支持 05/05/2018: 加入Discuz3.4简体中文UTF8版本 2)不用mejs的一键贴:
个人分类: Discuz|7041 次阅读|49 个评论
分享 东方式自卑与嫉妒
笔记本 2016-4-11 01:22 PM
今天我在网上查阅资料,结果看到美中网一篇文章被多处转载,标题是《岳东晓状告34家公司版权官司自愿协议撤诉》。该文写道:【 岳东晓在去年 5 月赢了一个版权案 Yue v. Chordiant ,只拿到一百多万。 8 月他气壮如牛,乘胜追击,又控告了 21 century 等等共 34 个公司侵犯版权。】  然后此人写道【 stipulated dismissal 当然是双方协议撤销案件,结束战争,但是自愿结束战争不等于赢了战争,打官司要赢了钱和对方道歉才是赢。岳东晓没有赢,因为这个案子他既没有审判团审讯也没有和解 settlement 。。。 岳东晓这个案子的 docket 只显示了双方协议撤销案件 stipulated dismissal ,但是没有显示 settlement 和解。会不会是像他说的“当然在法庭案卷上看不到那个协议内容,因为那可能是保密的。 ” ?不可能, 因为依照联邦民事法庭法规第 79 条: Records Kept by the Clerk ,所有的跟案子有关的文件譬如 settlement agreement 都必须 file 在法院 ,记录在这个案子的 docket 上,第 79 条法规说在 docket 上这些必须被记录】 写这个的人看来查看了相关联邦法院的案卷,而且知道一点联邦诉讼程序,很可能是一名律师。如果是,那就是一名低级别的、没有多少实际经验、读不懂条款的律师 。因为  FRCP 79  上根本没有写和解协议必须递交给法庭。 实际上,和解协议一般是不会递交给法庭的,甚至都没有必要向法庭提及 。和解是诉讼双方不通过法院裁决而私下解决了争端,双方签了个协议。法院根本不需要知道双方是怎么和解的、和解的条款是什么。和解双方需要通知法院的事情是:双方就此不打了, 法院就可以把案子给结了 。这一点,稍微见过点世面的律师就应该知道。 起诉 21 Century 等34个公司侵权案我曾经写过,双方在第九巡回法院调解员的调解下和解了。由于相关保密条款,我只能说最终以双方满意的条件解决了。金额多少,我不能说也没有必要说。我在联邦法院宣誓作证到:【 我起诉了21 Century 保险及其他33个下游侵权者。针对21 Century等被告的调解会议于2011年在美国第九巡回法院进行。被告们律师云集。对方公司代表与我决定抛开律师们直接谈判。案件很快和解了。我注意到当被告律师知道案子和解之后,脸上毫无笑容。】 我这个证词是想说明参与该案的被告律师想把案子变成摇钱树,看到案子和解很不乐意。其中某被告律师还等着拿律师费造游泳池呢 --- 这是他自己说的,但我还没揭发他这种不轨动机。 那个 《岳东晓状告34家公司版权官司自愿协议撤诉》文的 作者是什么心理呢?其实就是一种东方式自卑+嫉妒。所谓东方式嫉妒就是自己不行,不是去提高自己,而是想把他人拉下来跟自己扯平。那些诽谤者就是如此,极度自卑而又拼命想证明自己,于是捏造虚假的事实攻击他人聊以获得一丝可怜的慰藉。这样的人不是试图通过学习以期弥补其先天及后天的不足,而是将极度自卑表现为极度狂躁。 将诽谤者绳之以法,将证明东方式嫉妒在西方行不通,而且是作奸犯科。 文章来源: http://www.zhenzhubay.com/home.php?mod=space&uid=2&do=blog&id=32320
个人分类: 法律|0 个评论
分享 从代码修改到插件开发:封面插件
热度 3 天香公主 2016-2-20 11:08 PM
从代码修改到插件开发:封面插件
从修改系统代码到开发插件:支持网络图片和油管视频缩影图做为封面图 前几天我讨论了如何修改Discuz系统代码来支持网络图片和油管视频缩影图做为文章和日志的封面图( 链接 和 链接 )。东风兄跟评介绍了他的 北美生活网 使用的一个将油管视频缩影图做为论坛主题帖封面图的插件。用插件形式来修改系统给站长装卸和管理系统改动带来很大的方便。所以这几天我又考虑了下如何将前述修改写成插件的形式,本文记录下心得。 下图显示的是我写的封面插件在开发时的文件结构。非常简单,只包含了一个页面嵌入模块(其中只有一个全局嵌入点函数)和两个Javascript函数文件。 xmp { white-space: pre-wrap; display: block; vertical_align: top; background-color: lightgrey;} th, td { vertical_align: top; } 下面讨论下如何将前述代码修改转换成插件代码。前述修改的代码可以分成下面的三类。 第一类是客户端Javascript函数定义的修改,比如文章封面修改中对系统函数 createImageBox 的修改(见 链接 中的1a))。怎样能在不修改原来的函数的前提修改功能呢?Javascript语言有个好(或坏)的特点:它允许同名函数多次定义,只有最后一次的定义会被调用,也就是说后面的函数定义覆盖了前面定义的同名函数。所以我们可以不修改原来想要修改的函数,而在网页的后部给出个原来函数的修改版。以 createImageBox 为例: 系统代码(static/image/editor/editor_function.js): 修改代码: function createImageBox(fn) { if (typeof fn == 'function' && !fn()) { return false; } var menu = $('icoImg_image_menu'); ... function createImageBox(fn) { if (typeof fn == 'function' && !fn()) { return false; } if ($('conver')) { edit_save(); var imgs = getExternalImages(); ... 插件代码: 1. source/plugin/txgz_cover/cover.class.php: class plugin_txgz_cover { function global_footer() { global $_G; $rv = ''; if (!empty($_G )) { if(CURSCRIPT == 'portal') { if($_GET == 'portalcp' && $_GET == 'article') { $rv .= ' '; ... return $rv; } } 2. source/plugin/txgz_cover/js/cover.js: function createImageBox(fn) { if (typeof fn == 'function' && !fn()) { return false; } edit_save(); var imgs = getExternalImages(); ... 第二类是修改服务器端提供数据的PHP代码,如文章封面修改中的在门户页和文章列表页上显示的封面(见 链接 中的1b)和1c))。不改系统代码的话,这些网页用的网络图片的封面图的链接是无效的。我们的解决办法是在客户端把服务器端提供的无效链接在显示前再转换成有效链接。 以修改文章列表页里得到封面图的代码为例: 系统代码(source/function/function_home.php): 修改代码: function pic_get($filepath, $type, $thumb, $remote, $return_thumb=1, $hastype = '') { global $_G; $url = $filepath; if($return_thumb && $thumb) $url = getimgthumbname($url); ... function pic_get($filepath, $type, $thumb, $remote, $return_thumb=1, $hastype = '') { global $_G; $url = $filepath; if (preg_match('/^https?:\/\//', $url)===1) return $url; if($return_thumb && $thumb) $url = getimgthumbname($url); ... 插件代码: 1. source/plugin/txgz_cover/cover.class.php: class plugin_txgz_cover { function global_footer() { ... $rv .= ' '; return $rv; } } 2. source/plugin/txgz_cover/js/cleanupsrc.js: (function cleanupImageSources() { var imgs = document.getElementsByTagName('img'); for (var i = 0; i = 0) img.src = img.src.substr(sp + 1); } })(); 第三类是修改服务器端储存数据的代码,比如清空文章封面的代码( 链接 中的3))。由于我们现在不允许修改系统代码,我们就没法在最合适的地方做这件事,但是我们可以在插件内找到合适机会干这件事。 系统代码(source/include/portalcp/portalcp_article.php): 修改代码: if($_GET ) { $converfiles = dunserialize($_GET ); $setarr = $converfiles ; $setarr = intval($converfiles ); $setarr = intval($converfiles ); } if($_GET ) { $converfiles = dunserialize($_GET ); $setarr = $converfiles ; $setarr = intval($converfiles ); $setarr = intval($converfiles ); } else { $setarr = ''; $setarr = 0; $setarr = 0; } 插件代码: source/plugin/txgz_cover/cover.class.php: update($aid, $setarr); } } } 通过这两天的尝试,对Discuz插件的强有力的系统扩展机制有了深刻印象。粗看页面嵌入点函数只能在页面的一些特定位置添加些字符,再看发现它也能输出Javascript代码并由此变化和控制网页上任何位置的内容,可以添加Javascript函数来替代系统函数并进而改变系统功能。做为在服务器端执行的函数,它还能做于网页输出内容无关的事,如修改数据库数据。虽然嵌入点函数在被执行时并没有给予任何参数,但通过检查整体变量的值,可以得知很多执行环境的信息,如当前所执行的用户请求信息,并因此区分和决定该做的事。 插件下载: http://www.bian-wang.com/upload/txgz_cover_160302.zip
个人分类: Discuz|155 次阅读|8 个评论
分享 翰山网 ALEXA 排名释疑
笔记本 2016-2-15 01:58 PM
网友转来一篇翰山评论各网站排名的文章。我在很久以前对所谓 ALEXA 排名进行过解释,但估计我的解释翰山没有看懂。所以我再拨冗详细解释下。 所谓 ALEXA 排名是根据安装了 ALEXA TOOLBAR 的人群的互联网活动进行统计。如果你在自己的浏览器上面装了 ALEXA TOOLBAR,那么你访问了什么网站的同时,也有记录发到 ALEXA 那里。ALEXA 再根据这些访问记录进行排名。如果你没装 ALEXA TOOLBAR,ALEXA又不是神仙,当然不知道你去过哪些网站。 理论上,这算是一个抽样统计了。假如有 1% 的人安装了这个 ALEXA TOOLBAR 那么这个统计还有点有效性。但是从我掌握的数据来看,目前安装了这个 TOOLBAR 的人可能少于万分之一。 这是什么意思呢?我举个极端的例子,假如全世界只有一个人安装了 ALEXA TOOLBAR,而这个人最喜欢访问珍珠湾,那么珍珠湾就排名世界第一了。如果安装ALEXA 的人数少于万分之一,而一个网站的访问人数少于1万,那么这个网站在ALEXA上显示的几率访问数将是零。 而只要有一个访问者装上这个 TOOLBAR,网站ALEXA排名就可以迅速跃升 。 鉴于安装这个TOOLBAR人比例小,ALEXA 自己都承认,其排名只对非常靠前的网站才可靠。 翰山网访问量,即使是被人转帖的链接的帖子,能上200个点击了不起了,为什么其 ALEXA 排名反而超过其他明显比它热络的网站呢? 原因应该是翰山本人的浏览器上安装了 ALEXA TOOLBAR,如果他去掉这个 TOOLBAR,其网站排名应该会下降 100万左右。不信可以试试。 文章来源: http://www.zhenzhubay.com/home.php?mod=space&uid=1&do=blog&id=31837
0 个评论
分享 Discuz功能改进:将网络图片设为文章封面
热度 2 天香公主 2016-2-15 01:23 PM
Discuz功能改进:支持将网络图片和油管视频缩影图设为文章封面 Discuz里的文章功能提供了站方一个有序发布资讯如新闻的合适场所。很多网站里的文章都是转载其它网站的内容。文章可以按类别聚合到首页去,Discuz提供了图文模版可以在那里显示文章中的一幅图称为封面图。但现有的功能有个缺陷是封面图只能是在该文章中上传的图片,不仅其它网站的图片连自己网站上现有的图片虽然可以放入文章中,但都成不了封面图。作者为了给文章加封面图不得不将网络图片下载再上传到文章里,这不是种理想的做法,它不必要的占用了过多的网站资源。本文来探讨下如何修改Discuz来让作者可以直接用网络图片当封面图。 先记录下文章编辑页上有关部件的代码文件名和相关代码: xmp { white-space: pre-wrap; display: block; background-color: lightgrey; } 文章编辑页 portalcp_article.htm 编辑工具栏 home_editor.php, 工具栏上的'添加图片'图标的定义是: < a href="javascript:;" class="icoImg" id="icoImg" onClick="parent.createImageBox( );return false;" title=" 对点击工具图标的处理 editor_function.js function createImageBox(fn) 文章提交按钮 portalcp_article.htm {lang submit} 添加图片弹窗及其Tabs home/editor_image_menu.htm ... {lang upload_pic} {lang upload_pic} 添加图片弹窗中上传图片Tab里的内容 home/editor_image_menu.htm 按浏览器是否支持Flash显示下面两者之一: ... $article ... $article 添加图片弹窗中上传图片Tab里内容的数据来源 portalcp_article.php fetch_all_by_aid($aid) as $value) { ... $attachs = get_upload_content($attachs); } function_portalcp.php function get_upload_content($attachs, $dotype) 了解了相关代码的位置,我们就知道要从何着手了。 1。支持将网络图片做为封面图 当作者点击编辑工具栏里的'添加图片'按钮时,分析当前文章的内容,找到其中所有的网络图片,在添加图片弹窗里加入网络图片供作者选择封面图 1a) 在文件 static/image/editor/editor_function.js 里要修改一个函数并添加两个新函数。首先在函数 createImageBox 里开始部分 if (typeof fn == 'function' && !fn()) { return false; } 后加入: 0; i--) { d.removeChild(dts ); } if (dts.length==0) { var tableObj = document.createElement('table'); tableObj.className = 'imgl'; tbodyObj = document.createElement("TBODY"); tableObj.appendChild(tbodyObj); d.appendChild(tableObj); } var tableObj = document.createElement('table'); tableObj.className = 'imgl'; var html = ''; for (var i = 0; i < imgs.length; i++) { var thisConver = getExternalImageConver(imgs ); var check = (conver == thisConver) ? 'checked' : ''; if (i % 4 == 0) html += ' '; html += ' \ \ \ \ \ 设为封面 \ \ '; if (i == imgs.length - 1) { for (var j = 0; j < (4 - i % 4) ; j++) { html += ' '; } } if (i % 4 == 3 || i == imgs.length - 1) html += ' '; } tableObj.innerHTML = html; d.appendChild(tableObj); } 另外在该文件里加入下面两个新函数: function getExternalImageConver(img) { return 'a:3:{s:3:\"pic\";s:' + img.length + ':\"' + img + '\";s:5:\"thumb\";s:1:\"0\";s:6:\"remote\";s:1:\"1\";}' } function getExternalImages() { var hc = $('uchome-ttHtmlEditor').value; var imgs = +src=( )?(https?:\/\/ +)\1? *\/?>/g; while (m = rex.exec(hc)) { var url = m ; if (imgs.indexOf(url) == -1) imgs.push(url); } return imgs; } 注意在Discuz代码多处有个将封面cover写成conver的typo,所以我们也照此处理。 1b) 我们还要修改文章列表页里得到封面图的代码。在文件 source/function/function_home.php 中的函数 pic_get 里的开始部分 global $_G; $url = $filepath; 后加入 if (preg_match('/^https?:\/\//', $url)===1) return $url; 1c) 我们还要修改DIY模块里得到封面图的代码。在文件 source/function/function_block.php 中的函数 block_template 里将下面这句 } elseif($field == 'pic') { 改为 } elseif($field == 'pic' && preg_match('/^https?:\/\//', $replacevalue)!==1) { 2。支持默认封面图 现在Discuz只支持将上传图片为设为封面图,而且自动将第一幅上传的图片设为封面图。现在我们要支持网络图片,在用户不人为设置封面图时最好也能自动选择文中的第一幅网络图片做为封面图。做这个工作的合适时机是当用户点击'提交'按钮后 2a) 在文件 template/default/portal/portalcp_article.htm 中的函数 validate 里在下面这句 edit_save(); 后加入 setDefaultConver(); 2b) 在文件 static/image/editor/editor_function.js 里添加下面这个新函数: 0; i--) { d.removeChild(dts ); } var imgbtns = d.getElementsByTagName('input'); for (var i = 0; i 0) $('conver').value = imgConvers ; } } 3。支持清空封面图 如果我们依据文章里的网络图片设置了封面图,但后来作者修改了文章把那幅图去掉了,那我们怎么能更新封面图的设置呢?2b) 里引入的新函数 setDefaultConver 已经在这种情形下在客户端按情况清空了封面图或选择了文中另一幅图当封面图。但我们还需要支持在服务器端支持清空封面图:在文件 source/include/portalcp/portalcp_article.php 的下面这段 if($_GET ) { $converfiles = dunserialize($_GET ); $setarr = $converfiles ; $setarr = intval($converfiles ); $setarr = intval($converfiles ); } 后加入 else { $setarr = ''; $setarr = 0; $setarr = 0; } 4。支持将油管视频的缩影图做为封面图 我们还可以用文章中的油管视频做为封面图。在1a)里在文件 static/image/editor/editor_function.js 中引入的新函数 getExternalImages 的最后一句 return imgs; 前加入 // youtube video var rex = /https?:\/\/ +/ig; while (m = rex.exec(hc)) { var url = m ; var vid = ''; // e.g. https://www.youtube.com/embed/MD5bFCDfySc // e.g. https://www.youtube.com/v/MD5bFCDfySc var rex2 = /youtube.com\/(embed|v)\/( +)/i; m2 = rex2.exec(url); if (m2) vid = m2 ; // e.g. https://youtu.be/MD5bFCDfySc var rex2 = /youtu.be\/( +)/i; m2 = rex2.exec(url); if (m2) vid = m2 ; // e.g. https://www.youtube.com/watch?v=MD5bFCDfySc // e.g. https://m.youtube.com/watch?v=MD5bFCDfySc var rex2 = /youtube.com\/watch\?( +)/i; m2 = rex2.exec(url); if (m2) { var qs = m2 .split('&'); for (var i in qs) { if (qs .substring(0, 2) == 'v=') { vid = qs .substring(2); } } } if (vid) { url = 'https://img.youtube.com/vi/' + vid + '/0.jpg'; if (imgs.indexOf(url) == -1) imgs.push(url); } } 4/12/2016 补充:如何在提交文章里自动下载远程图片到本站 感觉用网络图片当封面有利有弊,缺点是网络图片随时可能会消失,还有就是图片所在的网站国内网民不一定进得去。另一种确保文章有封面的处理方式是当保存文章时自动将文章里的所有图片都下载到本地,这样做的话就没有用网络图片当封面的必要了。这需要对文件 portalcp_article.htm做几处改动,首先引进一个变量 pa_downloading 来判断是否正在下载远程图片。然后将点击提交按钮后执行的函数 validate 一分为三: var pa_downloading=false; function validate(obj) { pa_downloading=true; downRemoteFile(); check_download_progress(obj); } function check_download_progress(obj) { if (pa_downloading) { setTimeout(function() { check_download_progress(obj); }, 1000); } else { validate_original(obj); } } function validate_original(obj) { var title = $('title'); if(title) { var slen = strlen(title.value); if (slen 80) { alert("{lang article_validate_title}"); title.focus(); return false; } } if(!check_catid()) { return false; } edit_save(); window.onbeforeunload = null; obj.form.submit(); return false; } 先执行下载远程图片函数 downRemoteFile,执行完毕后再执行原来的提交函数 validate。其中用了个定时器来检查下载是否完毕。那么我们怎么能知道下载完毕呢?所以最后还需要加另一个改动: 如果用这种处理方式的话,点击文章"提交"按钮后不要立刻换页,而应等到网页自动转到显示"发布文章成功"的信息页。 注:本文中的代码里的<符号如果后面的字符是a的话,在它们中间加了一个不应该有的空格,以避免Discuz在保存日志时自动改变日志内容。
个人分类: Discuz|2752 次阅读|12 个评论
分享 关于夜城称珍珠湾点击率作假指控
笔记本 2016-1-8 03:20 AM
关于夜城称珍珠湾点击率作假指控
据网友反映,夜夜城老蔡写文章称珍珠湾点击率作假。 珍珠湾对此声明如下:老蔡此文错误,其对珍珠湾的指控虚假。 此前,我已要求刘牧野宣誓承认其为夜城“老菜头”马甲,至今刘未作出宣誓或非宣誓否认。 证据表明,老蔡 是刘牧野 (Muye Norley Liu aka Mason Liu) 的另一个马甲。 其相关涉嫌诽谤与不公平竞争内容,将依法坚决应对。 希望相关人士能像珍珠湾的网友们一样堂堂正正做人,有话站出来直说,说话负责。 夜城网友多系当年“锅巴”(注)等说动而去,当继承珍珠湾之高尚传统,明辨是非,自觉抵制反对各种不良网络行为。近墨则黑、潜移默化的古训应该记取。 注:证据显示,“锅巴”作为刘牧野之代言在珍珠湾宣传夜城,其IP与刘牧野IP(动态)只相差最后一个字节,二者关系尚待取证确认。 文章来源: http://www.zhenzhubay.com/home.php?mod=space&uid=1&do=blog&id=31530
0 个评论
分享 Discuz功能改进:将论坛里的文件上传对iPad的支持扩展到日志文章和相册 ...
热度 8 天香公主 2015-7-16 11:37 PM
Discuz功能改进:将论坛里的文件上传对iPad的支持扩展到日志文章和相册 ...
过去我曾经分析过日志里的图片上传机制 ( 链接 ),讨论过在那里使用基于Flash的SWFUpload组件的必要性。但没想到论坛里的类似功能提供了基于Flash技术和不基于Flash技术的两套上传方案,按浏览器是否支持Flash来选择用哪套方案。本文分析一下它的机制,并将它扩展到日志,文章和相册里。 首先注意整个发表贴子的网页所用的模板是 forum/post.htm,它引用了 javascript 文件 static/js/forum_post.js。它还嵌入了两个子模板 forum/editor_menu_forum.htm 和 common/upload.htm,而后者引用了 javascript 文件 static/js/upload.js。 xmp { white-space: pre-wrap; display: block; background-color: lightgrey; border: 1px solid darkgrey; } post.htm: upload.htm: {eval $_G = 1;} 1。我们先来分析是在哪里选择是否用基于Flash的上传方法的: 下面是在Firefox里的图片上传界面截屏,第一张是在Add-ons Manager激活了Shockwave Flash 的情形,第二张是不激活的情形: 从中可见,在这两种情形下,出现的是同一个弹出窗口,但所用的TAB不同。这四个TAB (上传图片,普通上传,相册图片,网络图片)定义在editor_menu_forum.htm 里: {lang close} {lang e_img_attach} {lang normal_upload} {lang e_img_albumlist} {lang e_img_www} 注意在定义普通上传TAB时用的属性 did="{$editorid}_btn_imgattachlist|local" ,这个信息告诉下面的代码上传图片TAB和普通上传TAB会有一个被隐藏: upload.js: function disableMultiUpload(obj) { if(obj.uploadSource == 'forum' && obj.uploadFrom != 'fastpost') { try{ obj.singleUpload.style.display = ''; var dIdStr = obj.singleUpload.getAttribute("did"); if(dIdStr != null) { if(typeof forum_post_inited == 'undefined') { appendscript(JSPATH + 'forum_post.js?' + VERHASH); } var idArr = dIdStr.split("|"); $(idArr ).style.display = 'none'; if(idArr == 'local') { switchImagebutton('local'); } else if(idArr == 'upload') { switchAttachbutton('upload'); } } } catch (e) { } } } function preLoad() { if(!this.support.loading) { disableMultiUpload(this.customSettings); return false; } } function loadFailed() { disableMultiUpload(this.customSettings); } var SWFUpload; var swfobject; if (SWFUpload == undefined) { SWFUpload = function (settings) { this.initSWFUpload(settings); }; } SWFUpload.prototype.initSWFUpload = function (userSettings) { ... this.loadSupport(); ... } SWFUpload.prototype.loadSupport = function () { this.support = { loading : swfobject.hasFlashPlayerVersion("9.0.28"), imageResize : false }; }; post.htm: var imgUpload = new SWFUpload({ ... swfupload_preload_handler : preLoad, swfupload_load_failed_handler : loadFailed, ... SWFUpload 定义在 upload.js 里,它在处理 preload 事件会检查浏览器是否支持 Flash。如果不支持就会调用 disableMultiUpload 来隐藏图片上传TAB而显示普通上传TAB。同时它需要用到Flash。所以当浏览器里的Flash没有被激活时,它的 load_failed 事件处理代码就会被调用,它同样会调用 disableMultiUpload。 2。接下来我们来分析一下不用Flash时的选择文件的代码: 上传图片列表和上传按钮定义在文件 editor_menu_forum.htm 里: 上传文件列表是 imgattachbody,它的内容是以 imgattachbodyhidden 为模版生成的。还有一个上传表单(form)列表 imgattachbtn,它的内容是以 imgattachbtnhidden 为模版生成的。接下来的代码显示了它们的生成过程。 当用户选择了一个文件后,界面上的上传文件列表会更新,上传表单列表也会更新,这是由这个选择文件按钮的 change 事件处理代码提供的功能: 注意下面的语句调用了一个按模版产生选择文件表单的函数,其中对选择文件按钮加了事件处理来达到前述效果。 post.htm: addAttach('img'); forum_post.js: function addAttach(prefix) { var id = AID ; var tags, newnode, i; prefix = isUndefined(prefix) ? '' : prefix; newnode = $(prefix + 'attachbtnhidden').firstChild.cloneNode(true); tags = newnode.getElementsByTagName('input'); for(i = 0;i < tags.length;i++) { if(tags .name == 'Filedata') { tags .id = prefix + 'attachnew_' + id; tags .onchange = function() {insertAttach(prefix, id);}; tags .unselectable = 'on'; } else if(tags .name == 'attachid') { tags .value = id; } } tags = newnode.getElementsByTagName('form'); tags .name = tags .id = prefix + 'attachform_' + id; $(prefix + 'attachbtn').appendChild(newnode); newnode = $(prefix + 'attachbodyhidden').firstChild.cloneNode(true); tags = newnode.getElementsByTagName('input'); for(i = 0;i < tags.length;i++) { if(tags .name == prefix + 'localid .value = id; } } tags = newnode.getElementsByTagName('span'); for(i = 0;i < tags.length;i++) { if(tags .id == prefix + 'localfile .id = prefix + 'localfile_' + id; } else if(tags .id == prefix + 'cpdel .id = prefix + 'cpdel_' + id; } else if(tags .id == prefix + 'localno .id = prefix + 'localno_' + id; } else if(tags .id == prefix + 'deschidden .id = prefix + 'deschidden_' + id; } } AID ++; newnode.style.display = 'none'; $(prefix + 'attachbody').appendChild(newnode); } function insertAttach(prefix, id) { var path = $(prefix + 'attachnew_' + id).value; var extpos = path.lastIndexOf('.'); var ext = extpos == -1 ? '' : path.substr(extpos + 1, path.length).toLowerCase(); var re = new RegExp("(^|\\s|,)" + ext + "($|\\s|,)", "ig"); var localfile = $(prefix + 'attachnew_' + id).value.substr($(prefix + 'attachnew_' + id).value.replace(/\\/g, '/').lastIndexOf('/') + 1); var filename = mb_cutstr(localfile, 30); if(path == '') { return; } if(extensions != '' && (re.exec(extensions) == null || ext == '')) { reAddAttach(prefix, id); showError('对不起,不支持上传此类扩展名的附件。'); return; } if(prefix == 'img' && imgexts.indexOf(ext) == -1) { reAddAttach(prefix, id); showError('请选择图片文件(' + imgexts + ')'); return; } $(prefix + 'cpdel_' + id).innerHTML = ' 删除 '; $(prefix + 'localfile_' + id).innerHTML = ' ' + filename + ' '; $(prefix + 'attachnew_' + id).style.display = 'none'; $(prefix + 'deschidden_' + id).style.display = ''; $(prefix + 'deschidden_' + id).title = localfile; $(prefix + 'localno_' + id).parentNode.parentNode.style.display = ''; addAttach(prefix); UPLOADSTATUS = 0; } 上传按钮的值(value)只有在IE里才记录了所选文件的路径和文件名,在Firefox和Chrome里出于安全考虑都只记录了文件名。 3。接下来我们来分析一下不用Flash时的上传文件的代码。 上传按钮定义在接下来的代码里: {lang upload} {lang upload_after_selected} {lang uploading} 当用户点击上传按钮后,处理 onclick 事件的代码调用了定义在 forum_post.js 里的函数 uploadAttach: function uploadAttach(curId, statusid, prefix, sizelimit) { prefix = isUndefined(prefix) ? '' : prefix; var nextId = 0; for(var i = 0; i < AID - 1; i++) { if($(prefix + 'attachform_' + i)) { nextId = i; if(curId == 0) { break; } else { ... $(prefix + 'attachform_' + nextId).submit(); } 注意这个函数的结尾处将该表单 (form) 提交给了服务器。但是用户在这个网页上可能已经选择了多个图片,每个选择对应着一个上传表单。如何将每个表单里选择的图片都提交给服务器呢?注意表单的 target 属性的值是 attachframe ,对应着定义在 editor_menu_forum.htm 里的下述 iframe: 所以图片提交后会调用定义在 forum_post.js 里的函数 uploadNextAttach: 0) { sizelimit = '(不能超过 ' + arr + ' 字节)'; } uploadAttach(parseInt(att ), arr == 'DISCUZUPLOAD' ? parseInt(arr ) : -1, att , sizelimit); } 而在它的结尾处又调用了uploadAttach,周而复始,从而将所有选择的图片都上传到服务器了。 4。那么论坛里不用Flash的上传文件方法能不能用于日志(以及文章)呢?我们先对照一下两者用到的相关代码文件结构: forum_post.php defines $editorid = 'e' includes post_newthread.php/post_newreply.php/post_editpost.php template post.htm includes forum_post.js defines addAttach subtemplate post_editor_body.htm subtemplate editor.htm defines editorid = '$editorid'; subtemplate editor_menu_forum.htm defines switchImagebutton subtemplate upload.htm includes upload.js defines SWFUpload class creates SWFUpload object calls addAttach('img') home_spacecp.php includes spacecp_blog.php template spacecp_blog.htm includes editor_function.js subtemplate editor_image_menu.htm subtemplate upload.htm includes upload.js defines SWFUpload class creates SWFUpload object defines switchImagebutton 大致上说 editor_image_menu.htm 和 editor_menu_forum.htm 对应定义了上传文件的对话框的内容,而 editor_function.js 和 forum_post.js 对应定义了上传文件的对话框的在客户端的功能。这两个是我们要重点修改的文件。 我们先做些辅助性的改动: 1) 文件 static/js/upload.js 里的函数 disableMultiUpload 引发了在支持和不支持Flash时在上传文件对话框里选择显示合适的TAB。我们要加入对日志和文章的支持。将下面的代码 function disableMultiUpload(obj) { if(obj.uploadSource == 'forum' && obj.uploadFrom != 'fastpost') { try{ obj.singleUpload.style.display = ''; var dIdStr = obj.singleUpload.getAttribute("did"); if(dIdStr != null) { if(typeof forum_post_inited == 'undefined') { appendscript(JSPATH + 'forum_post.js?' + VERHASH); } 修改为 function disableMultiUpload(obj) { if ((obj.uploadSource == 'portal' || obj.uploadSource == 'forum') && obj.uploadFrom != 'fastpost') { try { obj.singleUpload.style.display = ''; var dIdStr = obj.singleUpload.getAttribute("did"); if (dIdStr != null) { if (obj.uploadSource == 'forum') { if (typeof forum_post_inited == 'undefined') { appendscript(JSPATH + 'forum_post.js?' + VERHASH); } } 2) 接下来在文件 static/image/editor/editor_function.js 里加入下面的函数来支持上传文件的功能: function uploadFile(prefix) { prefix = isUndefined(prefix) ? '' : prefix; var path = $(prefix + 'attachnew').value; var extpos = path.lastIndexOf('.'); var ext = extpos == -1 ? '' : path.substr(extpos + 1, path.length).toLowerCase(); var re = new RegExp("(^|\\s|,)" + ext + "($|\\s|,)", "ig"); var localfile = $(prefix + 'attachnew').value.substr($(prefix + 'attachnew').value.replace(/\\/g, '/').lastIndexOf('/') + 1); var filename = mb_cutstr(localfile, 30); if (path == '') { return; } if (extensions != '' && (re.exec(extensions) == null || ext == '')) { showError('对不起,不支持上传此类扩展名的附件。'); return; } if (prefix == 'img' && imgexts.indexOf(ext) == -1) { showError('请选择图片文件(' + imgexts + ')'); return; } var form = $(prefix + 'attachnew').form; if ($('formaction')) { $('formaction').value = form.action; form.action = $('localformaction').value; form.target = (prefix == 'img') ? 'imageframe' : 'attachframe'; if (prefix != 'img') $('imgattachnew').name = ''; if (prefix != '') $('attachnew').name = ''; } form.submit(); } function uploadImageDone() { if ($('formaction').value) { $('formaction').form.action = $('formaction').value; $('formaction').form.target = ""; $('imgattachnew').name = 'Filedata'; $('attachnew').name = 'Filedata'; } var str = $('imageframe').contentWindow.document.body.innerHTML; if (str == '') return; var data = eval('(' + str + ')'); if (parseInt(data.picid)) { var tdObj = getInsertTdId($('imgattachlist'), 'image_td_' + data.picid); var img = new Image(); img.src = data.url; var imgObj = document.createElement("img"); imgObj.src = img.src; imgObj.className = "cur1"; imgObj.onclick = function () { insertImage(data.bigimg); }; tdObj.appendChild(imgObj); var inputObj = document.createElement("input"); inputObj.type = 'hidden'; inputObj.name = 'picids '; inputObj.value = data.picid; tdObj.appendChild(inputObj); } else if (data.aid) { var tdObj = getInsertTdId($('imgattachlist'), 'attach_list_' + data.aid); ajaxget('portal.php?mod=attachment&op=getattach&id=' + data.aid, tdObj.id); } else { showDialog('图片上传失败', 'notice', null, null, 0, null, null, null, null, sdCloseTime); } } function uploadAttachmentDone() { if ($('formaction').value) { $('formaction').form.action = $('formaction').value; $('formaction').form.target = ""; $('imgattachnew').name = 'Filedata'; $('attachnew').name = 'Filedata'; } var str = $('attachframe').contentWindow.document.body.innerHTML; if (str == '') return; var data = eval('(' + str + ')'); if (data.aid) { var tdObj = $('attachlist'); var fileObj = document.createElement("div"); fileObj.id = 'FileUpload_' + tdObj.childNodes.length; tdObj.appendChild(fileObj); ajaxget('portal.php?mod=attachment&op=getattach&type=attach&id=' + data.aid, fileObj.id); if ($('attach_tblheader')) { $('attach_tblheader').style.display = ''; } } else { showDialog('上传失败', 'notice', null, null, 0, null, null, null, null, sdCloseTime); } } 它们效仿了 static/js/forum_post.js 里的函数 uploadAttach 和 uploadNextAttach的框架,而其中后两个函数的代码参照了日志和文章在支持Flash时处理(static/js/upload.js 里的 uploadSuccess 函数)。 再对原有的函数 switchButton 略做改动,使之同时适用于图片上传和附件上传: function switchButton(btn, type) { var pre = 'ico' + ((type == 'attach') ? 'Attach' : 'Img') + '_'; var btnpre = pre + 'btn_'; if (!$(btnpre + btn) || !$(pre + btn)) { return; } var tabs = $(pre + type + '_ctrl').getElementsByTagName('LI'); $(btnpre + btn).style.display = ''; $(pre + btn).style.display = ''; $(btnpre + btn).className = 'current'; var btni = ''; for(i = 0;i < tabs.length;i++) { if(tabs .id.indexOf(btnpre) !== -1) { btni = tabs .id.substr(btnpre.length); } if(btni != btn) { if (!$(pre + btni) || !$('icoImg_btn_' + btni)) { continue; } $(pre + btni).style.display = 'none'; $(btnpre + btni).className = ''; } } } 3) 最后我们要对修改定义上传文件对话框的模板文件 template/default/home/editor_image_menu.htm 做多处改动: 3a) 在文件的开头加上 var extensions = ''; var imgexts = "$swfconfig "; function populateLocalSection(type) { var c = $('icoImg_imgattachlist').innerHTML; if (c) { var sv =' '; var nv = ' '; $('icoImg_local').innerHTML = c.replace(sv, nv); $('icoImg_imgattachlist').innerHTML = ''; } } function populateUploadSection(type) { var c = $('icoAttach_attachlist').innerHTML; if (c) { var lc = $('icoAttach_upload').innerHTML; var sv =' '; var nv = ' '; $('icoAttach_upload').innerHTML = c.replace(sv, nv); $('icoAttach_attachlist').innerHTML = ''; } } function switchImagebutton(btn) { if (btn == 'local') populateLocalSection(); switchButton(btn, 'image'); $('icoImg_image_menu').style.height = ''; doane(); } function switchAttachbutton(btn) { if (btn == 'upload') populateUploadSection(); switchButton(btn, 'attach'); doane(); } 3b) 在图片对话框里要添加一个TAB,它在没有 Flash 的环境里替代了原来的"上传图片"TAB。先添加新TAB的标题: 在下面这句 {lang upload_pic} 后加上 {lang upload_pic} 再添加新TAB的内容: 在下面这句 前加上 3c) 对文章里的附件上传要做类似的改动: 在下面这句 {lang upload_attach} 后加上 {lang upload_attach} 在下面这句 前加上 3d) 还要加些支持上传的内容: 将下面这句 改为:
个人分类: Discuz|8469 次阅读|86 个评论
分享 新华社使用依地语 "评棋者" 嘲讽藐视美国
热度 3 lawandorder 2015-3-24 12:49 AM
新华社使用依地语 " 评棋者 " 嘲讽藐视美国 今日读到 THE DIPLOMAT 网站的这篇文章, China Slams US as 'Kibitzer on South China Sea ' , 里面引述新华社 2015 年 3 月 21 日的这篇评论 Commentary: America the Kibitzer on South China Sea 。 新华社的评论文章标题使用了依地语 (Yiddish) kibitzer ,来自动词 kibitz, 原意是旁观并自我指点别人下棋或打牌,引申出看热闹并提供不需要的见解。这是个贬义词,带有嘲讽藐视鄙视的内涵。 新华社这个评论标题可以按字面翻译为《美国是南海问题的多嘴评棋者》,引申翻译为《美国在南海问题上自以为是指手画脚》。无论字面还是引申理解,这是我多年来第一次看到中国官方媒体在南海问题上如此揭示美国南海问题的表现(其实是海军将领和联邦参议员的观点陈述,并不能代表政府立场),反映出中国官方媒体挑战美国的胆量,同时评论全文也体现出对美国第七舰队现任舰队司令 Robert L. Thomas 中将 ( "The latest symptom of the obsession with unwanted counseling emerged into plain sight earlier this week, when Robert Thomas, commander of the U.S. Navy Seventh Fleet, whose country is not a party in theSouth China Seadisputes, advisedASEANcountries to form a combined maritime force for joint South China Sea patrols and even called for moreJapanese involvement."), 参议院 4 位资深参议员 ("The urge for presumptuous commenting escalated to a call for naked intervention on Thursday, as a handful of U.S. big-name senators, in a letter to State Secretary John Kerry and Defense Secretary Ash Carter, wrongfully pointed an accusing finger at China and clamored for a U.S. strategy to stop what is actually China's legitimate activity in South China Sea."), 甚至是对美国政府如此的嘲讽和藐视 ("Uncle Sam has long been in the grip of many addictions, such as muscle-flexing, preaching and borrowing, but there has turned out to be one more: kibitzing.")
1783 次阅读|5 个评论
分享 刘老大火眼金睛,mgzww999无所遁形
热度 4 忆江南 2013-4-8 10:23 PM
前两天,在美中网上像样正经文章一篇没有,专爱给名博挑刺品头论足的 mgzww999 又来到刘老大的博客撒野。 xuzhao 2013-4-5 14:55 您老,我真的又忍不住想说幼稚这个词,您太正派了!难怪桑欺负您。呵呵提这个对不起。 玩政治难道不都是玩两面派?尤其国与国之间,玩两面派的事多去了。特别是 ... 不等 mgzww999 把招术使全,刘老大已经了然于心: ksliu 2013-4-5 15:09 中国过去玩“两面派”的行为确实很多,但多数是对内,在外交上一直比较讲求信用。这次是不是两面派,还要看事实。 还有, 我猜你老弟就是999本人,而999就是过去经常和我抬杠的那位老朋友“小泼妇”,对不对?呵呵 ,这叫“多面人”。不过这不重要,咱们还是就事论事,面对观点的冲突,大家平心讨论,不管你用什么称号。 mgzww999 的变身先试图抵赖,矢口否认: xuzhao : 刘老大先生竟然猜测我是你,这也太离谱。 又打哈哈妄图蒙混过关: xuzhao : 哈哈,您老真的猜错了。我怎么可能是999呢? 太离谱。 请您仔细比较,999文笔是多么的老辣!俺不过是一个普通小网友,以前还有人猜俺是礁石,真令人哭笑不得。[e ... 刘老大目光炯炯,老神在在: ksliu 2013-4-6 02:04 不是就不是吧,这么紧张就说明我猜对了。呵呵。 看客们目瞪口呆之际,刘老大徐徐地道出一番话来: ksliu 2013-4-6 02:12 三 个人(或三个笔名)的个性有五个共同点,这是非常稀有的情况, 因此可以很肯定地说这是同一个人 ,特别是在中文网这样一个小范围之内。 这不是猜,是科学的个 性分析 。注意是分析“个性”,不是“文笔”,因为文笔可以造假,个性很难掩盖。 至于是如何分析的,有哪五个共同点,这就不能轻易传授给你了。呵呵。 至此 mgzww999 已无计可施,只得供认不讳: mgzww999 2013-4-6 06:33 刘先生目光如炬,不会看走眼的,刘先生思维缜密,不会出漏洞的。别说中文网上这种小范围的游戏,就是中美两国政府的秘密交往都漏不过他的法眼和科学分析。 性格不象就不是同一个人了吗?人的性格是可以改变的,连我自己现在经过五个特征的科学分析(方法属于绝密级别)之后都已经认定你就是我。不但你是我,礁石 也是我,我也是礁石,你也是礁石,礁石也是你。至于性格不同,原因很简单,你是过去的我,礁石是未来的我,我是现在的我。给你举一个例子,温家宝当总理时 博主极尽阿谀奉承之能,用尽大肆吹捧之功,但是在他下台之后立即发博文指责温家族27亿贪腐问题,你能说这前后的博主不是一个人吗? 证明我是礁石非常容易,只需看一看两个我在红酒影评文章争议中的表现就完全明白了。红酒应该认识礁石,所以他一定知道礁石就是我。 不要再自以为是的认为你不是我了,"不识庐山真面目,只缘身在此山中",所谓当局者迷,旁观者清就是这个道理。 各位看官,孙悟空72变逃不出如来佛的掌心,mgzww999变依然走不了刘老大的法眼!有诗赞曰:我行我素老英雄,此生无悔看错人!粪土当年弼马温,赤胆忠心献习总。 欲知后事如何,且听下回分解。
3748 次阅读|25 个评论
分享 如何将博文加入八一文武对决?
笔记本 2012-7-17 01:02 AM
如何将博文加入八一文武对决?
在张贴文章时选择正确的“站点分类“。如下图 注意:不能选择”文武PK”,必须选择下面的子类别,如“文-诗词”,或者“武-摄影/书画”。 对已经张贴的博文,可以编辑博文,然后修改其日志类别。在张贴博文(或者设置类别)之后约5分钟,您为博文将被加入 http://www.zhenzhubay.com/topic-2.html 请注意,如果不是参赛博文,请不要选择这个几个类别。参赛作品应该以原创内容为主。 https://maps.google.com/maps?f=qsource=s_qhl=engeocode=q=California+Street,+San+Francisco,+CAaq=3oq=calsll=37.0625,-95.677068sspn=53.167773,70.927734t=hie=UTF8hq=hnear=California+St,+San+Francisco,+Californiaz=13ll=37.787542,-122.444578output=embed 文章来源: http://www.zhenzhubay.com/home.php?mod=space&uid=1&do=blog&id=2165
0 个评论

小黑屋|Archiver|彼岸网  

Powered by Discuz! X3.1 © 2001-2014 Comsenz Inc.
GMT-4, 2026-5-26 09:10 AM , Processed in 0.041153 second(s), 26 queries.

返回顶部