commit 238c5d001f4e837fa37aa0a395be63229ca0e335 Author: 小松 Date: Tue Oct 16 17:02:11 2012 +0800 1.3版 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..412eeda --- /dev/null +++ b/.gitattributes @@ -0,0 +1,22 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp +*.sln merge=union +*.csproj merge=union +*.vbproj merge=union +*.fsproj merge=union +*.dbproj merge=union + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5ebd21a --- /dev/null +++ b/.gitignore @@ -0,0 +1,163 @@ +################# +## Eclipse +################# + +*.pydevproject +.project +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.classpath +.settings/ +.loadpath + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# CDT-specific +.cproject + +# PDT-specific +.buildpath + + +################# +## Visual Studio +################# + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results +[Dd]ebug/ +[Rr]elease/ +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.vspscc +.builds +*.dotCover + +## TODO: If you have NuGet Package Restore enabled, uncomment this +#packages/ + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf + +# Visual Studio profiler +*.psess +*.vsp + +# ReSharper is a .NET coding add-in +_ReSharper* + +# Installshield output folder +[Ee]xpress + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish + +# Others +[Bb]in +[Oo]bj +sql +TestResults +*.Cache +ClientBin +stylecop.* +~$* +*.dbmdl +Generated_Code #added for RIA/Silverlight projects + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML + + + +############ +## Windows +############ + +# Windows image file caches +Thumbs.db + +# Folder config file +Desktop.ini + + +############# +## Python +############# + +*.py[co] + +# Packages +*.egg +*.egg-info +dist +build +eggs +parts +bin +var +sdist +develop-eggs +.installed.cfg + +# Installer logs +pip-log.txt + +# Unit test / coverage reports +.coverage +.tox + +#Translations +*.mo + +#Mr Developer +.mr.developer.cfg + +# Mac crap +.DS_Store diff --git a/css/lastRSS.css b/css/lastRSS.css new file mode 100644 index 0000000..4bed189 --- /dev/null +++ b/css/lastRSS.css @@ -0,0 +1 @@ +.lastRSS_loding{background:url(loading.gif) no-repeat center center}#lastRSS{padding:1px 5px;height:25px;line-height:25px;overflow:hidden}#lastRSS ul{padding:0;margin:0}#lastRSS ul li{overflow:hidden;height:25px} \ No newline at end of file diff --git a/css/loading.gif b/css/loading.gif new file mode 100644 index 0000000..a576ecd Binary files /dev/null and b/css/loading.gif differ diff --git a/js/jquery-autoscroll.js b/js/jquery-autoscroll.js new file mode 100644 index 0000000..3cc2b75 --- /dev/null +++ b/js/jquery-autoscroll.js @@ -0,0 +1 @@ +;(function(e){e.fn.extend({autoScroll:function(t){function s(){var t=r.find("ul:first"),n=t.find("li:first");if(i.type==="H"){var s=-n.outerWidth(!0)+"px";t.animate({marginLeft:s},800,function(){e(this).css({marginLeft:"0px"}).find("li:first").appendTo(this)})}else{var o=-n.outerHeight(!0)+"px";t.animate({marginTop:o},800,function(){e(this).css({marginTop:"0px"}).find("li:first").appendTo(this)})}}var n=null,r=this,i={type:"V",timer:5e3};return t=t||{},e.extend(i,t),n=setInterval(s,i.timer),r.each(function(){e(this).hover(function(){clearInterval(n)},function(){n=setInterval(s,i.timer)})})}})})(jQuery) \ No newline at end of file diff --git a/lastRSS.php b/lastRSS.php new file mode 100644 index 0000000..5f73d4b --- /dev/null +++ b/lastRSS.php @@ -0,0 +1,166 @@ +cache_dir = EMLOG_ROOT.'/content/cache/'; +$rssparser->cache_time = $lastRSS_cache_time; +$rssparser->items_limit = $lastRSS_item_num > 3 ? 3 : $lastRSS_item_num; +$rssparser->CDATA = 'content'; +$rssparser->cp = 'UTF-8'; +$rssparser->channeltags = array ('title'); +$rssparser->itemtags = array ('title','link'); +$rssparser->imagetags = array (); +$rssparser->textinputtags = array (); +$DB = MySql::getInstance(); + +function urlShort($url){ + global $lastRSS_urlshort_domain; + if (!extension_loaded('curl')) { + return $url; + } else { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_URL, 'http://json.so/api/short.htm?d='.$lastRSS_urlshort_domain.'&u='.$url); + curl_setopt($ch, CURLOPT_TIMEOUT, 5); + curl_setopt($ch, CURLOPT_USERAGENT, 'PHP Curl/xiaosong.org 1.0 BETA'); + $results = curl_exec($ch); + curl_close($ch); + $results = json_decode($results, true); + if(isset($results['state']) && $results['state'] == 'success'){ + return $results['msg']; + } + return $url; + } +} +function getRssFeeds(){ + global $DB; + $sql = "SELECT * FROM ".DB_PREFIX."rssfeeds ORDER BY id ASC"; + $result = $DB->query($sql); + return $result; +} +function isLogExists($rssid, $hash){ + global $DB; + $sql = "SELECT id FROM ".DB_PREFIX."rsslogs WHERE rssid = $rssid AND hash = '$hash'"; + $result = $DB->query($sql); + $rows = $DB->num_rows($result); + return $rows; +} +function isFeedExists($url){ + global $DB; + $sql = "SELECT id FROM ".DB_PREFIX."rssfeeds WHERE url = '$url'"; + $result = $DB->query($sql); + $rows = $DB->num_rows($result); + return $rows; +} +function insertLog($rssid, $log ,$hash){ + global $DB; + if (isLogExists($rssid, $hash) == 0) { + $DB->query("INSERT INTO ".DB_PREFIX."rsslogs (rssid, log, hash) VALUES($rssid, '$log', '$hash')"); + } +} +function insertFeed($url, $title){ + global $DB; + if (isFeedExists($url) == 0) { + $DB->query("INSERT INTO ".DB_PREFIX."rssfeeds (url, title) VALUES('$url', '$title')"); + } elseif (!getTitle($url)) { + formMsg("RSS导入失败,RSS地址{$url}解析失败,请确定RSS地址及XML文件格式正确",'./plugin.php?plugin=lastRSS',0); + } else { + formMsg("RSS导入失败,数据库中已存在{$url}",'./plugin.php?plugin=lastRSS',0); + } +} +function deleteFeed($id){ + global $DB; + $rssurl = $DB->fetch_array($DB->query("SELECT url FROM ".DB_PREFIX."rssfeeds WHERE id = $id")); + $rssurl = $rssurl['url']; + $cache_file = EMLOG_ROOT.'/content/cache/rsscache_'.md5($rssurl); + $DB->query("DELETE FROM ".DB_PREFIX."rssfeeds WHERE id = $id"); + $DB->query("DELETE FROM ".DB_PREFIX."rsslogs WHERE rssid = $id"); + @unlink($cache_file); +} +function updateFeed($id, $url, $title){ + global $DB; + $DB->query("UPDATE ".DB_PREFIX."rssfeeds SET url = '$url', title = '$title' WHERE id = $id"); +} +function getTitle($rss_url){ + global $rssparser; + $rss = $rssparser->get($rss_url); + return $rss['title']; +} +function updateLogs(){ + global $rssparser, $DB, $lastRSS_is_urlshort, $lastRSS_is_blank; + $feeds = getRssFeeds(); + while ($item = $DB->fetch_array($feeds)) { + $rss = $rssparser->get($item['url']); + if(!empty($rss['items'])) + foreach ($rss['items'] as $key => $data) { + $rssid = $item['id']; + $hash = md5($data['title']); + $checklog = isLogExists($rssid, $hash); + if ($checklog == 0) { + if (trim($data['title']) != '') { + $link = $lastRSS_is_urlshort ? urlShort($data['link']) : $data['link']; + $target = $lastRSS_is_blank ? ' target="_blank"' : ''; + $log = ''.strip_tags($data['title']).''; + insertLog($rssid, $log ,$hash); + } + } + } + } +} +function displayLog(){ + global $DB, $lastRSS_item_num; + $sql = "SELECT rssid,log FROM ".DB_PREFIX."rsslogs ORDER BY id DESC limit $lastRSS_item_num"; + $result = $DB->query($sql); + $output = ''; + while ($row = $DB->fetch_array($result)) { + $rssid = $row['rssid']; + $log = $row['log']; + $_sql = "SELECT title FROM ".DB_PREFIX."rssfeeds WHERE id = $rssid"; + $title = $DB->fetch_array($DB->query($_sql)); + $output .= '
  • '.$log.' 来自 《'.$title["title"].'》
  • '; + } + $output = empty($output) ? '
  • 暂无Rss文章 ^_^' : $output; + $output = ''; + return $output; +} +function displayLogIndex(){ + echo '
    '; +} +function lastRSS_css(){ + echo ''."\n"; +} +function lastRSS_ajax(){ + emLoadJQuery(); + echo ''."\n"; + echo ''."\n"; +} +function lastRSS_adminUpdate(){ + echo ''."\n"; +} +function lastRSS_menu(){ + echo ''; +} +function lastRSS_backup(){ + global $DB, $tables; + $is_exist_rssfeeds_query = $DB->query('show tables like "'.DB_PREFIX.'rssfeeds"'); + $is_exist_rsslogs_query = $DB->query('show tables like "'.DB_PREFIX.'rsslogs"'); + if($DB->num_rows($is_exist_rssfeeds_query) != 0) array_push($tables, 'rssfeeds'); + if($DB->num_rows($is_exist_rsslogs_query) != 0) array_push($tables, 'rsslogs'); +} +addAction('data_prebakup', 'lastRSS_backup'); +addAction('index_head', 'lastRSS_css'); +addAction('index_loglist_top', 'displayLogIndex'); +addAction('index_footer', 'lastRSS_ajax'); +addAction('adm_head', 'lastRSS_adminUpdate'); +addAction('adm_sidebar_ext', 'lastRSS_menu'); +?> \ No newline at end of file diff --git a/lastRSS_callback.php b/lastRSS_callback.php new file mode 100644 index 0000000..1bc5d7f --- /dev/null +++ b/lastRSS_callback.php @@ -0,0 +1,44 @@ +query('show tables like "'.DB_PREFIX.'rssfeeds"'); + $is_exist_rsslogs_query = $DB->query('show tables like "'.DB_PREFIX.'rsslogs"'); + $dbcharset = 'utf8'; + $type = 'MYISAM'; + $add = $DB->getMysqlVersion() > '4.1' ? "ENGINE=".$type." DEFAULT CHARSET=".$dbcharset.";":"TYPE=".$type.";"; + $addone = "INSERT INTO ".DB_PREFIX."rssfeeds (url, title) VALUES('http://xiaosong.org/rss.php', '快乐忆站')"; + if($DB->num_rows($is_exist_rssfeeds_query) == 0){ + $sql_rssfeeds = " +CREATE TABLE `".DB_PREFIX."rssfeeds` ( +`id` int(10) NOT NULL AUTO_INCREMENT, +`url` text NOT NULL, +`title` varchar(255) NOT NULL, +PRIMARY KEY (`id`) +)".$add; + $DB->query($sql_rssfeeds); + $DB->query($addone); + + } + if($DB->num_rows($is_exist_rsslogs_query) == 0){ + $sql_rsslogs = " +CREATE TABLE `".DB_PREFIX."rsslogs` ( +`id` int(10) NOT NULL AUTO_INCREMENT, +`rssid` int(10) NOT NULL, +`log` text NOT NULL, +`hash` varchar(64) NOT NULL, +PRIMARY KEY (`id`) +)".$add; + $DB->query($sql_rsslogs); + } +} + +function callback_rm(){ + $DB = MySql::getInstance(); + $feeds = getRssFeeds(); + while ($item = $DB->fetch_array($feeds)) { + deleteFeed($item['id']); + } + $DB->query("DROP TABLE IF EXISTS ".DB_PREFIX."rssfeeds"); + $DB->query("DROP TABLE IF EXISTS ".DB_PREFIX."rsslogs"); +} +?> \ No newline at end of file diff --git a/lastRSS_class.php b/lastRSS_class.php new file mode 100644 index 0000000..b948b92 --- /dev/null +++ b/lastRSS_class.php @@ -0,0 +1,220 @@ +cache_dir != '') { + $cache_file = $this->cache_dir . '/rsscache_' . md5($rss_url); + $timedif = @(time() - filemtime($cache_file)); + if ($timedif < $this->cache_time) { + // cached file is fresh enough, return cached array + $result = unserialize(join('', file($cache_file))); + // set 'cached' to 1 only if cached file is correct + if ($result) $result['cached'] = 1; + } else { + // cached file is too old, create new + $result = $this->Parse($rss_url); + $serialized = serialize($result); + if ($f = @fopen($cache_file, 'w')) { + fwrite ($f, $serialized, strlen($serialized)); + fclose($f); + } + if ($result) $result['cached'] = 0; + } + } + // If CACHE DISABLED >> load and parse the file directly + else { + $result = $this->Parse($rss_url); + if ($result) $result['cached'] = 0; + } + // return result + return $result; + } + + // ------------------------------------------------------------------- + // Modification of preg_match(); return trimed field with index 1 + // from 'classic' preg_match() array output + // ------------------------------------------------------------------- + function my_preg_match ($pattern, $subject) { + // start regullar expression + preg_match($pattern, $subject, $out); + + // if there is some result... process it and return it + if(isset($out[1])) { + // Process CDATA (if present) + if ($this->CDATA == 'content') { // Get CDATA content (without CDATA tag) + $out[1] = strtr($out[1], array(''', ']]>'=>'')); + } elseif ($this->CDATA == 'strip') { // Strip CDATA + $out[1] = strtr($out[1], array(''', ']]>'=>'')); + } + + // If code page is set convert character encoding to required + if ($this->cp != '') + //$out[1] = $this->MyConvertEncoding($this->rsscp, $this->cp, $out[1]); + $out[1] = iconv($this->rsscp, $this->cp.'//TRANSLIT', $out[1]); + // Return result + return trim($out[1]); + } else { + // if there is NO result, return empty string + return ''; + } + } + + // ------------------------------------------------------------------- + // Replace HTML entities &something; by real characters + // ------------------------------------------------------------------- + function unhtmlentities ($string) { + // Get HTML entities table + $trans_tbl = get_html_translation_table (HTML_ENTITIES, ENT_QUOTES); + // Flip keys<==>values + $trans_tbl = array_flip ($trans_tbl); + // Add support for ' entity (missing in HTML_ENTITIES) + $trans_tbl += array(''' => "'"); + // Replace entities by values + return strtr ($string, $trans_tbl); + } + + // ------------------------------------------------------------------- + // Parse() is private method used by Get() to load and parse RSS file. + // Don't use Parse() in your scripts - use Get($rss_file) instead. + // ------------------------------------------------------------------- + function Parse ($rss_url) { + // Open and load RSS file + if ($f = @fopen($rss_url, 'r')) { + $rss_content = ''; + while (!feof($f)) { + $rss_content .= fgets($f, 4096); + } + fclose($f); + + // Parse document encoding + $result['encoding'] = $this->my_preg_match("'encoding=[\'\"](.*?)[\'\"]'si", $rss_content); + // if document codepage is specified, use it + if ($result['encoding'] != '') + { $this->rsscp = $result['encoding']; } // This is used in my_preg_match() + // otherwise use the default codepage + else + { $this->rsscp = $this->default_cp; } // This is used in my_preg_match() + + // Parse CHANNEL info + preg_match("'(.*?)'si", $rss_content, $out_channel); + foreach($this->channeltags as $channeltag) + { + $temp = $this->my_preg_match("'<$channeltag.*?>(.*?)'si", $out_channel[1]); + if ($temp != '') $result[$channeltag] = $temp; // Set only if not empty + } + // If date_format is specified and lastBuildDate is valid + if ($this->date_format != '' && ($timestamp = strtotime($result['lastBuildDate'])) !==-1) { + // convert lastBuildDate to specified date format + $result['lastBuildDate'] = date($this->date_format, $timestamp); + } + + // Parse TEXTINPUT info + preg_match("']*[^/])>(.*?)'si", $rss_content, $out_textinfo); + // This a little strange regexp means: + // Look for tag with or without any attributes, but skip truncated version (it's not beggining tag) + if (isset($out_textinfo[2])) { + foreach($this->textinputtags as $textinputtag) { + $temp = $this->my_preg_match("'<$textinputtag.*?>(.*?)'si", $out_textinfo[2]); + if ($temp != '') $result['textinput_'.$textinputtag] = $temp; // Set only if not empty + } + } + // Parse IMAGE info + preg_match("'(.*?)'si", $rss_content, $out_imageinfo); + if (isset($out_imageinfo[1])) { + foreach($this->imagetags as $imagetag) { + $temp = $this->my_preg_match("'<$imagetag.*?>(.*?)'si", $out_imageinfo[1]); + if ($temp != '') $result['image_'.$imagetag] = $temp; // Set only if not empty + } + } + // Parse ITEMS + preg_match_all("'(.*?)'si", $rss_content, $items); + $rss_items = $items[2]; + $i = 0; + $result['items'] = array(); // create array even if there are no items + foreach($rss_items as $rss_item) { + // If number of items is lower then limit: Parse one item + if ($i < $this->items_limit || $this->items_limit == 0) { + foreach($this->itemtags as $itemtag) { + $temp = $this->my_preg_match("'<$itemtag.*?>(.*?)'si", $rss_item); + if ($temp != '') $result['items'][$i][$itemtag] = $temp; // Set only if not empty + } + // Strip HTML tags and other bullshit from DESCRIPTION + if ($this->stripHTML && $result['items'][$i]['description']) + $result['items'][$i]['description'] = strip_tags($this->unhtmlentities(strip_tags($result['items'][$i]['description']))); + // Strip HTML tags and other bullshit from TITLE + if ($this->stripHTML && $result['items'][$i]['title']) + $result['items'][$i]['title'] = strip_tags($this->unhtmlentities(strip_tags($result['items'][$i]['title']))); + // If date_format is specified and pubDate is valid + if ($this->date_format != '' && ($timestamp = strtotime($result['items'][$i]['pubDate'])) !==-1) { + // convert pubDate to specified date format + $result['items'][$i]['pubDate'] = date($this->date_format, $timestamp); + } + // Item counter + $i++; + } + } + + $result['items_count'] = $i; + return $result; + } + else // Error in opening return False + { + return False; + } + } +} + +?> \ No newline at end of file diff --git a/lastRSS_config.php b/lastRSS_config.php new file mode 100644 index 0000000..a7d5278 --- /dev/null +++ b/lastRSS_config.php @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/lastRSS_setting.php b/lastRSS_setting.php new file mode 100644 index 0000000..58c21c1 --- /dev/null +++ b/lastRSS_setting.php @@ -0,0 +1,148 @@ + + +
    Rss订阅 参数设置 +插件设置完成 +
    +
    +
    +

    缓存时间: 单位为秒,留空或“0”表示不缓存,推荐设置大于“1200”

    +

    显示条数: 前台轮播显示的条数,推荐大于“1”

    +

    checked /> 使用网址缩短服务来缩短RSS日志的链接(已存入数据库的链接不变),需服务器开启curl,开启会增加程序运行时间

    +

    + +

    +

    checked /> 新窗口打开前台显示的RSS日志链接 

    +
    +
    RSS 导入
    +
    +
    +

    RSS URL:   标题(不填则插件自动获取):  

    +
    +num_rows($feeds) != 0): +?> +
    管理:(双击单行可对应修改该RSS的URL和标题)
    +
    +
    +

    RSS URL:   标题:  

    +
    +
      +fetch_array($feeds)) { +?> +
    1. + 删除 + 《》 URL: +
    2. + +
      暂无RSS地址,请导入
      + +
    + +"; + $file = EMLOG_ROOT.'/content/plugins/lastRSS/lastRSS_config.php'; + @ $fp = fopen($file, 'wb') OR emMsg('读取文件失败,如果您使用的是Unix/Linux主机,请修改文件/content/plugins/lastRSS/lastRSS_config.php的权限为777。如果您使用的是Windows主机,请联系管理员,将该文件设为everyone可写'); + @ $fw = fwrite($fp,$data) OR emMsg('写入文件失败,如果您使用的是Unix/Linux主机,请修改文件/content/plugins/lastRSS/lastRSS_config.php的权限为777。如果您使用的是Windows主机,请联系管理员,将该文件设为everyone可写'); + fclose($fp); + header("Location:plugin.php?plugin=lastRSS&setting=true"); +} +?> diff --git a/lastRSS_show.php b/lastRSS_show.php new file mode 100644 index 0000000..f32360f --- /dev/null +++ b/lastRSS_show.php @@ -0,0 +1,13 @@ + \ No newline at end of file