WackoWiki 6.3.0 API 使用详解
实测 WackoWiki 6.3.0 的 HTTP 接口:页面源码、修订历史与差异、XML 导出与 RSS 变更订阅、搜索、页面创建/编辑、附件上传下载、评论、逐页 ACL 与后台管理端点,含 Cookie 会话、一次性 nonce、409 覆盖告警与真实排障记录。
WackoWiki 6.3.0 API 使用详解
目标:WackoWiki 没有 REST/GraphQL JSON API,也没有命令行管理脚本或控制台;它对外真正可用的是 HTTP 页面接口、表单写入端点、RSS/XML 订阅与后台管理端点。本篇按 2026-11-02 的实测,把“怎么调、传什么、返回什么、哪里会失败”逐项讲清。软件定位与选型见《WackoWiki 介绍与选型指南》。
一、环境信息
- WackoWiki 版本:6.3.0(官方发布日期 2026-07-18)
- Web 服务:Apache 2.4.69(Debian),PHP 8.3.36
- 数据库:MariaDB 11.4.13(
11.4.13-MariaDB-ubu2404) - 站点名称:
WackoWiki Demo - 站点根地址:
http://localhost:8140/ - 首页:
HomePage - 测试页面:
S9WackoDemo(页面/修订/搜索/订阅)、S9ApiDemo(创建/编辑/上传/评论/ACL) - 演示账号:
root/q1w2e3r4;后台恢复口令同值(实验短口令,生产按 ≥15 位设置) - 客户端:curl 8.x(Ubuntu 26.04.1 LTS 宿主机)
- 实测日期:2026-11-02
💡 接口定性:后台菜单只有 Web 表单,没有“管理脚本/控制台/CLI”。因此本篇按 API 使用篇(D5)编写,而不是 CLI 命令篇(D1)。机器可读输出集中在
_revisions.xml、_export.xml与xml/changes_*.xml三类 XML;其余端点返回 HTML。
二、前置条件
- 站点可从服务器本机访问,首页返回 200:
BASE=http://localhost:8140
curl -sS -o /dev/null -w '%{http_code} %{content_type}\n' "$BASE/"
200 text/html; charset=utf-8
- 客户端具备
curl、grep、sed,并能保存 Cookie:
curl --version | head -1
curl 8.5.0 (x86_64-pc-linux-gnu) libcurl/8.5.0 OpenSSL/3.0.13 zlib/1.3
- 需要写入操作时准备管理员账号;只读接口可匿名访问(受页面 ACL 限制)。
- 写入端点全部依赖表单里的
_nonce,调用方必须先 GET 表单、取出 nonce,再 POST。 - 页面名区分大小写;URL 中的页面名就是 Wiki 页面标识(如
S9ApiDemo)。
三、接口总览
| 能力 | 方法与路径 | 认证/权限 | 返回形态 | 实测状态 |
|---|---|---|---|---|
| 首页/普通页面 | GET /、GET /<Page> | 按页面 read ACL | HTML | 200 |
| 页面源码 | GET /<Page>/_source | read ACL | HTML(<pre>) | 200 / 403 |
| 修订历史 | GET /<Page>/_revisions | read ACL | HTML | 200 |
| 修订订阅 | GET /<Page>/_revisions.xml | read ACL | RSS 2.0 | 200 |
| 版本差异 | GET /<Page>/_diff?a=&b=&diffmode= | read ACL | HTML | 200 / 403 |
| 单页导出 | GET /<Page>/_export.xml | export_handler + 登录 | RSS 2.0 | 200(可能含 Error item) |
| 全站变更订阅 | GET /xml/changes_<站点名>.xml | 无 | RSS 2.0 静态文件 | 200 / 404 |
| 搜索 | GET /Search?phrase=&topic=&p= | 无 | HTML | 200 |
| 新建/编辑页面 | GET /<Page>/_edit[?add=1] + POST /<Page>/_edit | write ACL + _nonce | 302 → HTML | 302 |
| 评论 | POST /<Page>/_addcomment | comment ACL + _nonce | 302 → HTML | 302 |
| 逐页 ACL | POST /<Page>/_permissions | write ACL + _nonce | 302 → HTML | 302 |
| 上传附件 | GET/POST /<Page>/_upload | upload ACL + _nonce | 302 → HTML | 302 |
| 下载附件 | GET /<Page>/_file?get=<文件名> | read ACL | 文件字节流 | 200 |
| 附件元数据 | GET /<Page>/_filemeta?m=show&file_id= | read ACL | HTML | 200 |
| 后台管理 | GET/POST /admin.php?mode= | Wiki 管理员会话 + 恢复口令 | HTML | 200 / 302 |
⚠️ 这不是 REST:没有资源路径版本号、没有 JSON、没有统一的错误体。写入用
application/x-www-form-urlencoded(上传用multipart/form-data),成功统一返回 302 跳转,失败则返回 200/409 并在页面里给出提示文本。
四、认证与会话
4.1 前台登录
先 GET 登录页并保存 Cookie,同时从表单取出 _nonce:
curl -sS -c ck.txt -o login_get.html "$BASE/Login"
grep -o 'name="_nonce" value="[^"]*"' login_get.html | head -1
<input type="hidden" name="_nonce" value="B7U89uSXXLb" />
登录表单的关键字段:
| 字段 | 示例值 | 说明 |
|---|---|---|
_action | login | 固定动作 |
_nonce | B7U89uSXXLb | 一次性 CSRF 令牌 |
user_name | root | 用户名 |
password | q1w2e3r4 | 密码 |
persistent | (可选) | 记住登录 |
提交:
curl -sS -b ck.txt -c ck.txt -L \
--data-urlencode '_action=login' \
--data-urlencode '_nonce=B7U89uSXXLb' \
--data-urlencode 'user_name=root' \
--data-urlencode 'password=q1w2e3r4' \
-o login_post.html -D login_post.hdr \
"$BASE/Login"
实测响应:
HTTP/1.1 302 Moved Temporarily
Server: Apache/2.4.69 (Debian)
X-Powered-By: PHP/8.3.36
Set-Cookie: LocalhostwSKwXXAuth=cHiIr_...; expires=Wed, 02 Dec 2026 10:34:42 GMT; Max-Age=2592000; path=/; httponly; SameSite=Lax
Location: /Users/Root?3xBZ
Content-Length: 0
跟随跳转后为 200,页面标题为:
<title>Root - WackoWiki Demo</title>
Cookie 名形如 LocalhostwSKwXXAuth,与站点主机名绑定;把 ck.txt 用作后续所有请求的会话即可。
错误口令返回 302 到 /Login?Redo,页面提示:
The username or password you have entered is invalid.
💡
curl不加-L时只会看到 302 和空响应体,容易误判“登录失败”。判断登录成功应同时检查Location与 Cookie 罐。
4.2 一次性 nonce
所有写操作表单都带 _nonce。该令牌与表单绑定,用过一次即失效。重复提交同一个 nonce 时,页面返回:
The submitted form was invalid. Try submitting again.
调用约定:每个写请求前重新 GET 目标表单,解析 _nonce,再提交;不要缓存 nonce,也不要用 A 表单的 nonce 提交 B 表单。
4.3 后台二次认证
后台入口 /admin.php 有两道门:
- 当前会话必须是 Wiki 管理员;否则直接 302 到首页:
HTTP/1.1 302 Moved Temporarily
Location: /HomePage
- 通过第一道门后,页面要求输入后台恢复口令,标题为:
Administration Control Panel : Authorization
表单字段:
| 字段 | 示例值 | 说明 |
|---|---|---|
_action | ap_login | 固定动作 |
_nonce | 表单值 | 一次性令牌 |
ap_password | q1w2e3r4 | 恢复口令(config.php 中的 recovery_password) |
登录成功后标题变为:
Administration Control Panel : Basic functions > Main Menu
⚠️ 恢复口令与前台用户密码是两套校验:前台密码在
wacko_user表,恢复口令走password_verify()校验recovery_password哈希;两者不要混用。
五、读取接口
5.1 普通页面
curl -sS -D home.hdr -o home.html "$BASE/"
实测响应头:
HTTP/1.1 200 OK
Server: Apache/2.4.69 (Debian)
Content-Security-Policy: default-src 'self';base-uri 'self';form-action 'self';frame-ancestors 'self';...
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
Content-Length: 4991
Content-Type: text/html; charset=utf-8
页面正文即 Wiki 渲染结果;没有“内容接口”,要拿结构化内容只能用下面的源码或导出端点。
5.2 页面源码 _source
curl -sS -o page_source "$BASE/S9WackoDemo/_source"
返回 HTML 中的 <pre> 就是原始 Wiki 标记:
<pre id="cb-CR636vQ" class="code source-handler">= WackoWiki 功能验证页 =
本页用于验证 WackoWiki 6.3.0 的页面创建、修订、搜索与附件功能。
== 列表 ==
* 创建页面
* 编辑并生成修订
* 全文检索
== 第二修订 ==
第二次编辑追加的段落,用于验证修订历史。
== 第三修订 ==
第三次编辑用于触发 RSS/XML 订阅文件生成。
</pre>
源码端点受页面 read ACL 控制。把页面 read 设为私有后,匿名访问返回 403:
HTTP/1.1 403 Forbidden
Content-Length: 3079
Content-Type: text/html; charset=utf-8
页面提示:
You aren't allowed to read this page.
5.3 不存在的页面
curl -sS -o notfound.html -w '%{http_code}\n' "$BASE/NoSuchPage12345"
404
页面标题与提示:
<title>No Such Page 12345 - WackoWiki Demo</title>
This page doesn't exist.
六、版本与导出接口
6.1 修订历史 _revisions
curl -sS -o page_revisions "$BASE/S9WackoDemo/_revisions"
页面列出该页全部修订,实测版本号为 3、2、1(倒序)。页面同时提供指向 _revisions.xml 的订阅链接。
6.2 修订订阅 _revisions.xml
curl -sS -o page_revisions.xml "$BASE/S9WackoDemo/_revisions.xml"
实测 200,1,503 字节,2 条 <item>;最新修订的链接为 ?revision_id=2,上一条为 ?revision_id=1:
<channel>
<title>WackoWiki Demo - S9WackoDemo</title>
<link>http://localhost:8140/S9WackoDemo</link>
<description>Revisions of WackoWiki Demo: S9WackoDemo</description>
<language>en</language>
<item>
<title>Root: </title>
<link>/S9WackoDemo?revision_id=2</link>
<description><![CDATA[<br><strong>Additions:</strong><br>
<div class="additions"><pre>== 第三修订 ==
第三次编辑用于触发 RSS/XML 订阅文件生成。
</pre></div>...]]></description>
<pubDate>Mon, 02 Nov 2026 10:03:46 +0000</pubDate>
</item>
...
</channel>
description 里是本次修订的增删片段,而不是整页正文。要拿整页正文应使用 _export.xml。
再次编辑 S9ApiDemo 后,该页的 _revisions.xml 为 1,835 字节,2 条 <item>,链接分别是 ?revision_id=4 与 ?revision_id=3。
6.3 版本差异 _diff
curl -sS -o diff.html "$BASE/S9WackoDemo/_diff?a=1&b=2"
实测 200,6,504 字节,标题 S9 Wacko Demo (diff) - WackoWiki Demo,差异片段:
<ins class="diff">== 第二修订 ==
第二次编辑追加的段落,用于验证修订历史。</ins>
diffmode 取值:
| 值 | 模式 | 说明 |
|---|---|---|
0 | Full diff | 完整差异(默认) |
1 | Simple | 简化差异 |
2 | Source | 源码对照 |
3 | Side by side | 并排对照 |
4 | Inline | 行内差异 |
5 | Merged | 合并视图 |
a、b 必须是该页真实存在的修订 ID。实测在 S9ApiDemo 上传入不匹配的 a=1&b=2 会得到 403;用 a=3&b=4 则返回 200,标题 S9 API Demo (diff) - WackoWiki Demo。
6.4 单页导出 _export.xml
匿名请求:
curl -sS -o page_export.xml -w '%{http_code} %{size_download}\n' "$BASE/S9WackoDemo/_export.xml"
200 530
返回 200,但内容是错误条目:
<item>
<title>Error</title>
<link>/S9WackoDemo/show</link>
<description>You're not allowed to access this information.</description>
</item>
带会话再请求:
curl -sS -b ck.txt -o export_auth.xml -w '%{http_code} %{size_download}\n' "$BASE/S9WackoDemo/_export.xml"
200 977
这次返回完整页面正文:
<item>
<title>S9 Wacko Demo</title>
<link>http://localhost:8140/S9WackoDemo</link>
<description><![CDATA[= WackoWiki 功能验证页 =
本页用于验证 WackoWiki 6.3.0 的页面创建、修订、搜索与附件功能。
== 列表 ==
* 创建页面
* 编辑并生成修订
* 全文检索...
]]></description>
<author>Root</author>
<pubDate>Mon, 02 Nov 2026 10:02:41 GMT</pubDate>
</item>
原因在配置:export_handler=2 表示“仅登录用户可导出”。匿名不是收到 403,而是收到 200 + Error item——必须解析 item 标题,不能只看状态码。
七、订阅接口
站点级变更订阅的 URL 规则为:
/xml/changes_<站点名归一化>.xml
WackoWiki Demo 去掉非字母数字并转小写后得到 wackowikidemo:
curl -sS -o changes_now.xml -w '%{http_code} %{size_download}\n' \
"$BASE/xml/changes_wackowikidemo.xml"
200 1238
实测内容(2 条记录,最新在前):
<channel>
<title>WackoWiki Demo - Recent changes</title>
<description>Recent changes to the WackoWiki Demo</description>
<lastBuildDate>Mon, 02 Nov 2026 10:39:36 +0000</lastBuildDate>
<item>
<title>S9ApiDemo</title>
<link>http://localhost:8140/S9ApiDemo/_diff?a=3&b=&diffmode=3</link>
<guid>http://localhost:8140/S9ApiDemo</guid>
<pubDate>Mon, 02 Nov 2026 10:39:36 +0000</pubDate>
<description>2026-11-02 10:39:36 by Root</description>
</item>
<item>
<title>S9WackoDemo</title>
<link>http://localhost:8140/S9WackoDemo/_diff?a=2&b=&diffmode=3</link>
<pubDate>Mon, 02 Nov 2026 10:05:37 +0000</pubDate>
<description>2026-11-02 10:05:37 by Root</description>
</item>
</channel>
要点:
- 文件由页面保存/评论时生成,属于静态文件,不是每次请求实时查询;最新记录最多 30 条。
- 文件写在站点根目录的
xml/下;该目录对 Web 进程不可写时,页面仍能保存,但订阅文件不会更新或直接 404。 - 站点改名后 URL 随之变化,旧文件不会自动改名。
- 本实例未启用评论订阅、新闻订阅与 Sitemap,实测
/xml/comments_wackowikidemo.xml、/xml/news_wackowikidemo.xml、/xml/sitemap_wackowikidemo.xml均返回 404(324 字节的 404 页)。
八、搜索接口
curl -sS -o search.html "$BASE/Search?phrase=WackoWiki"
实测 200,5,570 字节,结果区文本:
Search results for «WackoWiki» (2):
Home Page 11/02/2026 09:10 - System - 331.0 B
Welcome to your WackoWiki ...
S9 Wacko Demo 11/02/2026 10:05 - Root - ...
标题搜索:
curl -sS -o search_topic.html "$BASE/Search?phrase=S9Api&topic=1"
实测 200,4,902 字节,命中 1 条:
results for «S9Api» (1): S9 API Demo 11/02/2026 10:41 - Root - 118.0 B
无结果时:
curl -sS -o search_nohit.html "$BASE/Search?phrase=zzz_no_such_term_2026"
页面文本:
No results for "zzz_no_such_term_2026"
参数:
| 参数 | 取值 | 默认 | 说明 |
|---|---|---|---|
phrase | 任意字符串 | 空 | 少于 3 个字符不执行检索 |
topic | 1 | 关闭 | 只搜页面标题/标签,不搜正文 |
p | 页码 | 1 | 结果分页 |
max | 每页条数 | 10 | 覆盖系统默认值 |
lang | 语言代码 | 空 | 只搜指定 page_lang |
scope | pages / all | all | pages 只搜页面,all 含评论 |
分页示例:
curl -sS -o search_p2.html -w '%{http_code} %{size_download}\n' \
"$BASE/Search?phrase=WackoWiki&p=2"
200 5570
本实例只有 2 条命中,p=2 仍返回同一结果集(页面没有第 2 页时回落到第 1 页内容)。结果按相关度(MySQL MATCH ... AGAINST 分数)倒序,标题搜索按页面标签排序。
九、写入接口:页面创建与编辑
9.1 取编辑表单
新页面用 ?add=1:
curl -sS -b ck.txt -o edit_new.html -w '%{http_code} %{size_download}\n' \
"$BASE/S9ApiDemo/_edit?add=1"
200 8003
表单字段:
| 字段 | 示例值 | 说明 |
|---|---|---|
_action | edit_page | 固定动作 |
_nonce | 7gv33IpDuYP | 一次性令牌 |
section | 0 | 整页编辑;其他值表示段落编辑 |
h_level | 1 | 标题层级 |
previous | 2026-11-02 10:35:25 | 编辑基线时间(HTML 实体编码) |
title | S9 API Demo | 页面标题 |
body | 多行文本 | Wiki 正文 |
9.2 创建页面
curl -sS -b ck.txt -c ck.txt -o create_page.html -D create_post.hdr \
--data-urlencode '_action=edit_page' \
--data-urlencode '_nonce=7gv33IpDuYP' \
--data-urlencode 'section=0' \
--data-urlencode 'h_level=1' \
--data-urlencode 'previous=2026-11-02 10:35:25' \
--data-urlencode 'title=S9 API Demo' \
--data-urlencode 'body=//S9 API demo page//
Created via HTTP form API at 2026-11-02.' \
"$BASE/S9ApiDemo/_edit"
实测响应:
HTTP/1.1 302 Moved Temporarily
Location: /S9ApiDemo
Content-Length: 0
跟随跳转后 200,页面创建成功,page_id=18,version_id=3,revisions=2(创建算 1 次修订,随后编辑再生成 1 次)。
9.3 二次编辑与覆盖保护
再次编辑必须先 GET 当前页面编辑表单,原样取回 previous:
curl -sS -b ck.txt -o edit4.html "$BASE/S9ApiDemo/_edit"
实测 previous 为:
2026-11-02 10:39:36
即 HTML 实体编码的空格( )与冒号(:)。提交前必须解码为 2026-11-02 10:39:36,否则服务端判定基线不一致,返回 409 与提示:
HTTP/1.1 409 Conflict
OVERWRITE ALERT: This page was modified by someone else while you were editing it.
Please copy your changes and re-edit this page.
解码后提交:
curl -sS -b ck.txt -c ck.txt -o edit4_after.html -D edit4_post.hdr \
--data-urlencode '_action=edit_page' \
--data-urlencode '_nonce=<取自 edit4.html>' \
--data-urlencode 'section=0' \
--data-urlencode 'h_level=1' \
--data-urlencode 'previous=2026-11-02 10:39:36' \
--data-urlencode 'title=S9 API Demo' \
--data-urlencode 'body=//S9 API demo page//
Created via HTTP form API at 2026-11-02.
== 第二版 ==
Revision created through the edit API.' \
"$BASE/S9ApiDemo/_edit"
实测 302 → /S9ApiDemo,随后 200,version_id=3、revisions=2 保持不变(同一修订链按版本号推进)。
⚠️
previous的 HTML 实体是踩坑高发点:直接从页面复制 hidden 值会带入 与:,看起来是空格和冒号,服务端按字面比较就会冲突。用脚本解析时必须解码。
十、评论与逐页 ACL
10.1 发表评论
评论表单在页面底部,动作路径为 /<Page>/_addcomment,字段:
| 字段 | 示例值 | 说明 |
|---|---|---|
_action | add_comment | 固定动作 |
_nonce | 表单值 | 一次性令牌 |
parent_id | 0 | 顶层评论 |
title | (可选) | 评论标题 |
body | 多行文本 | 评论正文 |
提交实测返回:
HTTP/1.1 302 Moved Temporarily
Location: /S9ApiDemo?show_comments=1&p=last#Comment1
Content-Length: 0
跟随跳转后页面出现:
Comment added.
10.2 逐页 ACL
表单路径为 /<Page>/_permissions,动作 _action=set_permissions,五个 textarea 分别对应五类权限:
| 字段 | 权限 | 实测值 |
|---|---|---|
read_acl | 读 | * |
write_acl | 写 | Admins\nModerator |
comment_acl | 评论 | Admins |
create_acl | 创建子页 | $ |
upload_acl | 上传 | Admins |
规则:
- 一行一个主体,不是逗号分隔。写成
Admins,Moderator会得到Access control list syntax error。 *表示所有人(含匿名),$表示已注册用户,其余按用户名/组名匹配。- 提交成功后页面提示:
Access control lists updated
- 再次提交同一个
_nonce会得到The submitted form was invalid. Try submitting again.,必须重新 GET 表单。
十一、附件上传与下载
11.1 上传
上传表单路径 /<Page>/_upload,enctype="multipart/form-data",字段:
| 字段 | 示例值 | 说明 |
|---|---|---|
_action | upload | 固定动作 |
_nonce | vPRHqIPWGUD | 一次性令牌 |
upload | 1 | 必须为 1,缺失会被当作普通页面请求 |
MAX_FILE_SIZE | 512000 | 表单侧上限(字节) |
upload_to | local / global | 页面级附件或全局附件 |
file | 文件 | 待上传文件 |
file_description | (可选) | 附件说明 |
file_overwrite | 1 | 允许覆盖同名文件 |
提交:
curl -sS -b ck.txt -c ck.txt -o upload_after2.html -D upload_post2.hdr \
-F '_action=upload' \
-F '_nonce=vPRHqIPWGUD' \
-F 'upload=1' \
-F 'MAX_FILE_SIZE=512000' \
-F 'upload_to=local' \
-F 'file=@s9api-upload.txt;type=text/plain' \
-F 'file_description=API upload test' \
"$BASE/S9ApiDemo/_upload"
实测响应:
HTTP/1.1 302 Moved Temporarily
Location: /S9ApiDemo/_filemeta?m=show&file_id=3
Content-Length: 0
跟随跳转后页面提示:
File upload successful
11.2 下载
curl -sS -D file_dl.hdr -o file_dl.bin \
"$BASE/S9ApiDemo/_file?get=s9api-upload.txt"
实测响应头:
HTTP/1.1 200 OK
Server: Apache/2.4.69 (Debian)
Cache-Control: max-age=2592000
Last-Modified: Mon, 02 Nov 2026 10:35:45 GMT
Content-Length: 37
Content-Disposition: inline; filename="s9api-upload.txt"
X-Content-Type-Options: nosniff
Content-Type: text/plain;charset=UTF-8
正文 37 字节,即上传文本原样返回。下载走页面的 read ACL,不额外校验上传者身份。
11.3 附件元数据
curl -sS -b ck.txt -o files.html "$BASE/S9ApiDemo/_filemeta?m=show&file_id=3"
返回附件详情页(文件名、大小、上传者、下载链接等),适合在脚本里核对上传结果。
十二、后台管理接口
后台只有 Web 入口 /admin.php?mode=<模块>,没有 JSON API。常用模块:
mode | 页面 | 用途 |
|---|---|---|
system_info | System Info | 版本、PHP/Apache/数据库、扩展、目录权限 |
system_statistics | Statistics | 各表记录数、目录文件数与体积 |
system_log | System Log | 系统日志(最多 100 条) |
db_backup | Database Backup | 按表/目录导出备份 |
db_restore | Database Restore | 恢复备份 |
db_repair | Database Repair | 表检查/修复 |
user_users | Users | 用户列表、编辑、删除 |
user_groups | Groups | 用户组管理 |
config_basic 等 | Configuration | 基础/外观/邮件/权限/安全/上传等分组设置 |
content_menu / content_deleted | Content | 菜单与已删除页面 |
maint_resync / maint_inconsistencies | Maintenance | 重同步与一致性检查 |
12.1 系统信息
curl -sS -b ck.txt -o admin_system_info.html "$BASE/admin.php?mode=system_info"
实测页面关键值:
WackoWiki 6.3.0
Apache/2.4.69 (Debian)
MariaDB 11.4.13
PHP 8.3.36
UTF-8
memory_limit 128.0 MiB
12.2 系统日志与过滤
curl -sS -b ck.txt -o admin_system_log.html "$BASE/admin.php?mode=system_log"
grep -o 'name="_action" value="[^"]*"' admin_system_log.html
name="_action" value="systemlog"
日志表单字段 level_mod(阈值关系)与 level(级别):
| 字段 | 实测可选值 | 说明 |
|---|---|---|
level_mod | equal / not higher than | 等于 / 不高于 |
level | 1: critical、2: highest、3: high、4: medium、5: low、6: lowest | 日志级别 |
p | 页码 | 分页,单页最多 100 条 |
提交筛选(level_mod=2、level=3)后,页面回显:
<option value="2" selected>not higher than</option>
<option value="3" selected>3: high</option>
12.3 用户列表与排序
curl -sS -b ck.txt -o admin_users_sorted.html \
"$BASE/admin.php?mode=user_users&order=user_name_desc&user=Root"
实测命中管理员行:
Root root@example.com 2 1 3 3 en
参数:
| 参数 | 说明 |
|---|---|
order | 排序,如 user_name_desc |
user | 按用户名过滤 |
p | 页码 |
12.4 数据库备份
curl -sS -b ck.txt -o admin_db_backup.html "$BASE/admin.php?mode=db_backup"
页面表单按表提供 __str__<table>(结构)与 __dat__<table>(数据)复选框,另有 __dir__file/global、__dir__file/perpage 目录备份项与 log_note 备注。实测覆盖 wacko_acl、wacko_page、wacko_revision、wacko_user、wacko_config 等表。
⚠️ 后台所有写操作同样带
_nonce,且后台会话与前台会话共用 Cookie;先用前台管理员登录,再完成ap_login,顺序反了会 302 回首页。
十三、分页、过滤与排序汇总
| 端点 | 分页参数 | 过滤/排序 | 单页上限 |
|---|---|---|---|
/Search | p | phrase、topic、lang、scope | max,默认 10 |
/<Page>/_revisions | — | limit(默认 100)、minor、deleted | 100 |
/<Page>/_revisions.xml | — | 最新在前 | 由 _revisions 的 limit 控制 |
/xml/changes_<site>.xml | — | 最新在前 | 30 |
/admin.php?mode=system_log | p | level、level_mod、order | 100 |
/admin.php?mode=user_users | p | user、order | 按后台设置 |
通用约定:页码从 1 开始;页码越界时回落到第 1 页;过滤条件变化后页码应重置。
十四、错误码与排障实录
14.1 状态码
| 状态 | 场景 | 响应特征 |
|---|---|---|
| 200 | 正常读取、搜索、后台页面 | HTML;导出/订阅为 XML |
| 200 + Error item | 匿名 _export.xml | <title>Error</title>,正文为权限提示 |
| 302 | 登录成功、写入成功、未授权进后台 | Location 指向目标页或 /HomePage |
| 403 | 私有页面 _source;diff 修订 ID 不匹配 | 3,079 字节 HTML,You aren't allowed to read this page. |
| 404 | 页面不存在;未生成的订阅文件 | 3,068 字节 HTML,This page doesn't exist.;XML 路径为 324 字节 404 页 |
| 409 | 编辑基线不一致 | OVERWRITE ALERT |
14.2 排障实录
问题 1:写操作返回 The submitted form was invalid. Try submitting again.
原因:复用了已消费的 _nonce,或 nonce 与表单动作不匹配。
处理:每次写请求前重新 GET 目标表单,解析并立即使用新的 _nonce。
问题 2:二次编辑 409 OVERWRITE ALERT
原因:previous 直接照抄页面 hidden 值,带着   与 : 实体;服务端按字面比较,判定页面已被他人修改。
处理:提交前把实体解码为空格与冒号;或从编辑页 hidden 值原样回传但由客户端做 HTML 解码。
问题 3:上传不成功,页面回到普通视图
原因:漏传 upload=1 或 upload_to。缺少 upload=1 时服务端不会进入上传分支。
处理:按第 11 节的字段表补齐,upload_to 显式取 local 或 global。
问题 4:_export.xml 返回 200 但只有 Error item
原因:export_handler=2 要求登录;匿名请求不会得到 403,而是 200 + Error。
处理:带管理员/读者会话请求,或在后台把 export_handler 调成允许匿名导出。
问题 5:/xml/changes_*.xml 404
原因:xml/ 目录对 Web 进程不可写,页面保存时无法生成静态订阅文件。
处理:修正 xml/ 属主/权限,保存任意页面触发重建;确认文件名中的站点名已归一化。
问题 6:/admin.php 直接 302 到 /HomePage
原因:当前会话不是 Wiki 管理员,第一道门未通过,还没到恢复口令页。
处理:先完成前台管理员登录,再访问后台并提交 ap_password。
问题 7:_diff 返回 403
原因:a/b 不是该页真实修订 ID,或当前用户无该页读权限。
处理:先从 _revisions 或 _revisions.xml 取得修订 ID,再拼接 _diff。
问题 8:curl 登录返回空响应
原因:未加 -L,只看到 302 的空响应体。
处理:加 -L 跟随跳转,同时用 -c 保存 Cookie 罐。
问题 9:搜索无结果
原因:关键词少于 3 个字符时服务端不执行检索;或内容不在正文/标题中。
处理:使用 ≥3 字符的关键词;标题搜索加 topic=1;必要时放宽 scope=all。
十五、参考链接
- WackoWiki 官方文档(英文):https://wackowiki.org/doc/Doc/English
- WackoWiki 配置说明:https://wackowiki.org/doc/Doc/English/Configuration
- WackoWiki GitHub 仓库:https://github.com/WackoWiki/wackowiki
- WackoWiki 6.3.0 Release:https://github.com/WackoWiki/wackowiki/releases/tag/6.3.0
- Apache HTTP Server 2.4 文档:https://httpd.apache.org/docs/2.4/
- PHP 手册:https://www.php.net/manual/zh/
- MariaDB 文档:https://mariadb.com/kb/en/documentation/