著作权代码收集工具

使用Python编写,可以设置源码目录,排除目录,收集文件类型,输出目标文件,是否允许空白,编码等。

使用示例:

python zhuzuoquan.py -s D:\pythoncode\projectname \
-e debug,release \
-t .h,.cpp \
-en gb18030 \
-o result.txt

zhuzuoquan.py 代码

#!/usr/bin/python
# -*- coding: utf-8 -*-

import argparse
import os

parser = argparse.ArgumentParser(
    description='著作权代码收集工具', usage='''
    zhuzuoquan.py -s 源码目录 -e 排除目录 -t 文件类型 -o 输出文件
    ''')
parser.add_argument('-s', help='源文件目录', required=True)
parser.add_argument('-e', help='排除目录,多个用半角逗号分割', )
parser.add_argument('-t', help='扩展名,多个用半角逗号分割', required=True)
parser.add_argument('-o', help='输出文件')
parser.add_argument('-el', help='允许空白行')
parser.add_argument('-en', help='编码', default='utf-8')

def filter_files(root_dir, excluded_dirs, allow_types):
    valid_files = []
    for root, dirs, files in os.walk(root_dir):

        for f in files:
            excluded = False
            p = os.path.join(root,f)
            d = p[root_dir.__len__():]
            for ex in excluded_dirs:
                if d.startswith(ex):
                    excluded = True

            allow = False
            for t in allow_types:
                if f.endswith(t):
                    allow = True
            if allow and not excluded:
                filepath = os.path.join(root, f)
                valid_files.append(filepath)
    return valid_files

if __name__ == '__main__':
    args = parser.parse_args()

    if args.e:
        excluded_dirs = args.e.split(',')
    else:
        excluded_dirs = []

    allow_types = args.t.split(',')

    root_dir = args.s

    output_file = args.o

    allow_empty_line = args.el

    encoding = args.en

    files = filter_files(root_dir, excluded_dirs, allow_types)
    total_files = total_lines = 0
    if output_file:
        with open(output_file, encoding=encoding, mode='w') as op:
            op.write("")

    for f in files:
        total_files = total_files + 1
        try:
            with open(f, encoding=encoding) as fh:
                content = fh.read()
                if not allow_empty_line:
                    content = "\n".join([s for s in content.splitlines() if s.strip()])
                lines = len(content.splitlines())
                relative_path = f[root_dir.__len__():]
                print(relative_path, lines)
                total_lines = total_lines + lines
                if output_file:
                    fh.seek(0)
                    with open(output_file, encoding=encoding, mode='a+') as op:
                        op.write(relative_path + ":\n\n" + content + "\n\n\n")
        except:
            pass

    print("Total: files %d, lines %d" % (total_files, total_lines))

将chrome的copy as cURL转换成Python、PHP、Go等十多种语言代码

chrome提供了非常方便的复制功能,可以将页面请求复制为curl命令行或者nodejs fetch等。那么,能不能得到其他比如PHP,Go,Python版本的代码呢?答案是可以,且只需两步。

获取curl代码

在 Chrome 开发工具的网络选项卡中,右键单击请求,然后单击“复制” > “复制为 cURL (命令)”。

file

得到

curl 'https://c4ys.com/' -H 'authority: c4ys.com'...

将cURL命令转化成其他语言代码

浏览器打开 https://cURL.trillworks.com/ 就可以将 cURL 命令转换成 Python、 NodeJS 、Go、 PHP等十多个语言版本了。

file

软著申请统计代码行数

统计代码行数

find  . \
\( -path ./web -o -path ./runtime -o -path ./config \) -prune -o \
\( -name "*.php" -o -name "*.js" -o -name "*.css" -o -name "*.scss" \) \
| xargs wc -l

web,runtime,config为需要排除的目录

php,js,css,scss为源码文件扩展名

IntelliJ/PhpStorm/PyCharm等启动报错Cannot Lock System Folders

解决办法

Disable hyper-v (which will required a couple of restarts)

dism.exe /Online /Disable-Feature:Microsoft-Hyper-V

When you finish all the required restarts, reserve the port you want so hyper-v doesn’t reserve it back

netsh int ipv4 add excludedportrange protocol=tcp startport=50051  numberofports=1

Re-Enable hyper-V (which will require a couple of restart)

dism.exe /Online /Enable-Feature:Microsoft-Hyper-V /All

when your system is back, you will be able to bind to that port successfully.

参考

Windows Terminal支持ssh,git-bash,wsl, msys

打开 profiles.json 配置文件

打开Windows Terminal,点击设置,可以看到,复制增加一组ssh配置,然后修改三个地方。

{
// Make changes here to the powershell.exe profile.
"guid": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}",
"name": "Windows PowerShell",
"commandline": "powershell.exe",
"hidden": false
},

修改guid

利用powershell可以生成guid

powershell -Command "[guid]::NewGuid().ToString()"

修改名字

任意,可以是系统名字,IP,用户名等,如 username@aliyun-bj

