Cocoa

Rust Learning from Zero (23) —— The OwO software distribution system!

Although I've written a SSL management and distribution system, rcert, but the here immediately goes another problem: I still need to manually deploy the rcert, which is kind of frustrating. Or I can write some shell scripts to make this process automatically. Let's solve this (possibly) once and for all.

I built a handy (perhaps also buggy) software distribution system this time. This main purpose is of course to ease out the deployment process. And I'd like to call it OwO, because this emoji looks so nice and cool. Moreover, it should be able to deploy itself once I have the initial instance ran.

Basically, it will serve these pages and API endpoints below (let's take owo.ryza.moe as its domain)

URLCategoryAuthNotes
Homehttps://owo.ryza.moe/WebpageNo
Admin https://owo.ryza.moe/adminWebpageYesadmin is customisable
Sign Inhttps://owo.ryza.moe/signinWebpage APINo
Sign Outhttps://owo.ryza.moe/signoutWebpage APINo
Compile-time Static Fileshttps://owo.ryza.moe/static/{filename}Web ResourcesYesThese files are compiled into the final binary
Feature Imagehttps://owo.ryza.moe/feature_img/{img}Web ResourcesNoFeature Image for Specific Project
Install Scripthttps://owo.ryza.moe/{name}/install.shWeb ResourcesNoInstall Script for Specific Project
Project Resourceshttps://owo.ryza.moe/{name}/resources/{resource_name}Web ResourcesNoResources for Specific Project
Update Project Infohttps://owo.ryza.moe/update-dist-infoAPI EndpointYesPost
Upload Project Resourcehttps://owo.ryza.moe/upload-dist-resourceAPI EndpointYesPost, one file per request
Get Raw Install Scripthttps://owo.ryza.moe/raw-scriptAPI EndpointYesGet
Remove Project for Versionhttps://owo.ryza.moe/remove-distAPI EndpointYesPost
Remove Project Resourcehttps://owo.ryza.moe/remove-dist-resourceAPI EndpointYesPost

Once I had decided these rules, the next question was which http server crate should I use. I considered hyper, but let's try something else this time. Thus OwO uses actix_web as its http server framework.

Apparently, OwO will output dynamic webpages, so it needs an HTML template engine. After some googling, I chose ructe as the template engine to render dynamic webpages for OwO.

And here is the result of 3 days' coding!

You can visit the live instance of my OwO at https://owo.ryza.moe. And the code goes here: https://magic.ryza.moe/ryza/owo

Rust Learning from Zero (22) —— SSL certificates management and distribution with Rust

Screenshot of rcert

Last night, I was planning to do some web development, and when I created my new VPS, I just felt like it was quite a tedious process either manually copying-pasting SSL certs around or deploying CertBot to allocate new ones for me. My life would be easier if there is some sort of SSL certificates management and distribution system.

Although I didn't really search these keywords on Google, I can promise that they definitely exist on the web. Nevertheless, I want to write one myself, because it has been such a long period since last time I wrote something in Rust.

Continue reading Rust Learning from Zero (22) —— SSL certificates management and distribution with Rust

Isekai

After three and a half months work, I finally resigned so that I can have some break. Reviewing this period, I found it boring and plain for the most of the time. Although occasionally eating outside or having a voice call online with friends, I spent the rest of my time alone, wondering if this is how life would be in the following 10 or 20 years, or would it last to the final end?

One of my friend on Facebook recommended a comedy anime, KonoSuba (この素晴らしい世界に祝福を!), to me. And it indeed is an amazing comedy. But meanwhile, I somehow felt more depressed.

The main character, Satou Kazuma, was a neet and otaku, dead less than 80 seconds in the anime, thus he entered a different world (isekai, 異世界) beginning his adventure journey mainly with other 3 girls. They became really good friends and Kazuma fell in love with Megumin afterwards.

There are also some other anime featuring afterworlds as its story's background, such as Angel Beats and Zombie Land Saga. And I think the main characters in these stories share something in common: they didn't have a happy nor even normal life when they were alive, or encountered unexpected accidents and had some pities when they passed away. But the most attractive thing for me is that, they have a better life with great friends in isekai. They can hangout with friends and meet up each other on a daily basis, in contrast with the highly likely lonely life in my next many years.

So in my perspective, it can't be more wonderful if such isekai exists. Yet knowing that they are all fiction worlds makes me feel depressed in someway. And in reality, if one passes away, then they physically no longer exists. Even if there is something like reincarnation, one cannot possibly remember anything from their former life. (What about cyborg? That can be an entirely different topic though. I once wrote some of my thought about it. I, self, mind, immortality and death)

Don't let numbers make one numb to others feelings

Today is my first time going home from work after 9 PM in this company, but that's not important. What I want to talk about and matters is that, one of my colleague seems to be emotionally hurt by another colleague from our quants depts.

People in quants depts usually deal with data, lots of data. And of course, most, if not all, are numbers. However, if one work with numbers for a really long time, it can magically make people numb to others feelings.

In this morning, I heard that a colleague from quants depts (will use Q for shorthand) talked with our ops (will use O for short). There seemed to be a log analyser should be changed by O to meet the standard in Q's depts. But the task contains some specific terms in quants, and O cannot be sure about the meaning for some fields with these quant terms. Then Q said something really harsh to O, "I feel it's very difficult to have you understood", "Why don't you ask me for explanation earlier?!", "It almost makes me feel angry to talk with you!".

Well, I don't really think that Q was trying to communicate with others at that time. Intentionally or not, Q seemed to be numb with others feelings. Though O wasn't starting any argument with Q, O became depressed a day long. Moreover, during the weekly meeting in this afternoon, O looked his own phone for a few seconds, and the big boss asked him to stop looking at the phone with a little bit anger.

Yes, the second one is really a small case. But it is the last straw that breaks the camel's back. After the weekly meeting, our leader also found that O was in depress and wanted to have a talk with him. It not to my surprise that O refused the talk and said to the leader, "If you or boss is unhappy with my work, you or he can just fire me, that OK. It's late and I don't want to talk anything now. I just want to go home, otherwise I'll miss the last subway."

It may sound childish, but IMHO, it's better than numb / indifference in some way.

As a matter of fact, I'm thinking about to learn some quant skills recently. But I don't want to be numb or indifference to others. Are numbers making one numb? Or themselves? Perhaps both, perhaps we are just making excuse so that numbers are the ones to be blamed instead of ourselves.

Rust Learning from Zero (21) —— All I need is a dlsym | Exploit macOS application with Rust

It has been a long time since my last reverse engineering on macOS, and that was about Netease Cloud Music. 

But I always write that in Objective-C, perhaps I should try something different, let's say, Rust.

  1. Compile a .dylib that macOS recognises
  2. Build a Constructor Function that Invokes on dylib Loading
  3. All I need is a dlsym
    1. Find the Symbol You Want
    2. Casting to Function Pointer
  4. Compile and Hook

1. Compile a .dylib that macOS recognises

The first step is to tell cargo that what we need is a library

cargo new --lib exploit

And cargo will create these files for us.

exploit
├── Cargo.toml
└── src
    └── lib.rs

However, if we compile this project, the output library has a suffix .rlib. which suggests that this is a Rust library. Yet we need a dylib that macOS recognises.

Therefore the hint for producing a .dylib library should be added in Cargo.toml, which is shown below.

[lib]
crate-type = ["dylib"]

This tells cargo out crate type is a dylib, which satisfies the format requirements of macOS dynamic library.

Continue reading Rust Learning from Zero (21) —— All I need is a dlsym | Exploit macOS application with Rust

最近

離上次寫點東西已經過了一個月有餘,這一個月裡也算是發生了蠻多事情吧

見到了一直以來想見的朵朵和范范~

自己也暫時可以說是在這邊落腳了,一個人找了地方租房子住下了。但一個人住的確是挺寂寞的,沒有人可以說話,自己對很多事情也提不起來興趣⋯

感覺好像世界上就只剩下自己一個人了,唯一可以跟其他人交流的渠道就只剩網絡⋯⋯雖然說是有網絡可以交流,但是實際上並沒有人來找這邊聊天就是了。週六外面在下雨,於是在住的地方待了一整天,也是呆了一整天。

今天週日,出門去逛逛好了,順便買些需要的東西回來。大概需要一個檯燈吧,房間裡自帶的燈還是有點暗的感覺,也許是自己習慣在較高亮度的環境了?總而言之先出門好了w

買了一些會用到的東西,燈還是被我咕咕咕了,要不直接在網上買、快遞過來好了。一回來就已經下午 5 點半了,明天又是週一了呢,又要開始 5 天的上班了><

在 CentOS 7 中编译安装 Aria2

以前自己折腾的时候主要是 Ubuntu / Debian,自己有记录一份 Ubuntu / Debian 下 Aria2 的编译安装流程~不过 CentOS 的话,因为是 RedHat 系,所以有蛮多不一样的地方,于是就一边摸索一边记录下来了~

那么第一步就是安装各种依赖了,当然还有 autotools 和 libtool 也是需要的/

sudo yum install expat-devel libssh2-devel libxml2-devel \
     c-ares-devel zlib-devel gnutls-devel nettle-devel \
     gmp-devel libsqlite3x-devel automake autoconf \
     gettext-devel libtool

第二步则是安装 GCC 8.0 了喵~因为 Aria2 需要 C++14 的编译支持,而 CentOS 默认的似乎是 GCC 4.9.0 的样子

sudo yum install centos-release-scl
sudo yum install devtoolset-8-gcc devtoolset-8-gcc-c++

安装好之后,就可以先切换到 GCC 8.0 的环境下来操作了/

sudo scl enable devtoolset-8 -- zsh

第三步就很简单了,git clone 下来 Aria2 的 repo,然后正常编译安装就好~

git clone --depth=1 https://github.com/aria2/aria2.git cd aria2 autoreconf -i && ./configure --enable-libaria2 && \
     make -j`nproc` && sudo make install

下面就来到了第四步~这里假设希望的 Aria2 的下载目录和 session 目录都是 /mnt/vdb/aria2~先创建名为 aria2 的用户和 group,然后创建好对应的下载目录和 session 文件,并且将下载目录和 session 文件的所属用户和所属组都设置为 aria2,同时设置 aria2 用户和组对该下载目录可读可写。

Continue reading 在 CentOS 7 中编译安装 Aria2

WebP Server in Rust

Generate WebP images for JPG / PNG files on-the-fly with Rust! webp_server_rs

Speaking of switching to WebP image, at the first glance, I just did it in a very naive approach.

Then @Nova wrote a Node.JS server that can serve JPG/PNGs as WebP format on-the-fly. You can find that at n0vad3v/webp_server.

A few days ago, @Nova and @Benny rewrite the WebP Server in Golang, webp-sh/webp_server_go

And that looks really promising, the size of the webp server, according to its description, had greatly reduced from 43 MB to 15 MB, and it is a single binary instead of webp_server with node_modules.

I cloned that project and added a tiny feature. However, I just found that although it is absolutely easy to implement the tiny feature, there is a potential design issue with the `fasthttp` module. In order to get everything work, it took me about 4 hours to debug on it.

Finally, it turned out to be a pointer of an internal variable (ctx.Request.uri, or so) was directly returned from ctx.Path(), and if users invoke ctx.SendFile(filepath), the ctx.Request.uri will be set to filepath, which will also propagate to all variables that hold the shared value of ctx.Path(). You may visit my previous blog post for details.

Well, in aforementioned blog post, I said that it would be better if it was written in Rust. Now, let's make it come true and push the WebP server even further.

There are some comparisons among n0vad3v/webp_server, webp-sh/webp_server_go and webp_server_rs.

As for size,

  • webp_server(nodejs) with node_modules takes 43 MB
  • webp-server(go) has reduced to 15 MB, and it's single binary
  • webp-server(Rust) pushes that even further, only 3.6 MB on macOS and 6.4 MB on Linux

In terms of convenience, you can just download the binary file and run if you choose either webp-server(go) or webp-server(Rust). However, webp_server(nodejs) requires pm2 to run.

Performance, to be honest, I haven't got time to run some benchmarks on them. But IMHO it (webp-server(Rust)) should be as fast as golang version.

记 Golang 下遇到的一回「毫无由头」的内存更改

前两天看到 @Nova Kwok@BennyThink 做了一个 WebP Server,于是 clone 下来玩了一下,发现貌似没有做“原始图像更新后,重新生成相应的 WebP 图像”的功能。好的,这个说起来简单,做起来也很简单,就是 os.Stat 一下,然后取到图像最后修改时间的 UNIX timstamp,STAT.ModTime().Unix(),最后再跟先前生成好的 WebP 文件名比较一下就好(timestamp 会放在生成的 WebP 文件名里)。

上面为止真的都很简单,在 macOS 上测试了一下,看起来没问题~于是就提交 Pull Request

然而 Nova 告诉我说,

Nice PR, but there seems a little problem that the older converted images are not deleted after the change of the original image, this might cause a possible leakage of the original one's content.

显然我是一头雾水,一开始还以为自己提交 PR 的时候是不是手滑删掉了几行,检查了一下之后发现并没有!然后姑且先把 macOS 上测试的截图 comment 在了 PR 下面。

接着我估计 Nova 应该是在 Linux 下跑的测试,于是就在一台新的 VPS 上安装了 go,把我 fork 且修改过的那份代码 clone 在 VPS 里测试。本来我预估的时候要么是我搞错了文件,要么也许是 Nova 不小心用了以前编译好的文件。然后一测试我就惊了,居然真的没有删除以前生成的 WebP 图像 Σ(・□・;)?!

由于没有 Linux 机器,也懒得安装虚拟机了,只能一头雾水的在 VPS 用 fmt.Println 输出来简易 debug 了。根据 fmt.Println 的输出,发现 ImgName 不知道为什么就突然之间被改了!

[1]ImgName: webp_server.png
[2]ImgName: webp_server.png
[3]ImgName: webp_server.png
[4]ImgName: webp_server.png
[5]ImgName: root/webp_serve

上面是在 5 处不同的地方 fmt.Println("ImgName", ImgName) 的输出,虽然我放了这么多,但是实际上在代码里 ImgName 在其作用域内只有过一次赋值,

ImgPath := c.Path()
// ... 略去 10 行左右判断文件扩展名的代码
ImgName := path.Base(ImgPath)

然后就没写过了,仅有读的操作,没有任何赋值,中间只有一次被用来当作 Sprintf 的一个参数

WebpImgPath := fmt.Sprintf("%s/%s.%d.webp", DirPath, ImgName, ModifiedTime)

但显然这个也不会更改 ImgName 的内存嘛。“这不科学!” 虽然想这么叫出来,但是想想这个肯定还是有原因的!

Continue reading 记 Golang 下遇到的一回「毫无由头」的内存更改

「不可愛」清單

昨天和今天看到推特上有在玩把人加入到「可愛」清單的遊戲,我自己的話,既沒有被任何人加到這樣的清單裡,也並不在意這些的說,但是剛有看到 @FiveYellowMicepost 說 ——

于是黄鼠有想做类似的事情,可是在考虑了一下之后,觉得还是放弃会比较好了。

因为有着被加入清单的人,就意味有没有被加入清单的人。被加入的人会很开心,可是对于没有加入的人而言,这样就是明显的排除和拒绝了。不在意黄鼠的人当然不会去在意自己有没有被加入,可是如果是在意黄鼠的人,没有被加入清单一定会是一个打击吧。也许这个打击不会很大,因为黄鼠大概也不会有那么重要,也许会很在意黄鼠的看法的人根本不存在。但是那是黄鼠没有获知的事情,万一在意黄鼠的看法的人是存在的,或者在未来的某一天出现了,那样的话,黄鼠不想要让他们觉得自己被排除和拒绝了呢。

那麼既然建立類似於「白名單」的可能會對在意自己的看法的人造成傷害的話,不如建立一個「黑名單」好啦!

於是咕嚕咕嚕地跑去創建了一個空白的「不可愛」清單,然後裡面一個人都沒有~!

不知道為什麼,突然間就想到了內田彩的「Merry Go」裡的一段歌詞

何だって 裏表だね
為什麼會有表裡存在
裏だって 表なら
如果說裡是表
表だったさ 裏なんです!
那表也是裡了呀(・8・)
幸せの反対も
就算在幸福的背面
回せば幸せに姿を変える
只要轉身就能遇見幸福
悲しみの背中には
悲傷的背後
喜びの翼が生えてるの
也有喜悅的翅膀在生長

いまが最高!