Browsed by
分类:Web Develop

Web开发

[看着不爽] NEUCrack 替代掌上东大的网页端查询工具

[看着不爽] NEUCrack 替代掌上东大的网页端查询工具

不得不吐槽一下, 学生竟然需要为了查询寝室班级信息而去下载一个只会用一次, 没错只会用一次, 的软件, 叫掌上东大

因而本着造福大家+宣传我网络部+自己闲着没事玩玩这三个原则, 将掌上东大给实现为了一个网站

 

传送门

16级的目前还不能查询到自己的信息, 无论是用我这个web还是用app都不行, 目前登陆的时候,你们会看到这样的提示

Screenshot from 2016-08-15 13-49-39

而当大家信息可以查询的时候, 就会变成这个样子

Screenshot from 2016-08-15 13-50-51

 

可以查询掌上东大能查到的各种信息, 主要是给新生使用的 因为这些信息对于13 14 15级的没有什么用= =

 

下面上几张使用截图

3f1e5d92446e2b21 -7b7bea5bfaacb908 -6d9f9f2ceca30ab4

 

 

 

voidisprogramer.com 全站启用HTTPS啦~

voidisprogramer.com 全站启用HTTPS啦~

域名备案总算OK了(生无可恋的眼神) 那么下一件事肯定是给我的WOWO启用HTTPS啦~

首先申请了一个免费证书 大家搜索WoSign 免费证书 , 就可以找到能用两年的免费SHA256加密的合法证书哦

然后给我的httpd开启https服务

因为之前没有安装mod_ssl,先安装好, 然后 在/etc/httpd.conf/下就有一个默认生成好的配置文件 ssl.conf我们打开, 修改相应的SSL证书路径, 设置为我们从上面获取到的证书的路径,然后 重启Apache, 通过https 访问https://voidisprogramer.com 发现OK~….. 不过 同时也发现了, 竟然 全站CSS还有JS图片都没法加载出来QAQ, Chrome F12看一下, 发现这些资源还都是用https://120.27.97.96这个路径去加载的,难怪加载不出来= =(证书只绑定了https://voidisprogramer.com 和 https://www.voidisprogramer.com两个域名 因而= =IP直接访问肯定不行啦)  这个问题倒不难解决, 去Wordpress后台, 的设置, 把WordpressURL, 和 站点URL都改成了 https://voidisprogramer.com即可~  [然后我发现就算改完首页banner图还有背景图的URL也没变,于是手动更新一下这两个图片的URL, 后来我发现如果把下面的步骤搞完这个根本不用管的说-0-]

恩~~ https域名访问看来没问题了~~ 那么 试试http可以访问么~ , 果然= =!http访问的话,不会定向到https下, 于是乎,下一个要解决的问题就是, 如何把http 还有 IP的直接访问,都定向到https去,这个使用了rewrite mod + NameVirtualHost的限制来实现. 首先, 我们在 /etc/httpd/conf.d/下面新建一个config文件”redirect-direct-ip-visit.conf” 然后 加入如下配置:

这里,我们将所有通过IP的访问, 把他们的DocumentRoot设置为了非wordpress站点所在的DocumentRoot,然后 在这个目录里新建一个 .htaccess对URL进行重写, 即可完成重定向, 重写的规则如下:

这几句 的意思一点点解释一下

首先开启了Rewrite功能,

然后 如果用户访问的时候,遇到找不到的文件(通过IP,还有http访问必然找不到, 因为在相应的DocumentRoot里只有.htaccess这一个文件,其他的任何请求都是找不到的, ) 这时候, 将请求的URL重定向为 https://voidisprogramer.com/下面的相应文件, 这里最后一句话 ,是因为 ,如果直接访问http://voidisprogramer.com那么, 不加最后一行的配置的话, 会导致重写规则定向到https://voidisprogramer.com/index.html, 这是一个不存在的路由, 因而, 将这个请求特殊处理一下, 如果定向到了index.html那么就直接定向到/

好了~~~ 到了这里, 访问 IP/XXX.html 还是 http:XXX/XXX.html都已经转到 https://XXX/XXX.html了 ~~ 看起来好像没什么问题了呢 QWQ, 不过 当我打开Chrome Console,发现竟然还有问题 = =!

QQQ

竟然是萌萌的夏娜酱的gif URL依旧是 Direct IP的QAQ!! 这个夏娜酱是通过一个插件 “伪春菜” 诞生的, 于是我去尝试修改伪春菜的后台Config,想着,给夏娜的URL换一个地址不就可以了么 然而- – 让我大吃一鲸的是!  竟然没有提供更换皮肤地址的选项!!!!

