MENU

Catalog

    博客外链图片已恢复

    January 27, 2021 • Read: 1083 • 默认分类

    我从一个多月前开始发现石墨的粘贴图片功能很好用,可以直接Ctrl + V把图片放上去。
    早期的时候我写博客为了避免麻烦都是不贴图片的,发现了这个功能之后就基本上是在石墨上写作,然后导出markdown文件。

    但是近段时间,石墨似乎对图片外链做了限制(增加了对访问来源的检测),所以我部分文章中全部图片无法显示。

    到了今天,我突发奇想要修复这个图片的问题,于是就百度搜索了一下typecho在这方面的插件,搜索到了一款插件,但当然不能拿来直接用,于是我对其代码进行了大改,最后达到效果是让文章在编辑的时候都会自动替换外链图片信息。

    不得不提的是,我这款主题似乎还对typecho的插件函数进行了hook,导致我刚开始测试的时候死活用不了,后来搜索终于找到了解决方法。
    感觉现在有点看厌了这款主题,似乎没刚接触的时候认为的好看,但是短时间内应该不会换了,因为找个新主题也挺麻烦的。
    而且由于现在写作都是导出markdown,似乎可以考虑一下一些静态博客(那也是以后的事情了,毕竟现在的文章数量,还没能到让这个系统变得臃肿的程度)

    还有不知道为啥,上传目录必须要给执行权限才能够成功的创建文件,这是啥原因有人知道吗?

    我放一下源码应该不会被rce吧...按照我的水平,不知道要怎么入手来攻击。

    这个脚本是为了适应我目前的主题而修改的,如果其他主题需要使用,请参照 https://www.liuguogy.com/archives/mirages-plugin-conflict-solution.html 把相关代码替换回去

    <?php
    if (!defined('__TYPECHO_ROOT_DIR__')) exit;
    /**
     * 自动下载保存远程图片
     *
     * @package AutoSaveImage
     * @author wjh
     * @version 1.0.0
     * @link http://blog.wjhwjhn.com
     */
    class AutoSaveImage_Plugin implements Typecho_Plugin_Interface
    {
        //上传文件目录(统一目录,不再按日期新建目录,查询到文件已存在时则不再处理)
        const UPLOAD_DIR = '/usr/uploads/image/';
        /**
         * 激活插件方法,如果激活失败,直接抛出异常
         *
         * @access public
         * @return void
         * @throws Typecho_Plugin_Exception
         */
        public static function activate()
        {
            //下载保存远程图片
            Typecho_Plugin::factory('Mirages_Plugin')->writePost  = array('AutoSaveImage_Plugin', 'saveFile');
            Typecho_Plugin::factory('Mirages_Plugin')->writePage  = array('AutoSaveImage_Plugin', 'saveFile');
    
            /*
            如果你不用Mirages插件的话,就把上面的两行换成下面的部分
            Typecho_Plugin::factory('Widget_Contents_Post_Edit')->write = array('AutoSaveImage_Plugin', 'saveFile');
            Typecho_Plugin::factory('Widget_Contents_Page_Edit')->write = array('AutoSaveImage_Plugin', 'saveFile');
            */
        }
    
        /**
         * 获取插件配置面板
         *
         * @access public
         * @param Typecho_Widget_Helper_Form $form 配置面板
         * @return void
         */
        public static function config(Typecho_Widget_Helper_Form $form)
        {
    
        }
    
        /**
         * 禁用插件方法,如果禁用失败,直接抛出异常
         *
         * @static
         * @access public
         * @return void
         * @throws Typecho_Plugin_Exception
         */
        public static function deactivate()
        {
    
        }
        /**
         * 个人用户的配置面板
         *
         * @access public
         * @param Typecho_Widget_Helper_Form $form
         * @return void
         */
        public static function personalConfig(Typecho_Widget_Helper_Form $form)
        {
    
        }
    
        /**
         * 下载保存远程图片
         *
         * @access public
         * @param array $post 数据结构体
         * @return array
         */
        public static function saveFile($post)
        {
            $options = Typecho_Widget::widget('Widget_Options');
            $siteUrl = $options->siteUrl;
            $text = $post['text'];
    
            $urls = self::getImageFromText($text);
            if(!isset($urls) || count($urls) == 0) return $post;
    
            $save_dir = self::UPLOAD_DIR;
            $save_dir = parse_url($save_dir, PHP_URL_PATH);
            $uploadDir = Typecho_Common::url($save_dir,  __TYPECHO_ROOT_DIR__);
            //创建上传目录
            if (!is_dir($uploadDir))
            {
                if ([email protected]($uploadDir, 0744))
                {
                    throw new Typecho_Widget_Exception(_t('上传目录无法创建, 请手动创建安装目录下的 %s 目录, 并将它的权限设置为可写然后继续尝试', $uploadDir));
                }
            }
            //获取相对路径
            $domain = trim($_SERVER['HTTP_HOST']);
            foreach ($urls as $url)
            {
                $tmp_url = strtolower(trim($url));
                if (strpos($tmp_url, '://') === false || strpos($tmp_url, $domain) !== false) continue;
                $hash = md5($url);
                $array = pathinfo($url);
                $ext = $array['extension'];
                $filename = $hash.'.'.$ext;//生成要保存在本地的文件名
                $dst_path = $uploadDir.$filename;//本地保存绝对路径
                $dst_file = $save_dir.$filename;//相对保存路径
                $dst_url = $siteUrl.$dst_file;//生成的本地文件url
                if (!file_exists($dst_path))
                {
                    //不存在文件则下载
                    self::get_remote_file($url, $dst_path);
                }
                if (file_exists($dst_path))
                {
                    //有文件了,替换内容
                    $text = str_ireplace($url, $dst_url, $text);
                }
            }
            $text = str_replace('!thumbnail', '', $text); //石墨外链特殊处理
            $post['text'] = $text;
            return $post;
        }
    
        static function getImageFromText($text)
        {
            // $patten = '!(http|https)://[a-z0-9\-\.\/]+\.(?:jpe?g|png|gif)!Ui';
            $patten = '!(https?:\/\/.*\.(?:png|jpg|bmp|jpeg|gif|webp))!';
            preg_match_all($patten, $text, $arr);
            $result = [];
            if(isset($arr) && count($arr) > 0)
            {
                foreach ($arr as $key => $value)
                {
                    if(count($value) > 0)
                    {
                        foreach ($value as $v)
                        {
                            if(!in_array($v,$result))
                                $result[] = $v;
                        }
                    }
                }
            }
            return $result;
        }
        /**
         * 下载远程文件
         *
         */
        static function get_remote_file($url, $save)
        {
            if ( trim($save) === '' || trim($url) === '' ) return false;
            $fp = fopen ($save, "wb");
            if (!$fp) throw new Typecho_Widget_Exception(_t('上传目录无法写入文件:%s', $save));
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
            curl_setopt($ch, CURLOPT_REFERER, $url);
            $img = curl_exec($ch);
            fwrite($fp, $img);
            curl_close($ch);
            fclose($fp);
            return true;
        }
    
    }
    

    ==如果代码有问题,麻烦请告知/高抬贵手,毕竟我这博客经常忘记备份,数据被删可就麻烦了==

    Archives QR Code
    QR Code for this page
    Tipping QR Code