找到9685个回复 (用户: 老虎会游泳)
  • 已知问题7

    如果安装了Steam但是没有登录,Wine游戏助手可能会报错:

    2022-05-17 23:00:11,865: Starting Lutris 0.5.10.4
    2022-05-17 23:00:11,899: No folder at /home/hu60/.local/share/net.winegame.client/runners/retroarch/
    2022-05-17 23:00:11,976: Using NVIDIA drivers 510.68.02 for x86_64
    2022-05-17 23:00:11,977: GPU: NVIDIA GeForce RTX 3080 Ti
    2022-05-17 23:00:11,977: GPU: 10DE:2208 7377:140A (nvidia drivers)
    2022-05-17 23:00:12,200: Error while completing task <bound method LutrisInitDialog.initialize of <dialogs.LutrisInitDialog object at 0x7f1bb253ea68 (lutris+gui+dialogs+LutrisInitDialog at 0x1f442b0)>>: <class 'FileNotFoundError'> [Errno 2] 没有那个文件或目录: '/home/hu60/.local/share/Steam/userdata/352964089/config/shortcuts.vdf'
      File "/opt/apps/net.winegame.client/files/lib/lutris/lutris/util/jobs.py", line 34, in target
        result = self.function(*args, **kwargs)
      File "/opt/apps/net.winegame.client/files/lib/lutris/lutris/gui/dialogs/__init__.py", line 197, in initialize
        init_lutris()
      File "/opt/apps/net.winegame.client/files/lib/lutris/lutris/startup.py", line 213, in update_runtime
        update_all_artwork()
      File "/opt/apps/net.winegame.client/files/lib/lutris/lutris/util/steam/shortcut.py", line 152, in update_all_artwork
        with open(shortcut_path, "rb") as shortcut_file:
    2022-05-17 23:00:17,790: Shutting down Lutris
    
  • 求一个ish shell的ios安装包ipa
    228点击 / 05-15 15:22发布 / 1天前回复 / /

    @MFVPNHAHA,我没有苹果设备

  • 给葫芦林的一点建议。
    506点击 / 05-14 20:54发布 / 1天前回复 / /

    但是,如果只是“这些地方的分割希望能优化一下”,恕我不知道该优化成什么样子,是增大间距,还是减小间距?是增粗分割线,减弱分割线,还是改变分割线样式?多粗,多弱,什么颜色?

    不要把设计自由留给我。我不会设计,只会实施。

  • 给葫芦林的一点建议。
    506点击 / 05-14 20:54发布 / 1天前回复 / /

    或者,如果不会代码也不会作图,又还是想改,那可以给我发精确的修改指令,比如:
    把12楼和13楼的间隔增大10像素,其中,分割线以上5像素,分割线以下5像素。
    这种我可以做到,我会先给你做个网页插件,让你看到效果。如果你满意,我可以向全站推广。

  • 给葫芦林的一点建议。
    506点击 / 05-14 20:54发布 / 1天前回复 / /

    除了 Stylish 插件,还可以直接把代码粘贴到这里来修改主题:https://hu60.cn/q.php/addin.webplug.html
    我需要的就是这样的代码,如果想让我改进主题,最好先自己实现出来,然后把代码提交给我。
    如果真的不会HTML/CSS,那就把设计图提交给我,我尝试为你实现。
    如果没有代码也没有设计图,只有文字描述,凭我的美术水平,肯定不会有让你满意的实现,在这一点上你一定要相信我,希望有多大失望就有多大。

  • 已知问题5(已在0.5.10.4中修复)

    如果安装脚本的files区域为空(不下载任何文件),那么installer区域也会被置为空,导致安装未进行。

    该错误由lutris开发者在0.5.10引入。

  • 已知问题4(已在0.5.10.4中修复)

    wine版本管理页面的排版很混乱

    图片.png
  • 给葫芦林的一点建议。
    506点击 / 05-14 20:54发布 / 05-14 23:51回复 / /

    @花祭,jhin主题不是我设计的,如果要我动手改,在没有像素级设计图的情况下,肯定会改得比现在还差。我只能改出经典主题的水平,是什么水平我想你也看到了。

  • 给葫芦林的一点建议。
    506点击 / 05-14 20:54发布 / 05-14 23:38回复 / /

    @花祭

    1. 需要可直接实施的,精确到像素的设计图或者CSS代码。最好是CSS代码,因为可能无法按设计图精确实现。不要指望 @老虎会游泳 会把文字转换成理想的设计。要了解 @老虎会游泳 的网页设计水平,切换到经典主题即可。

    2. 虎绿林没有友链,首页的是虎友网站展示。只要还有虎友在做网站,还有虎友想在虎绿林首页展示他们的网站,虎绿林首页就会继续为他们保留该区域。

    3. 需要可直接实施的,精确到像素的设计图或者CSS代码。最好是CSS代码,因为可能无法按设计图精确实现。不要指望 @老虎会游泳 会把文字转换成理想的设计。要了解 @老虎会游泳 的网页设计水平,切换到经典主题即可。

  • @Albedo,👌

  • @花祭,那不是可以直接给虎绿林用的效果图,我需要的效果图是真正的虎绿林帖子页面,不需要做任何添加删除修改就能用的。比如,我肯定要把楼层序号放上去,但是网易没有,所以需要我设计。我选的位置和字体肯定不会好看。

  • @花祭,我对界面设计没有任何想法,我只能等待有人提供效果图或者CSS代码(最好是CSS代码,因为效果图不一定能完美实现),这样我就能直接应用了。只提供文字版的建议没有什么用,我只会改得更难看。

  • @花祭,都是什么样的?我只看过微博的。

  • @姜辰,把配置文件里的变量和所需的类复制过来就行了。注意$CC_DATA必须指定到tmpfs内,否则性能会很差,不能防CC。如果没有条件使用tmpfs,可以改用memcached

    部署cc.php的方法很简单,把这个代码粘贴到程序的主配置文件(config.php,就是那个包含数据库配置的文件)开头即可。

    <?php
    
    
    /////////////////// 防止CC攻击 ///////////////////
    
    /**
     * 是否启用防CC模块
     */
    $ENABLE_CC_BLOCKING = true;
    
    /**
     * 使用memcache
     */
    $CC_USE_MEMCACHE = false;
    
    /**
     * CC行为记录文件
     *
     * 请指定到tmpfs文件系统内,否则性能会很差。
     * 如系统为Windows,请使用memcache,这样就不需要指定该文件。
     */
    $CC_DATA = '/dev/shm/hu60-cc.dat';
    
    /**
     * CC行为日志
     * 
     * 设为null禁用
     */
    $CC_BLOCK_LOG = '/tmp/hu60-cc.log';
    
    /**
     * 正常访问日志
     *
     * 设为null禁用
     */
    $CC_ACCESS_LOG = null;
    
    /**
     * CC判定范围
     */
    $CC_LIMIT = [
        10,  // n秒内
        50, // 最多访问n次
    ];
    
    /**
     * 特定IP判定范围
     */
    $CC_IP_LIMIT = [
        // 设置特定IP n秒最多能访问的次数
        '127.0.0.1' => 100,
    ];
    
    /**
     * 真实IP
     * 
     * 开头加#禁用,删除#启用
     */
    
    // 无代理时使用
    $CC_REAL_IP = $_SERVER['REMOTE_ADDR'];
    
    // 采用CloudFlare或百度云加速代理时使用
    #$CC_REAL_IP = $_SERVER['HTTP_CF_CONNECTING_IP'];
    
    
    /* 缓存设置 */
    /**
     * 缓存类型
     */
    define('CACHE_TYPE', 'memcached');
    
    /* memcached设置($CC_USE_MEMCACHE = true 时需要设置) */
    /** 服务器名称 */
    define('MEMCACHED_NAME', 'hu60');
    /** 服务器主机名 */
    define('MEMCACHED_HOST', 'localhost');
    /** 服务器端口 */
    define('MEMCACHED_PORT', 11211);
    
    # 防止CC攻击
    hu60_cc_prevent();
    
    function hu60_cc_prevent()
    {
    	global $ENABLE_CC_BLOCKING,
    		$CC_DATA,
    		$CC_LIMIT, // 数组, $CC_LIMIT[0] 秒内最多访问 $CC_LIMIT[1] 次
    		$CC_USE_MEMCACHE,
    		$CC_BLOCK_LOG,
    		$CC_ACCESS_LOG,
    		$CC_IP_LIMIT,
    		$CC_REAL_IP;
    
    	// 记录数,决定记录文件的大小
    	$CC_RECORD_NUM = 256 * 256;
    	// 单个记录字节数
    	$CC_RECORD_SIZE = 6;
    
    	if (!$ENABLE_CC_BLOCKING) {
    		return;
    	}
    
    	if (empty($CC_REAL_IP)) {
    		$CC_REAL_IP = $_SERVER['REMOTE_ADDR'];
    	}
    
    	if (isset($CC_IP_LIMIT[$CC_REAL_IP])) {
    		$CC_LIMIT[1] = $CC_IP_LIMIT[$CC_REAL_IP];
    	}
    
    	// 当前时间,uint16
    	$currTime = unpack('v', pack('v', $_SERVER['REQUEST_TIME']));
    	$currTime = $currTime[1];
    
    	// IP hash,代表记录在文件中的位置
    	$ipHash = (hexdec(substr(md5($CC_REAL_IP), 0, 8)) % $CC_RECORD_NUM) * $CC_RECORD_SIZE;
    
    	if ($CC_USE_MEMCACHE) {
    		$key = "cc/$ipHash";
    		$record = cache::get($key);
    	} else {
    		if (!is_file($CC_DATA) || filesize($CC_DATA) < $CC_RECORD_NUM * $CC_RECORD_SIZE) {
    			file_put_contents($CC_DATA, str_repeat("\0", $CC_RECORD_NUM * $CC_RECORD_SIZE));
    		}
    		$CC_DATA = fopen($CC_DATA, 'r+');
    		fseek($CC_DATA, $ipHash);
    		$record = fread($CC_DATA, $CC_RECORD_SIZE);
    	}
    
    	$record = unpack('v3', $record);
    	// 首次访问时间
    	$firstAccTime = $record[1];
    	// 最后访问时间
    	$lastAccTime = $record[2];
    	// 访问次数
    	$accCount = ++$record[3];
    
    	if ($firstAccTime <= 0) {
    		$firstAccTime = $currTime;
    	}
    	if ($lastAccTime <= 0) {
    		$lastAccTime = $currTime;
    	}
    
    	$timeDiff = $currTime - $firstAccTime;
    
    	if ($timeDiff < 0) { // uint16溢出时会发生
    		$firstAccTime = $currTime;
    		$lastAccTime = $currTime;
    		$accCount = 1;
    		$timeDiff = $CC_LIMIT[0];
    	} elseif ($timeDiff < $CC_LIMIT[0]) { // 不够n秒,补充到n秒
    		$timeDiff = $CC_LIMIT[0];
    	}
    
    	$accRate = $accCount / $timeDiff;
    	$allowRate = $CC_LIMIT[1] / $CC_LIMIT[0];
    
    	$block = false;
    	if ($accRate > $allowRate) {
    		$block = true;
    		// 10 秒内访问 434 次
            // 设访问速度下降到每秒 5 次的最短等待时间是 t
            // (434 + 1) / (10 + t) = 5
    		// 10 + t = (434 + 1) / 5
            // t = (434 + 1) / 5 - 10
    		$needWaitSeconds = ceil(($accCount + 1) / $allowRate - $timeDiff);
    		hu60_cc_output($needWaitSeconds, $timeDiff, $accCount, $accRate, $allowRate);
    		// 超速访问日志
    		if ($CC_BLOCK_LOG) {
    			hu60_cc_log($CC_BLOCK_LOG, '超速', $timeDiff, $accCount);
    		}
    	} else {
    		// 正常用户访问日志
    		if ($CC_ACCESS_LOG) {
    			hu60_cc_log($CC_ACCESS_LOG, '正常', $timeDiff, $accCount);
    		}
    	}
    
    	$lastTimeDiff = $currTime - $lastAccTime;
    	// 上次访问距离这次访问经过了很久,且未超速,重置统计
    	if (!$block && ($lastTimeDiff > $CC_LIMIT[0] || $lastTimeDiff < 0)) {
    		$firstAccTime = $currTime;
    		$lastAccTime = $currTime;
    		$accCount = 1;
    		$timeDiff = $CC_LIMIT[0];
    	}
    
    	$record = pack('v3', $firstAccTime, $currTime, $accCount);
    	if ($CC_USE_MEMCACHE) {
    		cache::set($key, $record);
    	} else {
    		fseek($CC_DATA, $ipHash);
    		fwrite($CC_DATA, $record);
    		fclose($CC_DATA);
    	}
    
    	if ($block) {
    		exit;
    	}
    }
    
    function hu60_cc_log($file, $stat, $timeDiff, $accCount)
    {
    	global $CC_REAL_IP;
    
    	$fp = fopen($file, 'a+');
    	fwrite($fp, "[" . date('Y-m-d H:i:s', $_SERVER['REQUEST_TIME']) . "] <$stat,{$timeDiff}秒{$accCount}次> $CC_REAL_IP\t[PATH] $_SERVER[REQUEST_URI]\t[REF] $_SERVER[HTTP_REFERER]\n");
    	fclose($fp);
    }
    
    function hu60_cc_output($needWaitSeconds, $timeDiff, $accCount, $accRate, $allowRate)
    {
    	global $CC_LIMIT, $CC_REAL_IP;
    
    	header('HTTP/1.1 503 Service Unavailable');
        header('Retry-After: '.$needWaitSeconds);
    	header('Content-Type: text/html; charset=UTF-8');
    ?>
    <!DOCTYPE html>
    <html>
    <head>
    	<meta charset="utf-8" />
    	<title>刷新不规范,虎友两行泪</title>
    </head>
    <body>
    	<h4>
    		虎绿林第三区交通委提醒您:<br/>
    		网址千万条,耐心第一条。<br/>
    		刷新不规范,虎友两行泪。
    	</h4>
    	虎绿林低速网络限速<?=$CC_LIMIT[0]?>秒内最多访问<?=$CC_LIMIT[1]?>次(每秒<?=round($allowRate, 2)?>次)。<br/>
    	您在<?=$timeDiff?>秒内访问了<?=$accCount?>次(每秒<?=round($accRate, 2)?>次),您已超速。<br/>
    	作为惩罚,吊销您的虎绿林通行证<?=$needWaitSeconds?>秒钟,在这段时间内您将不能访问虎绿林。<br/>
    	您的IP地址为<?php echo $CC_REAL_IP; ?>,违章记录已存档。
    	请勿反复刷新,否则违章记录将延续。<br/>
    </body>
    </html>
    <?php
    }
    
    interface cacheInterface
    {
        public function get($key);
    
        public function set($key, $value, $timeout = 0);
    
        public function del($key);
    }
    
    class cacheMemcached implements cacheInterface
    {
        /* Memcached 设置 */
        protected static $memcachedName = MEMCACHED_NAME;
        protected static $memcachedServers = [
            [MEMCACHED_HOST, MEMCACHED_PORT]
        ];
    
        protected $memcached = null;
    
        public function __construct()
        {
            $this->memcached = new Memcached(self::$memcachedName);
            $this->memcached->addServers(self::$memcachedServers);
        }
    
        public function get($key)
        {
            return $this->memcached->get($key);
        }
    
        public function set($key, $value, $timeout = 0)
        {
            return $this->memcached->set($key, $value, $timeout);
        }
    
        public function del($key)
        {
            return $this->memcached->delete($key);
        }
    }
    
    class cache
    {
        protected static $cacheClassName = CACHE_TYPE;
        protected static $instance = null;
    
        static protected function getInstance()
        {
            if (self::$instance == null) {
                $cacheClass = 'cache' . self::$cacheClassName;
                self::$instance = new $cacheClass();
            }
    
            return self::$instance;
        }
    
        static public function get($key)
        {
            return self::getInstance()->get($key);
        }
    
        static public function set($key, $value, $timeout = 0)
        {
            return self::getInstance()->set($key, $value, $timeout);
        }
    
        static public function del($key)
        {
            return self::getInstance()->del($key);
        }
    }
    
    ?>
    
  • @胡图图

    为什么这都能吵起来

    因为“删除 goto 是一种宗教选择”,而有些开发人员陷入了狂信

  • @胡图图,可以看看4楼的代码2和代码1相比多了什么,它在恰当的地方添加了
    success = false;

    success = true;

    这种无中生有的新增,需要真正的人类智能。转换器要先学会像人类一样思考,学会类比、等价和推理,才能完整这种程度的重构。

  • @胡图图,编译器所做的事情,是把其他一切分支跳转代码转换成goto。所以在别人直接使用goto的情况下,你怎么可能简单的用其他代码进行模拟?它们不是等价的,不是一一对应的,只有goto的某些特定使用方式能转换成if/switch/while,但是开发人员之所以想使用goto,一定是因为if/switch/while的表达能力不满足他们的要求。所以可以这么说,除非程序员真的想滥用goto,否则代码中出现的每个goto都难以自动转换成其他表现形式。

  • @胡图图

    为什么没有人自己设计一个"goto killer" 把所有带goto的代码,都转换成不带goto的代码?

    如果可以优雅地转换,我们就不会提出这种批评了:

    “删除 goto 是一种宗教选择,而不是技术选择。”

    “如果你发现自己为了避免使用goto而不得不采取真正愚蠢的方案,那就应该停下来。”

    转换后的代码一定会比原始代码更蠢,因为一切用于“模拟”goto的代码本质上都是goto。if是goto,while是goto,switch是goto,foreach是goto,甚至函数调用实际上也是goto,只是它们用更精美的包装呈现给你了而已。

    所以在那些真正需要非结构化跳转的地方,想用更高层次的“结构化跳转”(if/while/函数调用)模拟goto,只能得到愚蠢的代码,甚至根本难以实现,远比不上直接大大方方的使用goto。

    因此,就连中毒最深最讨厌goto的人,也没有办法实现这个自动转换器。

  • @胡图图,请仔细阅读4楼的代码及其评论。

    实际上,编译器生成的代码几乎完全一致。

    解释一下这句话:就是说,编译后两者生成的程序里,目标代码(机器语言代码)完全相同。

    但是两个代码哪个更清晰,一目了然。

  • https://stackoverflow.com/a/741517

    GOTO 仍被认为有害吗

    • tylerl 2009年4月12日 9:32

    在某些情况下,goto可以为“真正的”异常处理提供一种替代。

    考虑以下代码:

    ptr = malloc(size);
    if (!ptr)
      goto label_fail;
    bytes_in = read(f_in,ptr,size);
    if (bytes_in =< 0)
      goto label_fail;
    bytes_out = write(f_out,ptr,bytes_in);
    if (bytes_out != bytes_in)
      goto label_fail;
    

    显然,这段代码被简化以减少空间占用,所以不要太过在意细节。

    但是考虑一下我在生产代码中看到过多次的替代方法,看看编码人员为了避免使用goto而荒谬的程度:

    success = false;
    do {
      ptr = malloc(size);
      if (!ptr)
        break;
      bytes_in = read(f_in,ptr,size);
      if (count =< 0)
        break;
      bytes_out = write(f_out,ptr,bytes_in);
      if (bytes_out != bytes_in)
        break;
      success = true;
    } while (false);
    

    从功能上讲,这两段代码完全相同。实际上,编译器生成的代码几乎完全一致。然而,在热切地安抚 Nogoto(可怕的学术谴责之神)的同时,这位程序员完全打破了循环所代表的基本习惯,并对代码的可读性做了真正糟糕的事情。这并不比直接使用goto更好。

    所以,故事的寓意是,如果你发现自己为了避免使用goto而不得不采取真正愚蠢的方案,那就应该停下来。