修改commandline

ssh -i C:\user\username\id_rsa username@aliyun-bj

其中i参数后面为证书存放位置,如果试用密码登录可以不填

完整SSH支持(图标,配色等)

 {
     "acrylicOpacity" : 1,
     "closeOnExit" : true,
     "colorScheme" : "One Half Dark",
     "commandline" : "ssh username@aliyun-bj",
     "cursorColor" : "#FFFFFF",
     "cursorShape" : "bar",
     "fontFace" : "Consolas",
     "fontSize" : 14,
     "guid" : "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}",
     "historySize" : 9001,
     "icon" : "ms-appx:///ProfileIcons/{9acb9455-ca41-5af7-950f-6bca1bc9722f}.png",
     "name" : "username@aliyun-bj",
     "padding" : "0, 0, 0, 0",
     "snapOnInput" : true,
     "startingDirectory" : "",
     "useAcrylic" : false
 }

 支持Git-bash

{
            "guid": "{7f0152b2-c491-4bb6-8a87-610352d630c8}",
            "acrylicOpacity" :1,
            "closeOnExit" : true,
            "colorScheme" : "Campbell",
            "commandline" : "\"%PROGRAMFILES%\\Git\\Bin\\bash.exe\" -i -l",
            "cursorColor" : "#FFFFFF",
            "cursorShape" : "bar",
            "fontFace" : "Consolas",
            "fontSize" : 14,
            "historySize" : 9001,
            "icon" : "%PROGRAMFILES%\\Git\\mingw64\\share\\git\\git-for-windows.ico",
            "name" : "Git-bash",
            "padding" : "0, 0, 0, 0",
            "snapOnInput" : true,
            "startingDirectory" : "%USERPROFILE%",
            "useAcrylic" : true
        }

WSL

        {
            "guid": "{2c4de342-38b7-51cf-b940-2309a097f518}",
            "hidden": false,
            "name": "Ubuntu",
            "source": "Windows.Terminal.Wsl"
        },

msys2

 {
                "guid": "{17da3cac-b318-431e-8a3e-7fcdefe6d114}",
                "name": "MINGW64 / MSYS2",
                "commandline": "C:/msys64/msys2_shell.cmd -defterm -here -no-start -mingw64",
                "startingDirectory": "C:/msys64/home/%USERNAME%",
                "icon": "C:/msys64/mingw64.ico",
                "fontFace": "Lucida Console",
                "fontSize": 9
            },
            {
                "guid": "{2d51fdc4-a03b-4efe-81bc-722b7f6f3820}",
                "name": "MINGW32 / MSYS2",
                "commandline": "C:/msys64/msys2_shell.cmd -defterm -here -no-start -mingw32",
                "startingDirectory": "C:/msys64/home/%USERNAME%",
                "icon": "C:/msys64/mingw32.ico",
                "fontFace": "Lucida Console",
                "fontSize": 9
            },
            {
                "guid": "{71160544-14d8-4194-af25-d05feeac7233}",
                "name": "MSYS / MSYS2",
                "commandline": "C:/msys64/msys2_shell.cmd -defterm -here -no-start -msys",
                "startingDirectory": "C:/msys64/home/%USERNAME%",
                "icon": "C:/msys64/msys2.ico",
                "fontFace": "Lucida Console",
                "fontSize": 9
            }

参考

付费、免费以及开源工单系统比较

比较了网易七鱼,创逸云客服,udesk,单小二,腾讯云智服,售后宝,以及国内开源产品。

收费软件大多是集成在客服、CRM中,存在接口不足、界面太重、价格过高的问题。开源项目都基本是没法用。而国外的对微信,钉钉支付不好。

目前看来售后宝比较符合需求。API调用10万次1000元。

file

nginx 非www跳www,www跳非www,http跳https

非www跳www

if ($host ~ ^(?!www\.)(?<domain>.+)$) {
    return  301 $scheme://www.$domain$request_uri;
}

www to non-www

if ($host ~ ^www\.(?<domain>.+)$) {
    return  301 $scheme://$domain$request_uri;
}

其他域名跳统一域名

if ($host != "example.com") {
    return  301 $scheme://example.com$request_uri;
}

http跳https

if ($scheme != "https") {
       return 301 https://$host$request_uri;
   } # managed by Certbot

参考

letsencrypt https证书增加OCSP Stapling解决iOS公众号H5首次打开慢问题

原因

最近收到反馈网站公众号H5打卡慢,发现都是iOS用户,最后搜了以下发现可能因为letsencrypt证书域名被污染,导致到国外验证证书慢,解决办法是开启OCSP Stapling本地服务器缓存。

nginx 日志可以看到

ocsp.int-x3.letsencrypt.org could not be resolved (110: Operation timed out)

检查证书是否已开启OCSP Stapling

openssl s_client -connect c4ys.com:443 -servername c4ys.com -status -tlsextdebug < /dev/null 2>&1 | grep "OCSP"

