duangsues.is_a? SaltedFish
60 subscribers
609 photos
6 videos
91 files
562 links
🌶🐔🐟 duangsuse 的日常
尤其喜欢发些奇奇怪怪的东西
和转载别人的东西
Download Telegram
Forwarded from dnaugsuz
这也是我一直以来对技术交流的态度,我和对方都是爱好者而已
Forwarded from dnaugsuz
作为爱好者来看待

难道 Kotlin/Common 的程序员不是 JVM 程序员?

难道 String 不是 CharSequence?
Forwarded from dnaugsuz
可是这也正是我曾经对他说的话,我个人并没有什么特别的在提高自己的地位...

我只是一直在尝试学习...
Forwarded from dnaugsuz
学习是没有错的... 可能大家学的方向是有点不一样而已,但我真的是作为一个交际人,我相信我绝对不是自傲的
Forwarded from dnaugsuz
比如说,我可能倾向学杂七杂八的东西,别人专门写应用,

drakeet 开始是写应用,可后来他表示『他的逆向工程技能很不错』(这话是他说的)

然后我不服才『自大』的,我说的也只是(客观评价了一下逆向工程方面 drakeet 真实能力)
这不能说是我默认是自恃技术怎么样

我没有在他面前说我逆向工程比他强,但我的确是至少在这方面努力比他多,你们也看到了,至少我逆向分析了纯纯写作和 CoolApk 的 liba.so

liba.so 是机器代码写的,就是这样我也能还原其逻辑,而当时 drakeet 眼里就是:如果我用 NDK 集成写校验逻辑,我就会什么都做不了(黑盒)
Forwarded from dnaugsuz
也是,毕竟我不应该不看人家的性格...
Forwarded from dnaugsuz
我以为大家都是爱好者,可他觉得我是爱好者,他是工程师...
Forwarded from dnaugsuz
所以为人还是多学习少撕逼
以后遇到这种人,就只说好的,绝口不提任何负面的评价
Forwarded from dnaugsuz
你说上面的,其实我自己大概也注意到了(因为我自我感觉,如果这些信息不准确,我可能会被喷,如果我把自己的姿态降到不能再低,显然信息准确性怎么样都好)

我说的比较随性,这也是因为平时在 @dsuse 里 CS 广播发多了的原因导致我总是这样不带感情的提这些东西...

希望你没有感觉自己被冒犯到就好 🐱

下面的