ChiJing

当然可以选择删掉这个伪春菜再建一个 = = 然而!! 我怎么可能做出那种丧尽天良的事情! 于是乎, 开始从数据库入手

打开wordpress的数据库,看看有没有weichuncai这个插件的相应数据表吧 ,然后我看到的是这样的:

= = 泥煤啊! weichuncai这个插件没有单独一个数据表啊擦! (通过这里来看貌似大部分插件都没有单独一个数据表) ,没办法 , 我不可能一个个表去查看, 而且,就算能查找, 该查哪个字段也是不知道的TAT,索性去看weichuncai的源码了

在wordpress目录下找到 wp-content/plugins/weichuncai 这就是这个插件的目录了 ~~ 其中的 sm-options.php,通过查看, 我们发现 ,用户自己定义的URL地址是通过一个叫做 $wcc[‘userdefccs’]这样一个变量保存的, 然后查看了一下, 这个变量是如何被获取到的 发现是通过49行

这里得到的, 然后去找get_option这个函数,发现不是weichuncai插件定义的函数, 于是 查找了一下Wordpress的开发者文档中, 找到了对应的说明 https://codex.wordpress.org/Function_Reference/get_option 根据Document所说,找到了wp-includes/option.php.  这个文件进行查看,  通过查看这个文件, 查看到了, get_options是通过查看数据库内的 $wpdb->options表 , 获取相应的options信息返回给用户,

这里出现了wpdb这个对象, 感觉这个对象应该是很重要的一个对象, 因而使用grep查找了这个对象在哪里定义的,  找到了 wp-db.php 这个文件, 打开发现是$wpdb整个类的定义,  然后, 又在options这个定义的附近发现了注释: “WordPress Options Table” , 这个应该就是$wpdb->options对应的表了~~ 也就是伪春菜的配置信息所在的表,  再查看一次数据库内的数据表发现 有一个表名为”wp_options” 于是选中这个表, 查询我们要的信息:

这里的option_name列是通过desc wp_options得到的表结构,进而得到列名, 然后, 查询的字段是通过, 上面伪春菜插件中的代码 get_options(‘sm-weichuncai’) 得到的, 查询后,果然得到了想要的结果~~

(太长了就不要在排版意细节了)

然后 只要更新option_value数据项~~ 我们就可以更换夏娜酱的URL啦~~~

然而= =!!! 遇到了一个大坑!!! 当使用下面的内容替换上面的option_value后

结果! 夏娜消失了!!

再去查看数据库,发现 刚刚的修改也失效了, 修改没有生效, 设置变成了最初安装时候的设置 = = 看来是因为设置不对,导致自动初始化设置了

经过多次查看原因发现, 在修改字符串的前面还有一个属性”s” 这个属性的值原来是字符串的长度, 在修改了URL之后,也要一起修改这个, 才可以 QAQ 于是 将更新的语句换成这个:

这次终于对了!!!!夏娜酱回来了 ~~ 之前的设置也都保留了, 撒花QAQ(到现在还没吃饭一直在搞这个这才叫真爱吧!!!

Gitlab DroneCI 配置记录

Gitlab DroneCI 配置记录

OJ的代码越来越多了, 功能也越来越多= = 也就导致bug越来越多, 测试的必要性就很高了, 因此我们需要用 CI平台鞋好的代码进行及时的测试, 因为OJ的代码是私有的,不能直接用DroneCI 或者是 TravisCI, 因而自己需要搭建一个DroneCI,具体操作如下, 根据DroneCI 官方文档说明  gitlab配置droneCI还有点麻烦, 之间也真遇到了几个坑= = 因此纪录一下过程

服务器端使用CentOS 首先安装docker, 并且 fetch DroneCI的镜像image到本地, 这就是一个基本的DroneCI环境了

根据DroneCI的说明 , 在  gitlab里首先创建一个application Oauth 接口,  配置为

Callback URL:即DroneCI所在的auth URL :http://202.118.31.226:3322/authorize这里为这个

然后会生成application id ****(A) 和 application secret *****(B)

将这两个写在 DroneCI Server的 /etc/drone/dronerc内 分别对应 A=> client_id B=> client_secret

注意REMOTE_DRIVER为 gitlab

REMOTE_CONFIG为 http://example.yourgitlab.com?client_id=A&client_secret=B

然后将 这个保存为脚本

然后运行脚本之后, DroneCI就搭建好了~ 点击登陆会跳转到相应的gitlab Oauth页面, 最开始因为没有弄清楚Oauth的关系, 把secret还有 CallbackURL全填写错了导致一直登陆失败QAQ

[NEUOJ日记] #1 Hello World

[NEUOJ日记] #1 Hello World

写在前面:

NEUOJ的开发即将满五个月, 算是我在大学阶段做的最大的一个项目了(因为搞ACM的缘故没有在大一大二做什么项目出来) 在开发过程中遇到了很多问题  & 学到了很多东西, 谨以此系列文章记录开发过程以及开发心得体会

文章的格式:

每一篇文章都会以: 一个主标题 开头, 然后 分为多个副标题, 每个副标题后面会跟一个解释下面要讲的内容的commit-id

Hello World

Why we start (No commit id)

两年半的ACM生涯结束了, 老师征求我们对于重写OJ的想法, 我们队伍的大家早就有自己写一个OJ的想法了, 作为挖坑小能手的我 ( Qrz ) 本来还有点因为自己的时间+个人原因不是很想搞(其实内心是非常想搞的) 被两个队友拉着就果断入坑了, 我们想写出一个能够给大家一个梯度训练, 界面友好, 测评多样化, 符合当今Web开发潮流的新的Online judge 系统, 于是我们队伍+ sjm + wyf就开始了对OJ的开发, 最初的分工是 我们队伍搞 Web 后端开发, sjm 搞前端开发, wyf + 我搞测评端研究

How we design (No commit id)

开发OJ对我来说最陌生的就是测评后端的开发, 不知道如何下手, 好在老师给我们提供了一个开源的测评系统 domjudge, domjudge的后端judgehost已经非常完善了, 支持多语言多环境多测试样例的安全测评, 于是我们初期就直接使用judgehost来做我们的测评后端, 然后前端我们使用的是Bootstrap框架, Web后端使用Laravel框架, 然后我们初步设计了一下表的结构, 参考了hustoj的数据表结构 & 我们自己的表结构,对表进行了设计, 最初的表有

 

(之后会在不同的阶段介绍表的具体结构  & 修改)

How we start(No commit id)

经过一周的讨论, 我们最后定下来了第一版的目标 先做出一个可以让用户提交代码(不管能不能测评)能看题的一个壳出来(虽然这个后来很快就实现了), 前端为 sjm 开始学习前端的知识(Bootstrap jQuery等等),后端为 accelercode队伍(即我们队) 我的另外两个队友都没有Web开发的经验, 因此给他们安排的任务是先学习PHP, 然后学Laravel, 在此同时我先开始熟悉laravel5(我之前用的是laravel4) 熟悉5之后, 开始建表, 建Model,建route, wyf 和 我的测评后端的任务是(刚开始没有让我搞测评后端, 我感觉搞OJ最有趣的地方就是测评后端了于是自己也主动去看了) 搭建domjudge, 并且研究judgehost的源码

Build the Domjudge(No commit id)

回去之后,我就开始了自己本地搭建domjudge的过程, 其中遇到了一些问题, 比如 archlinux下 jsoncpp头文件的名字和domjudge 的configure脚本里的名字不符,会导致就算安装了jsoncpp-devel还是找不到头文件, 这时候我在/usr/include/下面mkdir jsoncpp/json/ 然后把所有json/下的头文件拷贝到 jsoncpp/json/下 ,然后 再次configure就OK了 另外在下载源码之后没有configure文件, 需要先./bootstrap才行, 然而 bootstrap的时候会make 一次 latex的东西, 如果电脑里没有latex的东西, 你需要自己将 Makefile里关于latex的东西注释掉,也就是注释掉 make distclean下面的那一行,然后就可以了

Make the Plan for 1.0(931612-ffb28b)

这是我们的第一条commit, 在这个commit的时候, 我将大家拉入了我Bearychat的讨论组 NEUOJ-accelercode(private)

并且, 使用学校的gitlab 服务器 (219.216.96.46)对代码进行托管, 新建了 README.md 当时的计划如下:

 

然后为laravel工程建立了.gitignore, 并将laravel工程建好,配好了PHPStorm, laravel的环境, 配laravel的环境使用的是一键式傻瓜XAMPP, 我们的OJ开发正式开始 [Wed Nov 25 19:35:11 2015 +0800]

[NEUOJ] 测评后端分析 测评过程分析(judgedaemon.main.php)

[NEUOJ] 测评后端分析 测评过程分析(judgedaemon.main.php)

还没有整理, 先放生肉(Draft)

DOMJudge 测评后端API分析
====

### 调用流程简介:
1. domserver存储有所有数据信息,包括测评必须的信息
2. domserver提供一套RESTful API供judgedaemon客户端调用, judgedaemon可以有多个实例同时运行
3. judgedaemon运行之后, 每隔一定时间向domserver的api请求数据, 如果有数据的话, server会返回给judgedaemon一个json包,包含要运行的judge所需要的所有信息
4. judgedaemon将信息解析之后, 制作出相应的程序执行,和编译脚本 compile.sh , run.sh 之后执行(可以选择在CHROOT环境下执行, 暂时没有考虑)
5. 执行后的结果通过参数和返回值的形式返回给judgedaemon , 之后judgedaemon将测评结果数据提交给domserver, domserver随即更新数据库内的信息

### judgedaemon.main.php内函数分析

* dbconfig_get_rest
* fetch_executable
* judge
* read_credentials
* request
* rest_encode_file
* usage

#### dbconfig_get_rest
* arguments:
$name: 用于表示想要get的配置的名称

* description:
获取服务器的配置信息

* retval
服务器的相应的配置信息

#### fetch_executable
__核心函数,用于下载用户提交的代码,并且将代码编译, 生成运行测评的脚本run.sh 并且返回run.sh的绝对路径共后续调用使用__

* arguments:
$workdirpath: 测评路径
$execid: 需要fetch的执行脚本archive的id
$md5sum: zip的校验和
* description:
该函数根据提供的三个参数, 先检查是否本地已经存在运行本次测评需要的所有脚本(或者二进制文件), 如果不存在则从server 访问 REST/executable ,获取下来相应的execid对应的base64加密后的zip文件,解码,然后在本地的workdir/executable/$execid/下进行解压 ,并且根据不同语言写入不同的脚本内容
* retval:
返回值为相应的执行脚本(run.sh)所在的绝对路径

#### judge(主测评函数)
* arguments:
$row: 一个数组,里面含有测评所需要的所有信息, $row是在服务器端获得数据之后decode,然后存入的数据
* description:
该函数实现比较复杂, 将该函数的整个执行以流程的形式说明
1. 检查是否有创建文件等一系列的权限
2. 获取比赛队员提交的文件 需要访问RESTapi 的 submission_files ,id存在$row[‘submitid’]内
3. 获取编译该语言代码所需的 compile script ,调用fetch_executable, 取出所需的compile_script,并且返回一个绝对路径 $execrunpath
4. 运行LIBJUDGE_DIR下的compile.sh脚本, 对代码进行编译
5. 检查compile的成功与否, 成功则继续,否则退出,并将compile result返回给server
6. 如果有CHROOT的设置,则建立chroot环境
7. 循环获取每个testcase, 本地无testcase则去远端获取(input & output) ,将他们放在 $workdirpath/testcase/下
8. 获取hardtimelimit(运行时限), __**未解决**__为什么要用overshoot_time这个函数来求运行时限(line 612左右 定义在 lib/lib.misc.php下)
9. 执行testcase run脚本, 测评开始
10. 判断测评结果(返回值的含义)
11. 尝试从program.metadata中读取测评耗时(等信息)
12. 将测评结果返回给server RESTapi POST 请求 judging_runs 返回的数据如下:(数据的解释可能有偏差)


testcaseid: 测试数据id
runresult: 执行结果
runtime: 执行时间
judgehost: 测评的host名
output_run: 测评标准输出
output_error: 测评中的地方发
output_system: 测评信息
output_diff: 测评diff

13. 如果有chroot环境则destroy掉
14. 一次judge结束

* retval:NULL
#### read_credentials
* arguments: NULL
* description:
获取配置文件(ETCDIR/restapi.secret)中的认证信息并且添加到全局认证变量 $endpoints 中.配置文件中通过空白字符对每个信息域进行分割, 信息含有 认证记录的index(字符串), RESTAPI的入口地址 和访问RESTAPI需要的用户名和密码.
* retval
实际上是将全局变量 $endpoints的信息更新了, 不过没有返回值

#### request
* arguments:
$url:请求的restapi的路径
$verb: 请求方式(GET POST PUT…)
$data: 通过curl GET or POST时候附带给server的数据
$failonerror: 表示这个函数失败的时候是fail还是报警告
* description:
所有的curl请求通过这个函数进行, 这个函数就是封装好的curl请求函数, 当 $verb 参数为GET时, 表示通过GET请求数据, 即请求的是 restapi 中的 xxxx_GET的API 执行过程如下, 先通过curl_init 初始化curl进程, 然后经过setopt设置好各种参数, 然后通过curl_exec向服务器发出请求, 将服务器回传的信息通过$response变量存储起来,并且通过curl_getinfo得到服务器的响应代码,然后进行error handling(如果response为NULL说明函数执行失败)

* retval
返回值为从服务器获得的回传数据, json格式
返回数据样例:

[{"filename":"a.c","content":"LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICAgID4gRmlsZSBOYW1lOiAvdG1wL2EuYwogICAgPiBBdXRob3I6IFZPSURfMTMzCiAgICA+ICMjIyMjIyMjIyMjIyMjIyMjIyMgCiAgICA+IE1haWw6ICMjIyMjIyMjIyMjIyMjIyMjIyMgCiAgICA+IENyZWF0ZWQgVGltZTogVHVlIDAxIERlYyAyMDE1IDEyOjQ2OjM5IFBNIENTVAogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwojaW5jbHVkZTxzdGRpby5oPgoKaW50IG1haW4odm9pZCkKewogICAgcHJpbnRmKCJIZWxsbyB3b3JsZCFcbiIpOwogICAgcmV0dXJuIDA7Cn0K"}]

#### reset_encode_file
* arguments:
$file: 文件所在路径
$sizelimit: 是否限制文件的大小 (传递给 dj_get_file_contents)
* description:
将文件用base64和urlencode进行编码,并返回其值, 如果限定了$sizelimit = TRUE 的话, 文件会被限制在50000B
* retval:
返回文件encode之后的字符串

#### usage
* arguments: NULL
* description:
显示说明信息并退出
* retval: NULL

##JSON format


---- POST api/judgings ----
{
"submitid":24,
"cid":2,
"teamid":2,
"probid":4,
"langid":"cpp",
"rejudgingid":null,
"maxruntime":1,
"memlimit":524288,
"outputlimit":4096,
"run":"run",
"compare":"compare",
"compare_args":null,
"compile_script":"cpp",
"compare_md5sum":"71306aae6e243f8a030ab1bd7d6b354b",
"run_md5sum":"c2cb7864f2f7343d1ab5094b8fd40da4",
"compile_script_md5sum":"cf76014b4e27a6e25378055f53733a7a",
"judgingid":37
}
---- GET api/config ----
{
"clar_categories":{
"general":"General issue",
"tech":"Technical issue"
},
"script_timelimit":30,
"script_memory_limit":2097152,
"script_filesize_limit":65536,
"memory_limit":524288,
"output_limit":4096,
"process_limit":64,
"sourcesize_limit":256,
"sourcefiles_limit":100,
"timelimit_overshoot":"1s|10%",
"verification_required":0,
"show_affiliations":1,
"show_pending":0,
"show_compile":2,
"show_sample_output":0,
"show_balloons_postfreeze":1,
"penalty_time":20,
"compile_penalty":1,
"results_prio":{
"memory-limit":"99",
"output-limit":"99",
"run-error":"99",
"timelimit":"99",
"wrong-answer":"30",
"no-output":"10",
"correct":"1"
},
"results_remap":[

],
"lazy_eval_results":1,
"enable_printing":0,
"time_format":"%H:%M",
"default_compare":"compare",
"default_run":"run",
"allow_registration":0,
"judgehost_warning":30,
"judgehost_critical":120,
"thumbnail_size":128
}
---- GET api/submission_files ----
[
{
"filename":"biubiubiu.cpp",
"content":"I2luY2x1ZGUgPGNzdGRpbz4NCmludCBtYWluKCl7DQogcHJpbnRmKCIyMDRcbiIpOw0KIHJldHVybiAwOw0KfQ0K"
}
]

---- GET api/testcases ----
{
"testcaseid":6,
"rank":1,
"probid":4,
"md5sum_input":"495804e297ee23dbbef4ab1b7bb845ab",
"md5sum_output":"495804e297ee23dbbef4ab1b7bb845ab"
}
---- GET api/executable ----
String(base64_encode zip archive)

---- GET api/testcase_files ----
String(base64_encode plain file)

---- POST api/judging_runs ----
// POST omit

[NEUOJ] 测评后端分析 judgehost文件结构分析

[NEUOJ] 测评后端分析 judgehost文件结构分析

NEUOJ的测评后端暂时使用的是domjudge 的 judgehost作为测评后端 下面分析一下judgehost的工作原理

首先分析一下judgehost的几个核心文件的功能

[这里省略了从clone domjudge repo 到编译安装好judgehost这个过程, 我认为来看这篇文章的应该都是已经可以自己安装好domjudge的人,不然可能这篇文章对于你来说还不适合阅读]

首先看bin下面的文件

runguard 是负责保证用户程序的安全运行, 不会对系统进行破坏的程序, 这个的代码利用了 rlmit, cgroup timeout等方式对用户程序进行限制

judgedaemon 一个php脚本, 测评后端的完整进程, 包括通过服务器下载数据, 到调用相应可执行文件对代码进行编译运行比对之后. 将结果返回给webserver的整个过程都是由这个程序进行的

runpipe: 用于在runjury(特殊的测评程序) 和 user program之间建立双向管道,进行交互式测评(目前只了解这些)

create_cgroups: 在设置了enable_cgroup 的编译参数之后, 通过这个来创建domjudge的 control group, cgroup能够获得更精确的运行时间和使用资源情况

dj_make_chroot, dj_make_ubuntu_chroot: 用于让java程序可以在chroot环境下运行

再看etc文件夹下的文件

sudoers.domjudge: 这个文件配置好了 运行测评的时候的用户的sudo权限配置

common-config.php: 一些通常的config文件

judgehost-static.php: 通过make 和 make install生成的静态config文件,不要进行修改

restapi.secret: 里面存有向API请求的时候的API地址和认证信息

再看judgings文件夹

judgings文件夹下, 所有的文件都是测评的时候生成的, 他的第一级给每一个judgehost分配一个不同的文件夹,名字为 HOSTNAME-n  , 每一个judgehost都要以一个不同的用户来运行, 不然会产生问题

每个judgings文件夹下, 有多个endpoint, 每一个endpoint对应你再 restapi.secret里面配置的不同的名字

如endpoint-neuoj

每个endpoint下 , 有 这样的文件夹: c[n]-s[n]-j[n]  每一个文件夹内都是一次测评,如果这个测评之前被测过了, 重新测评的时候, 原来的测评会叫做 c[n]-s[n]-j[n]-old-timestamp , 除了每一个测评一个文件夹以外, 还有两个文件夹, 一个用于存从服务器fetch来的input output, 一个用于存从服务器fetch来的 executable 分别叫testcase executable

对于每一个测评文件夹下的文件分析留到之后解释

再看看log文件夹, log文件夹内只存了必要的log信息, 没有其他东西, 至于run 和 tmp文件夹, 目前不清楚

最后看lib文件夹 ,仅介绍主要的几个文件, 我们看 lib/judge下的文件

testcase_run.sh 是用于运行程序测评的脚本, 脚本接受多个参数 会在介绍judge流程的时候具体介绍

sh-static 一个静态的 shell

judgedaemon.main.php 整个测评运行的主要程序, 实际上 bin下的judgedaemon就是来调用这个程序的

chroot-startstop.sh: 处理chroot

check_diff.sh: 简单的compare脚本

compile.sh: 一个用于调用其他compile executable的wrapper,并且保证compile不超时, 不超资源

 

以上就是judgehost的一个简单的分析, 下一篇会介绍judgedaemon的测评流程

 

 

 

 

空间红包谜题解法(Linux + base64 + HTTP Header + 摩尔斯电码)

空间红包谜题解法(Linux + base64 + HTTP Header + 摩尔斯电码)

题目

解密红包, 支付宝中文口令红包

(后来被人说二维码扫完还得用电脑重输一遍网址好麻烦 = = 于是我就把二维码对应的网址给出来了 : http://1.justquiz.sinaapp.com/voidmengmengda) —- 这就是完整的题干了, 谜题总共有三关, 个人认为难度是递增的, 下面放出每一关的解法

解法

* 第一关

首先看第一关的内容, 网页本身查看源码并没有什么用处, 不过注意到标题, “请用桌面浏览器打开哦~” 桌面浏览器(即Chrome Firefox) 和一般的移动端浏览器的区别就是, 桌面浏览器支持开发者视图, 可以看到更多详细信息, 除了看到源码, 我们还可以看到cookie session storage等东西, 也包括请求的header, 而这一关的线索就藏在了header里, 在服务器Response你的Request的时候, 会在header里带上下一关的线索,  之后我在空间里也对第一关进行了提示, 有十多人在提示之后到达了第二关QAQ 比我预期的少了很多 附上第一关解决的截图(点击可查看大图) 图中的 HintURL 就是第二关的线索

 

* 第二关

( 列出服务器网站目录) 进入到第二关, 你会发现看到一个在线编译器, 以及这样一段提示想信息:

Happy New Year~! Congrats! You have solve the first Challenge! See what you can find here
Remember : This is a BUGGY online Compiler
This is a BUGGY online Compiler 表示这个在线编译器是有bug的, 具体是什么bug就需要大家自己去找了, 这一关我没有再给提示, 大家稍微尝试之后就会发现, 这个online Compiler没有禁止系统指令的执行, (虽然用户权限是正确的, 无法删除root 的文件, 但是还是有很多事情可以做的)  因而编写下面代码到在线编译器里 , (我选用C语言做示例)

执行之后 ,会显示如下信息 :

稍微留心一下, 就会发现, 你列出的目录, 就是你当前访问的网站所在的目录, 同一级 ,再仔细看一眼列表 ,找到提示文件 thisIStheHintYouNeed.html 通过浏览器访问这个文件 , 得到下一关的提示信息, 本关解决. 附上本关解决之后的截图(点击查看大图)

 

* 第三关

这是本谜题的最后一关了, 也是我制作的时候花时间最多的一关(毕竟第一次用CoolEdit 以前从来没玩过QAQ) 通过第二关的最后提示, 得到一个网址 : 在浏览器里访问改网址 得到类似下面的东西(仅截取部分做展示)

看到这种形式的文件, 第一反应就是base64编码, 尝试用在线解码器进行解码 , 结果发现解出乱码了 , 推测这可能是一个二进制文件, 于是用Linux下自带的解码工具 (Windows下也许也有,不过我不清楚00.00) 将文件解码之后, 输出到另一个文件, 注意不要带后缀名, 带后缀名会影响linux对文件类型的推测, 一会儿要进行文件类型的推测 执行下面指令得到解码后的文件 :

然后推测文件类型 , 通过hexdump xxd 等工具并没有看出文件是什么类型的 = = (也许是我自己能力不够) 因此使用linux下的file指令推测文件类型

通过这个可以看出, 这应该是一个媒体文件 , 因此用播放器对其进行播放 , (linux 下有工具 playsound 或者修改后缀名进行播放) 听到电报音, 长短结合,  想到可能是摩尔斯电码, 然后根据摩尔斯电码表对应下来 密码为  100081  转成中文 一零零八一, 输入进口令, 然而并不对 , 这是这一关的最后一个陷阱, 发现不对之后, 回去看一下第二关的提示URL :  最后面 drowssap.txt 看起来是不是很眼熟,  他就是单词password的逆转, 这是重要的提示信息,因此就说明要对摩尔斯电码进行逆转, 那么到底是把所有的数字颠倒顺序, 还是指把点(.) 和划(-) 的表示颠倒? 尝试之后发现 , 逆转得到的密码为  180001  而将点划表示颠倒之后得到的密码为  655536  作为一个程序员, 这两个选择哪个就不难决定了吧~  到此整个谜题全部解开了, 在支付宝页面输入正确的密码对应的中文, 就会拿到红包啦~    

 

 

后记 : 最后也没有人拿到那个红包QAQ,  不过还是有很多人很接近答案了~ 解密红包的乐趣在于解密而不是红包~ 我是玩的很愉快, 大家也玩的很愉快就好~

 

附上解密后的音频文件:

hint

以及摩尔斯电码对照表

数字

字符 电码符号 字符 电码符号 字符 电码符号 字符 电码符号
0 ━ ━ ━ ━ ━ 1 .━ ━ ━ ━ 2 ..━ ━ ━ 3 ...━ ━
4 ....━ 5 ..... 6 ━ .... 7 ━ ━ ...
8 ━ ━ ━ .. 9 ━ ━ ━ ━ .

 

[被迫参加的hackathon] 在线编译系统开发小记

[被迫参加的hackathon] 在线编译系统开发小记

吐槽

因为某种原因我没有参加MSC举办的Hackathon, 不过我的部员们参加了 0.0 然后我本来想去蹭点Pizza之类的东西吃,结果(我感觉他们是给我诱拐过去了) 到了比赛现场之后告诉我, 这里封馆了 Orz 于是乎我就被迫开始写代码(连电脑都没有带只为了去蹭口pizza吃的我TAT[结果最后还没吃到pizza])

实现的是一个简单的在线编译系统 TOC (Toy Online Compiler) 支持多种语言, 下面简单说一下实现的思路和核心的代码

实现思路

简单分析一下这个系统,由两部分组成 ,代码提交模块和代码编译运行模块 ,前者负责将代码交给后者,后者编译运行完毕将结果返回给前者,然后前者将结果展示给用户.

具体实现方式是: 代码提交模块负责将代码文件保存到服务器, 然后通过socket将消息通知到代码编译模块,然后代码编译模块执行完毕的结果再通过通信的方式传递回来, 很显然实现代码提交模块实现难度很容易,主要的问题在后者的编译模块的通信和编译问题, 下面给出编译模块的核心代码

这段代码就是编译模块的核心逻辑, 我使用了一个队列来维护所有在队列内的通信, 队列最多有5个元素,   代码运行起来会持续检查队列是否为空,如果队列不为空,就会取出队列头的socket,处理socket传来的消息,编译相应的代码,然后产生结果通过封装好的socket_write SockWrite,将运行结果回传给代码提交模块,重复上述操作.

为了保证代码的可读性, 封装了一个编译类 actionClass 来进行编译和运行, 编译和运行的方式是通过exec调用系统命令,下面会具体说明

 

实现细节

  •  编译和运行的方式是使用exec调用系统指令, exec指令可以直接将执行结果作为返回值,不过他的结果只能返回stdout里的内容,stderr的内容不能返回, 因此我使用的方式是 将stderr的内容重定向到文件 cerr.txt 然后检测此文件是否为空, 如果不为空的话说明出错了
  • 不过在最初实现的时候出现了这样的问题, 当你提交一个编译错误的代码之后,再提交一个可以正常运行的代码,编译模块仍然会报编译错误, 而如果手动查看这个文件发现这个文件大小为0 , 通过打印filesize(“cerr.txt”)的返回值,发现了 filesize的返回值不为0 ,但是此时cerr.txt文件大小为0 (du -h cerr.txt )  查资料发现,  filesize 的结果会调用缓存的结果  “Note: The results of this function are cached. See clearstatcache() for more details.“[php.net 原文] . 因此在每次取得filesize之后, 都要使用clearstatcache()将之前的状态清除掉
  • 另外遇到的一个问题就是在停止掉后端编译模块之后, 再次启动这个模块会报错 Unable to bind , address already in use , 这个问题在php.net 的官网也有说明

If you want to reuse address and port, and get rid of error: unable to bind, address already in use, you have to use socket_setopt (check actual spelling for this function in you PHP verison) before calling bind:

设置上   SO_REUSEADDR

 

  • 另外代码运行时限是使用Linux中的timeout的功能实现的
  • 当程序执行结果为空的时候(不产生任何输出) 代码提交模块会一直在socket_read()处等待到来消息, 因此通过自己实现了封装好的SockRead和SockWrite 来避免这个问题

 

 

目前实现阶段

  • 支持PHP C++ C Python Ruby 的编译(解释)运行
  • 可以在Raspberry Pi上搭建整个系统

待解决问题

  • 编译时使用sandbox来保证安全性 , 暂定使用chroot来实现sandbox功能
  • 登录和注册没有完全实现
  • 将这个代码布置到拥有防火墙的CentOS服务器上, 两个模块之间不能互相通信(这个问题一直还没解决)

 

[Laravel] 配置phpstorm支持laravel语法补全

[Laravel] 配置phpstorm支持laravel语法补全

QAQ 不得不说,想使用我喜欢的vim来完美的做到larvel的智能补全太难了(以后自己试试能不能写出来插件吧QAQ*()

因此我回到了以前开发时用过的phpstorm, 给phpstorm配置laravel插件, 操作很简单, 不过要注意版本的兼容问题.

1. (其实没有顺序啦) 安装PhpStorm的Laravel Plugin

在phpstorm里连按两下Shift ,打开指令输入窗口,输入 Plugin,  选择 Install Plugin, 搜索laravel插件并且安装.

2.使用Composer 安装 laravel-ide-helper

这个laravel-ide-helper插件是我们要想让上面的插件实现补全的必备依赖, 如果不安装这个插件的话是没有办法使用laravel的补全的功能的, 而这个插件安装的版本要和自己的laravel版本配套

  • 使用的是 4.2.*版本的laravel 需要安装1.11.*的插件
  • 5.* 版本的安装2.*的插件

注意如果版本不匹配是不能安装成功的 , 会提示你缺少依赖

 

附上laravel-ide-helper插件的地址: Laravel-Ide-Helper

[Laravel] 使用artisan时遇到的问题 (更新中)

[Laravel] 使用artisan时遇到的问题 (更新中)

运行 php artisan migrate 的时候 报错(错误信息见下面) 的解决方法

报错信息如下

这是因为配置里面少了 一个参数 “migrations” 的值, 加上这个参数

之后问题就解决了 ~~~

 

执行db:seed 时,遇到问题(问题见下文)

主要错误信息:

参考这篇文章:http://laravel.com/docs/5.1/upgrade#upgrade-4.1.26

在User.php 中加入 :

再次运行php artisan db:seed 就可以了~