(nginx重启后需要运行两次,第二次才有结果)

如果结果是下面这样,说明 OCSP Stapling 已开启:

OCSP response:
OCSP Response Data:
    OCSP Response Status: successful (0x0)
    Response Type: Basic OCSP Response

而这样显然是未开启:

OCSP response: no response sent

开启ssl_stapling的两个条件

根据 nginx ssl_stapling 官方文档只需要两个条件即可:

  • 指定了resolver
  • 如果ssl_certificate没有包含中间商证书,则需要将中间证书包含在ssl_trusted_certificate中

letsencrypt certbot的ssl_certificate使用的是fullchain.pem,带了中间证书,所以只需要指定resolver即可。生成ssl_trusted_certificate和ssl_stapling_file的步骤不是必须的。

ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=60s ipv6=off;
resolver_timeout 5s;

查看当前域名的证书链

查看站点根证书,0,站点证书;1,中间证书,2,根证书

openssl s_client -connect c4ys.com:443 -servername c4ys.com -showcerts < /dev/null 2>&1

depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
verify return:1
depth=0 CN = c4ys.com
verify return:1

下载根证书

letsencrypt 的证书链介绍和下载

其他证书下载

cd /etc/letsencrypt/live/c4ys.com/
wget https://letsencrypt.org/certs/trustid-x3-root.pem.txt
mv trustid-x3-root.pem.txt trustid-x3-root.pem

验证证书

openssl x509 -in cert.pem -noout -subject
openssl x509 -in chain.pem -noout -subject
openssl x509 -in trustid-x3-root.pem -noout -subject

生成ssl_trusted_certificate

cat cert.pem chain.pem  trustid-x3-root.pem > ca_bundled.pem

查看证书ocsp地址

查看证书签署,来自ocsp.int-x3.letsencrypt.org

openssl x509 -in cert.pem -noout -ocsp_uri

验证ocsp获取

openssl ocsp -no_nonce -text \
-issuer chain.pem \
-cert cert.pem \
-CAfile ca_bundled.pem \
-VAfile ca_bundled.pem \
-url http://ocsp.int-x3.letsencrypt.org/ \
-header "HOST" "ocsp.int-x3.letsencrypt.org"

发现超时,修改/etc/resolv.conf,服务器dns

nameserver 8.8.8.8

然后出现

Response verify OK
cert.pem: good

开启ssl_stapling

ssl_trusted_certificate /etc/letsencrypt/live/c4ys.com/ca_bundled.pem;

开启后可以通过前面的方法验证,第二次才有效

服务器缓存OSCP staplingresp(可选)

服务器可以将OSCP resp缓存起来,避免走国外下载

使用ssl_stapling_responder(方式一,推荐)

由于ssl_stapling_file需要手动更新,比较麻烦,所以通过http代理获取。
参考:https://jhuo.ca/post/ocsp-stapling-letsencrypt/

开启ssl_stapling_file(方式二,推荐)

ssl_stapling_file可以将oscp缓存起来,避免服务器下载

下载并保存 oscp resp

openssl ocsp -no_nonce -text \
-issuer chain.pem \
-cert cert.pem \
-CAfile ca_bundled.pem \
-VAfile ca_bundled.pem \
-url http://ocsp.int-x3.letsencrypt.org/ \
-header "HOST" "ocsp.int-x3.letsencrypt.org" \
-respout ocsp.resp

nginx启用ssl_stapling_file

ssl_stapling_file /etc/letsencrypt/live/c4ys.com/ocsp.resp;

自动更新ssl_stapling_file

oscp有效时间通常只有7天,所以需要使用脚本自动更新缓存,参考:https://quchao.com/entry/how-to-configure-ocsp-stapling-on-nginx-for-the-certificates-issued-by-lets-encrypt/

参考

族谱的数据设计

需求分析

  • 族谱有一个特点就是写入少,所以可以建立一个缓存表。
  • 维护关系尽量简单
  • 查询上下几代尽量快速,避免递归

数据库结构

people 表

id 
name 姓名

relation 表

id
family_id 族号 一个用户可能存在多个族谱中,比如外嫁后进入其他族谱
people_id 用户编号
level 代系
relate_people_id 关联人,
type 关系:如丈夫,妻子,儿子,孙子,情人
order 第几个孩子,第几任妻子

索引

alter table relation create index family_level(family_id,level);

查询(高性能将上下三代查出来)

select * from relation where family_id=3 and level between current_level-3,current_level+3;

分析

这两个表记录基本不用改(除非录错了),任何时候都是增加记录即可,所以维护也非常简单。

界面展示上,查询出上下几代,然后名字作为主要展示标签,关系用连线展示,关系和人是多对多,完美解决关系混乱的问题。

level 代表是族谱里面的第几代。

如果发现了新的祖先,然么当然自己代数要加一。

比如李渊原来 level 是 1 代,然后认了老子做祖宗,那么他就不 1 代了,老子是 1 代。

族谱草图

file

参考