但是年轻人 🐸
就是出来体验生活的,为什么不多尝试一点(

我可没有说我是长者呦,这里有一个地方误会了,因为我多加了个折行,其实我的意思是:

但是年轻人就是出来体验生活的,为什么不多尝试一点(

我没有以『年轻人』称呼你(虽然似乎我高二比你大一点)
而是说所有『年轻人』都最好出来体验生活,多尝试一点...
Forwarded from AlPlank (Al Pt)
为了防止撞库攻击,很多人都建议任何密码相同(或相关)的用户修改自己的密码。

~想法~
所以,改成什么?
1.自己要能记忆
2.不同网站/程序不一样
3.不同密码之间无关连

思考了一下
希望:“即使断网也能查看密码”
所以要在本地完成计算。
同时“希望能在任何平台算出密码”
所以不想使用密码管理器。


~实施~
于是决定:
1.想好一个"盐"(可以有任何字符,长度也可以很大),记下来。
2.将其和要设置的网站的域名拼接
3.计算sha256
4.取最后几位作为该网站密码,位数建议多点(8-12)。


~问题~
优点?
即使有人脱了数据库,拿到了你的密码,也无法登录;
不需要密码管理软件,防止被密码管理软件坑到(也不需要钱钱购买);

缺点?
上一条中,如果针对你个人进行攻击,根据你的社会信息猜测盐值,或暴力猜测"盐"值(猜盐-计算sha256-比较脱库获得的网站密码)
需要手工记下sha256的最后几位,可能对记忆力不好的用户是个挑战。

可能的因为操作不当的漏洞?
在shell执行时,history里会留下记录;
如果偷懒复制粘贴,可能会被有剪贴板访问权限的程序偷了密码。

为什么sha256而不是md5?
因为其计算起来比md5慢,这样可以略微增加暴力破解者的计算成本,而对于用户,也不会感知缓慢。

copyright @AlPlank 1989-8103

#public
Forwarded from dnaugsuz
NLP 我不会,但是解析器理论我会一些,你想请教什么?我正准备写我的第一个 Java 解析组合子框架
Forwarded from dnaugsuz
NLP 部分和我们编译原理的解析器理论是相通的,但首先

+ 我只会写比较好看的递归下降法解析器
+ 实际上在 Parser Compiler (Compiler Compiler, 比如 re2c, yacc, bison) 和 Scanner generator 领域(对应 Lex-Yacc Style Parsers)

他们基本都用 NFA, DFA 这种自动机(上面的 NFA, DFA 都只是根据下一个状态属性命名的自动状态机的类型)
实际上,函数式编程向的人们基本都会直接用一段程序的状态替代这种(到状态机匹配指令和状态表的)编译器 + 状态机
而且递归下降法也很快,基于递归下降和 LR 的解析组合子也能解析很多很复杂的文法,基于组合子自动机的也可以自动做诸如左递归消除的解析器优化

+ 不过,这是说编译原理里的解析器理论,和自然语言处理里的还是蛮不一样的

比如说,我们的语法可能是固定的

program = many (_ statement _)
statement
= define | calculate
where
define = string "define" _ identifier _ char '=' _ value
calculate = string "calculate" _ expr

identifier = [a-zA-Z_] [a-zA-Z0-9_]*
value
= litInt | litString | litBoolean
where
litInt = [0-9]+
litString = char '"' char* char '"'
litBoolean = string "true" | string "false"

expr
= intAdd | stringConcat | booleanAnd
where
intAdd = expr '+' expr
stringConcat = expr '..' expr
booleanAnd = expr 'and' expr

_ = spaces

猜猜这能匹配什么(当然即使是“辣鸡”的编译原理向解析器也有运算符结合处理的问题,对于不懂递归的人来说这有点烧脑,是真的)

比如

define num = 1
define hundred = 100
define str = "Hello"
define yes = true define no = false (注意这里不需要换行,看上面的语法规则你就知道为什么)
当然如果 ';' 这个字符被视为空白也可以写成
define yes = true; define no = false

calculate "hello" .. " " .. "world"
calculate 1 + 1

二元表达式链看起来不是多么好办(但是可以左递归什么的,可以直接将优先级大的二元运算符比如 "*" "/" 表达式左右都结合优先级小的),不过自然语言处理要“处理”的问题可比这个简单的递归算法复杂得多

上面括号里的情况:

(=) 的前面是规则的名字;后面是规则的模式
one = "1"
(|) 组合一组可能的模式,实际上它的结果是这些模式中任何一种
booleanLiteral = "true" | "false"


Expr = BinAddSub

BinAddSub
= AtomExp ("+" | "-") AtomExp
| BinMulDiv

BinMulDiv
= AtomExp ("*" | "/") AtomExp
| AtomExp

这样实际上在解析规则的模式字面上定义了优先级,结合性问题估计也可以用类似手段去做

👆 比如说我们的语法可能是固定的

那 NLP 就不是这种情况喽,看 HanLP 它说它用了 Markov 链,这也是一种机器学习预测算法

看架构 NLP 的分词器显然要和解析器互相协作,依据两方的『猜测』决定最终的算法输出,这是我们编译原理里所没有的,何况它还支持监督学习自动识别单词和单词词性词类呢

不管怎么说建议你先学一下编译原理和简单的机器学习,比如 KNN、决策树、朴素贝叶丝分类器
以及语法,比如中文语法

自然语言处理虽然要做到极致的话,是不得不引入越来越多的分析和学习的,但是做事情也要看程度

LLVM Cookbook 的翻译者也是要学 NLP 的,不过他又半道学了一会编译原理,这是个不错的路径选择

你要学习的话,就赶快先试着自己写一个解释器看看,如果这样的能力都没有的话,自然语言处理是很难入门的,(新手村都出不了,跑)

而且最好先写点 NLP 的应用,比如说,主语推导?(将动词的隐式主语推导出来,显式输出出来)
GeekSpec 虽然非常不成熟(而且也没有技术支持...),但是它的确比 Swagger API Tools 的辣鸡 Schema-YAML 语法更优秀,它可以描述的东西是 OpenAPI 3.0 的一个子集

但是!它非常符合直觉,设想一下,如果你要在设计 API 的时候看着一大堆非常空阔的缩进行,你定义一个参数还得按一下缩进,看一个接口有几个参数还得慢慢数,而连自己在设计的接口叫啥名字都不能被很快地看到的话...

我都不敢想是什么样子,OpenAPI 由一群连编译原理和 DSL、面向语言编程都没见过的前端『全栈』工程师来设计... 难道就没有人发现写 OpenAPI 的时候很淡疼?即使是 YAML 换了 JSON 也一样?
(不如隔壁 cucumber.io 它还有门 DSL)

对 GeekSpec 来说就不存在这个问题,它的定义式更简洁富于可读性

它是诞生于这条 (https://t.iss.one/dsuse/9017)广播的,我大概花了三四天... 整整三四天啊

searchUser(type:String?{username,nickname,bio}, kw-path:String, sort:String?{created,followers}) -> array:GeekUser
= user/search/{kw}

想想这类接口,Swagger 又能把它写成几行呢?你写下面这种代码... 又要多花多长时间呢?
对于动辄几十个 HTTP API 接口大一点的应用,直接用 OpenAPI 解决 HTTP 接口定义真的大丈夫?

getAllUsers() -> array:string = /users
(当然这等价于)
GET@getAllUsers() -> array:string = /users

/users:
get:
summary: Returns a list of users.
description: Optional extended description in CommonMark or HTML.
responses:
"200": # status code
description: A JSON array of user names
content:
application/json:
schema:
type: array
items:
type: string


如果你会(用 JavaScript 或者 Ruby)写稍微麻烦一点的算法,就能简单地把 GeekSpec 语言的代码转化为 YAML 结构,就可以实现 GeekSpec 语言对 Swagger Tools 的兼容
(GeekSpec 是 Swagger YAML 的子类型、GeekSpec 实现了 Swagger OpenAPI Spec)

而且基于 GeekSpec 的定义上,还有 Spectrum 工具 (https://t.iss.one/dsuse/9120)(和信号处理无关)做辅助:

spectrum(0.6)> status
[+] Total 67 APIs, method count: GET: 37; POST: 8; PUT: 11; DELETE: 11
receiving ["String", "UserId", "Int", "CategoryId", "AppId", "CommentId", "UserSize", "TimelineSize", "NotificationSize", "AppSize", "CommentSize"]
and returning 67 types (["string", "GeekUser", "Category", "App", "AppUpdate", "Timeline", "Notification", "number", "Comment"])
[+] 55 path params, 3 body params

spectrum(0.9)> tree :args
...
POST /admin/makeUser
* username:String
PUT /admin/resetMetaHash/{uid}
* uid-path:UserId
* shash:String?

而且还支持作为测试客户端

spectrum(0.1)> listUser
[!] Arity mismatch: expected 3 (not optional 0), got 0
[*] NOTE: fill first optional argument to get started
listUser(sort:String?{created, followers}, sliceFrom:UserSize?, sliceTo:UserSize?) -> array:GeekUser
= GET user/all

spectrum(0.2)> listUser 'created'
=> {"timestamp"=>1549876643013,
"status"=>500,
"error"=>"Internal Server Error",
"message"=>"Optional int parameter 'sliceFrom' is present but cannot be translated into a null value due to being declared as a primitive type. Consider declaring it as object wrapper for the corresponding primitive type.",
"path"=>"/user/all"}
#Haha #life (2333 又翻冰封语录///
Forwarded from dnaugsuz
import Control.Applicative

data Move = U | D | L | R
deriving (Eq, Show, Read, Enum)

type Map = [[Bool]]
type Point = (Int, Int)

type Hitsory a = [a]
type TracedRoute = (History Move)

dfs :: Map -> Point -> History Point -> Maybe TracedRoute

dfs map target history step
| step == target = Just []
| step `outbounds` map = Nothing
| blocked or walked = Nothing
| otherwise
= firstJust (fmap try [Up, Down, Left, Right])
  where
(x, y) = step
blocked = not (map !! x !! y)
walked = step `elem` history
outbounds p m = let (px, py) = p
in px >= length m or py >= length m !! px

tryDfs m t s = dfs m t [] s


这是个;它递归搜索一个 boolean[][] 数组,返回从某一点到指定点的路径

否则可以选择向正上/下/左/右方尝试移动

据说某个学校(指 CDLFS,成都某外国语学校)初中的 OI 生都会做
#web #dev #Kotlin 插播一条消息
Forwarded from dnaugsuz
https://github.com/JetBrains/Exposed#sql-dsl-sample

好耶,比某些 Annotation based AOP 框架高到不知哪里去了

object Users : Table() {
// Column<out T>
val id = varchar("id", 10).primaryKey()
val name = varchar("name", length = 50)
val cityId = (integer("city_id") references Cities.id).nullable()
}

object Cities : Table() {
val id = integer("id").autoIncrement().primaryKey()
val name = varchar("name", 50)
}

...
Database.connect("jdbc:h2:mem:test", driver = "org.h2.Driver")

transaction {
SchemaUtils.create (Cities, Users)

val saintPetersburgId = Cities.insert { it[name] = "St. Petersburg" } get Cities.id
Users.insert { it[id] = "andrey"; it[name] = "Andrey"; it[cityId] = saintPetersburgId }
}

...

for (city in Cities.selectAll()) println("${city[Cities.id]}: ${city[Cities.name]}")


本来就应该使用这种风格的

然后还可以使用 DataAccessObjects 的风格

object Users : IntIdTable() {
val name = varchar("name", 50).index()
val city = reference("city", Cities)
val age = integer("age")
}

class User(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<User>(Users)

var name by Users.name
var city by (City referencedOn Users.city).nullable()
var age by Users.age
}

...
User.new {
name = "duangsuse"
age = 17
}
内存区域限制技能 get
Forwarded from dnaugsuz
关键是这个判断

if (retv && inlen >= value_len + 1)
  // strncpy (retv, value, strlen(value) +1);

原来可能就没有,所以有时候 strncpy (它的意思是从 src 复制 n 个 char 到 dst,这里 C 的『字符串长度』因为字符串是 NUL 结尾的,得加上 NUL 字符的长度 1,可惜作者弄错了或者说故意弄的,原因在后面)

The strcpy() function copies the string pointed to by src, including the terminating null byte ('\0')

strncpy
:
If there is no null byte among the first n bytes of src, the string placed in dest will not be null-terminated.

但是 strlen 不包含 NUL byte '\0' 长度, 所以作者 strncpy 时加上是正确的

但这样
(调用 strncpy, 写到指针, 但是指针是不定长无限制的)实际上就可能 overflow 了 retv: 本来它可能(是在其他函数里)分配了未知长度的内存,可是我们居然可以随便按照 value 字符串的长度复制
这是不安全的操作,所以 CC 阻止了编译,但它是没有问题的

找不到 inlen 的话就定义栈帧 auto 变量

size_t inlen = strlen(retv);
size_t value_len = strlen(value);

它可以 suppress
看起来就算是没有刻意用 GoF 的 OOP 设计模式,你也是会正常的 OO 吗,难道 FlarumSDK 的

public class FlarumException extends Exception
int status, code; List<Error> allErrors;

public class Result<T>
int id;
okhttp3.Response rawResponse;
JSONAPIObject object;
T mainAttr;

public class RequestBuilder<T>
final Flarum flarum;
final ObjectParser.JsonObjectConverter<TYPE> converter;
final String method, urlEndpoint;
final RequestBody body;

public static class RequestBuilder$BaseRequest<TYPE>

private okhttp3.Request.Builder baseBuilder ()
这一类虽然算法比较简单(几个顺序分支;和 Kotlin 里 thread 辅助函数的差不多,按需设置对象)但是没有一点意识也是写不出来的啦

public interface Callback<T> 这个看起来像是复制的(

可是怎么看都用了正常的面向对象编程啊;media type & converter、token getter、tasks & executor

还有 JSON response parser, Json Object converter...

这类代码都不能算是了解面向对象编程了吗,看起来菜鸡是不可能哪怕是不包括型变的泛型和 converter 这种东西...(虽然 converter 好像懂泛型能抽提就可以了)
要是真正的菜鸡大概是这些都不可能会的