1、使用 idoc 可实现看云基本的文档创作功能;
2、非常适合团队或者个人内部使用(写书、写笔记、写 api 文档都可以)
3、目前仅支持 markdown 编辑器(markdown 渲染仍有部分问题需要解决)
4、源码已发布在 github,项目地址:https://github.com/coderzheng/idoc
5、使用 php 原生代码编写,不依赖任何框架
6、Enjoy, http://idoc.codespeaking.com
1、使用 idoc 可实现看云基本的文档创作功能;
2、非常适合团队或者个人内部使用(写书、写笔记、写 api 文档都可以)
3、目前仅支持 markdown 编辑器(markdown 渲染仍有部分问题需要解决)
4、源码已发布在 github,项目地址:https://github.com/coderzheng/idoc
5、使用 php 原生代码编写,不依赖任何框架
6、Enjoy, http://idoc.codespeaking.com
1
qile1 Oct 7, 2019 via Android
如果我想把编辑的这些内容打印成纸质的有啥好办法分页没?如果我打印了一张半纸,我又添加了一些内容,如何在剩下的半张纸上继续从上次打印位置打印文件
|
2
rustkeyboard OP @qile1,打印了一张半纸的时候,临时再重新编辑文章内容,之后再继续打印?
|
4
windowsma Oct 8, 2019
不需要输入用户名密码也可以登录,这是怎么实现的(╬▔皿▔)凸
|
5
xiaotuzi Oct 8, 2019 via iPhone
我想爬看云的文档…
|
6
qile1 Oct 8, 2019 via Android
@rustkeyboard 只是添加内容,如果是编辑了,估计得重新打印了
比如第一次我书写如下笔记 '''20191020 测试新程序,调研准备开发 ''' 我把上面内容打印到一张纸上,可能只打印了一行 隔几天,又添加了一些内容 '''20191025 调研完成,准备编写文档 ''' 有没有办法打印到原来那张纸上,不要覆盖原来打印内容,这样就可以把自己的记录打印到一起,每次打印完都是连续的 |
7
yuankui Oct 8, 2019
php 果然是最好的语言
|
8
rustkeyboard OP @windowsma,一个小 bug 哈,已修复。
|
9
rustkeyboard OP @qile1,你这个问题有点意思。如果能实现这个需求,那么打印程序要完成以下步骤:
1、程序检测到纸张上已经存在有打印的内容(比如一张纸上有 3 行内容,第一行 aaa,第二行 bbb,第三行 ccc),自动获取最后一行的内容(ccc),并记录纸张上 ccc 行所在的位置; 2、程序将 ccc 这一行和即将进行打印的文本内容进行比较,自动定位到文本内容的 ccc 行; 3、程序发出指令给打印机,从文本内容 ccc 行下面的内容开始打印,并且这里最重要的一点是,需要告诉打印机,打印的位置是从纸张的 ccc 行下面一行开始打印。 然后我立刻按下 ctrl + p,查看了一下打印的设置界面,结论是:即使是手动设置里面也没有这么高级的选项。而且,在第二步这里存在一个似乎无法解决的问题:如果文本内容中包含有两个同样的 ccc 行,那要取哪个 ccc 行呢? |
10
lanyeol Oct 8, 2019
支持楼主
|
11
mokeyjay Oct 8, 2019
开源精神值得鼓励,不过需要提升的地方还有很多。举例:
- 数据库连接请使用 PDO,而不是 mysqli - 对于新手而言不依赖框架并不值得骄傲,反而容易导致很多安全隐患 - 前端体验较差,建议学习 ajax |
12
460881773 Oct 8, 2019
通过 4 楼有感 ,随便试试了 账号 1 密码 1 登录成功! 于是修改密码 123456 现在获得用户名 1 密码 123456 (╬▔皿▔)凸
|
15
wzhjii0 Oct 8, 2019
|
16
dafengchui Oct 8, 2019
|
17
markgor Oct 8, 2019
赞成 11L +1
提提几个问题: 1、输入内容未进行过滤。 创建主题时候,直接输入 JS 代码就能直接 XSS 注入了。(我输入了个</script>window.location.href="http://www.v2ex.com";</script>,現在訪問跳轉來 V2EX 了。 2、權限控制沒做好。 通過 POSTMAN,直接修改參數提交到 admin/api.php 就可以了。哪怕不是自己創建的。 3、存在 SQL 注入點- |
18
xbx1209 Oct 8, 2019
@rustkeyboard #9
为啥不换个思路 程序上记住本次打印内容至 xx 行 后来新增了新内容后,内容变成了 A 当要打印新增内容时 程序生成新的内容 B:第 1 行至 xx 行为空行,然后接下去上次打印后新增编辑内容 打印机这边手动插入上次的纸 然后就打印内容 B 就好了,打印出来的结果就跟内容 A 是一样的 |
19
cydian Oct 8, 2019 via Android
好东西。坐等更新楼上的安全漏洞。
很想部署,但是楼上说的安全漏洞令人担忧啊 |
20
anyc007 Oct 8, 2019
赞同楼上,有问题哦 xss 之类
|
21
markgor Oct 8, 2019
換成 PDO,參數綁定下,SQL 注入問題解決。
XSS 注入的問題,過濾下,可以用 HTMLPurifier 來過濾,千萬不要只是在前端進行過濾。 權限控制,沒什麼好說的。進行修改刪除添加的時候判斷下資源是否屬於當前用戶。 |
22
markgor Oct 8, 2019
另外 LS 說到打印的問題。
其實沒那麼複雜吧。 每次保存後記錄本次新增內容, 頁面生成的時候根據每次新增的內容用不同 DIV 包裹著,點擊打印的時候讓用戶選擇打印哪些內容,不需要打印的用 visibility 來佔位隱藏,配合 jqprint 就可以了。 不過實際上還會有些問題,例如用戶是修改了上次的內容,那那種辦法都不實際。 而且我覺得這個問題有點杠,不是不可能實現,而是沒必要實現。日常使用中,就算反面打印(手工)都會出現放錯紙,何況現在要增量打印?而且紙張價格不貴吧.......別扯環保問題,環保問題是有錢人才談論的。 |
23
rustkeyboard OP |
24
markgor Oct 8, 2019
@rustkeyboard
> $pids = $_SESSION['pids']; > $prid = $_REQUEST['prid']; > if ( strpos($pids, $prid) === false ) { > echo json_encode(['status'=>'FAIL', 'msg'=>'非法的操作!']); > exit; > } 如沒猜錯你是想判斷這兩個 ID 是否相等,不相等就沒權限處理吧? 但你這裡的 strpos 用的我是相當迷茫..... 查找 登錄 ID 在提交 ID 首次出現的位置。 那麼假設登錄 ID 固定為 12,當我需要改用戶 ID 為 13 的文章, 我只需要提交 prid=1 或者 2 那樣我就能繞過去了. 為什麼你不用 === 來判斷? $pids == $prid ,這樣不是更好嗎? 然後突然間我發現另一個問題, 為什麼你會在這裡進行判斷, 就算你用==來判斷,最終執行 SQL 的時候,還是成功執行了,為什麼不在 SQL 裡的 where 加條件? update xxx set xxxx WHERE pids = $prid 然後根據影響條數來判斷操作成功失敗? |
25
dafengchui Oct 8, 2019
@rustkeyboard 什么时候可以用类似左侧导航的模版, 我等很久了.
|
26
rustkeyboard OP @markgor,这里确实有点问题,刚刚已经修复了。
|
27
rustkeyboard OP @dafengchui , 左侧导航这个需求,可以考虑将来站点功能完善了之后,采用更换模板的问题来解决。已经加在需求列表中,等前面主要的功能都完成,就会添加,感谢关注, ^_^。
|
28
markgor Oct 8, 2019
@rustkeyboard
[url]http://idoc.codespeaking.com/book.php?id=8},function(a){});alert(123123);var%20a%20=%20({[/url] CSRF 漏洞 老實說,如果您覺得聽不進去就算了, 先拋開體驗度和功能,這套代碼要正式使用還有一大堆問題需要修復。 而且看你開源的代碼,感覺應該屬於練手系列吧? 你有個 api.php 的文件,是只處理後台的請求?然後前台的請求就分散各個頁面單獨處理, 這樣的話對於你後期擴展功能會很不方便。 另外看你 book.php 這個頁面,其實沒必要 BOOK.PHP 執行一次查詢,然後再通過 AJAX,獲取另一次查詢的結果。與其這樣還不如直接在 book.php 里完成查詢,或 BOOK.Php 改為靜態,內容通過一次 ajax 進行查詢回來? 還有 timestamp 這個類型真的不建議使用,項目大了之後到 2038 年就後悔死自己了。 |
29
rustkeyboard OP @markgor,已修复。
|
30
GG668v26Fd55CP5W Oct 8, 2019 via iPhone
卧槽,这简直教科书式的安全漏洞
|
31
rustkeyboard OP @falcon05,idoc 现在像是个初生的婴儿,由于没有框架的防护机制,难免会存在一些问题。有漏洞是正常的,想办法找出漏洞并解决它才是重点。
|
32
markgor Oct 9, 2019
|
33
rustkeyboard OP @markgor,你确定这里有问题? prid 可以伪造,但是$prids 是登录之后是由后端查询数据库自动保存在 session 中的。
再回来讲一下你说的可能存在的问题(24L), "那麼假設登錄 ID 固定為 12,當我需要改用戶 ID 為 13 的文章, 我只需要提交 prid=1 或者 2 那樣我就能繞過去了." 登录 ID 固定为 12,实际上$prids 的值是",12,", 此时你提交 prid=1,在 strpos 里面由于前后被自动拼接了逗号,会变成",1,",显然 strpos(",12,", ",1,") === false 是成立的。没绕过去吧?你觉得你要怎样才能绕过去呢?提交 12 对吧,如果提交 12,确实是绕过去了,但是这种情况和你登录之后在后台进行操作没有区别,程序认为你有权限操作自己的项目和文章,请问有什么问题? |
34
markgor Oct 9, 2019
@rustkeyboard 圖片掛了,你可以看看 book.php?id=8
你查查數據庫這條文字的更新時間和更新記錄吧。 POST:http://idoc.codespeaking.com/admin/api.php did:17 node_type:0 article_content:123" onload="alert(/again/) act:save_article_content prid:32 did->17 是文字的 ID,這個沒問題 prid->32 是我自己伪造的。 ID:17 的這文章並非我添加的,但是我能直接修改刪除,你覺得有問題嗎? |
35
rustkeyboard OP 不好意思,刚刚回复的这一条,有个地方输错了,
登录 ID 固定为 12, 实际上$pids 的值是",12," |
36
markgor Oct 9, 2019
或者我說白點吧,
$pids -> 是 session 中的,我沒理解應為 project_ids 即項目 ID 的意思吧, 添加文章後,數據庫保存了添加的 ID,還有項目的 id(prid) 沒錯吧? 然後修改的時候,通過判斷 提交的 prid 是否包含在 session 中的 pids ,如果包含在裡面的話就執行更新;這裡沒錯吧? 那麼你自己也說,prid 是可以伪造的,既然判斷條件是可以伪造,那你怎麼保證判斷的結果不是伪造的結果呢? 假設: session 中的 pids=32 我直接提交伪造 prid = 32 那這個判斷就已經過去了吧? 然後直接就執行了 undate 或 delete 了。 |
37
rustkeyboard OP @markgor , 这个无需争论,你可以试试通过 api 删除列表里面的第一个项,"大话星程"那本书,你能删掉里面的子节点(书里面的具体章节)或者直接把整本书都删了,再说。
|
38
markgor Oct 9, 2019
@rustkeyboard 已刪
|
39
markgor Oct 9, 2019
header:
Cookie:PHPSESSID=dcfab8f112bb806089dba16dbb109362 POST:XXXX/admin/api.php body: pid:6 act:delete_project prid:32 response: {"status":"SUCC","msg":"\u64cd\u4f5c\u6210\u529f!"} |
40
markgor Oct 9, 2019 via Android
通白点解释就是
两个狼友去按摩, 小明点了个 QT 小强点了个 Kb 老板分配手牌给小明,编号 12 分配手牌给小强,编号 55 然后他们各自进房,小强看到有 JS 经过时候,马上拉她进去,说我手牌是 12, 此时 JS 拿起房间电话打去前台说 12 上钟,前台看到有 12 这个编号,就回复他要做 QT,然后挂了。 小强做完一些嘿嘿嘿的事情后,拿出手牌根据 KB 的价格买单走人了 |
41
rustkeyboard OP @markgor,感谢反馈,已修复。
|
42
lufeng08 Oct 11, 2019
|