@follenfang/fupload 0.0.25 → 0.0.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/fupload/SKILL.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: fupload
|
|
3
3
|
description: Explicit author-publishing workflow for World of Warcraft plugins, configuration shares, and WA/strings on NewBeeBox, NetEase DD, CurseForge, Heybox Workshop, and ModUs.Creator, including local Creator login reuse and plugin ZIP publishing. Use only when the user explicitly invokes `$fupload`, explicitly asks to use the Fupload Skill, or loads this Skill by path. Do not trigger from ordinary mentions of publishing, NewBeeBox, DD, CurseForge, Heybox, ModUs, plugins, configurations, or WA.
|
|
4
4
|
metadata:
|
|
5
|
-
version: "0.0.
|
|
5
|
+
version: "0.0.26"
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Fupload
|
package/fupload/references/dd.md
CHANGED
|
@@ -81,7 +81,7 @@ When rebuilding a plugin update/edit form, preserve field presence from the curr
|
|
|
81
81
|
|
|
82
82
|
Before `plugin update`, traverse `/addon/addon_versions` pages as an optional duplicate guard. If it returns version rows, reject any candidate version already present anywhere in that history before upload; if it is empty or unavailable, retain the current-version check and continue. After update, confirm the submitted version fields from the matching item in the author plugin list, whose `latest_version` is the official update projection. `detail_v2` is supplementary. An empty history never marks a successful private-plugin update as failed and never triggers replay.
|
|
83
83
|
|
|
84
|
-
Read `plugin categories`, choose `primary_category_id`, then choose only returned `second_category_ids`. Read `plugin game-versions --game-type <id>` and use its stable values. The package accepts `.zip` only. Authorization always uses `file_type=a19-ui-res`, `business_id=addon`, fixed `file_name=addon.zip`, and `mime_type=application/x-zip-compressed`. Plugin image authorization uses `a19-ui-media/img` with an explicit empty wire file name.
|
|
84
|
+
Read `plugin categories`, choose `primary_category_id`, then choose only returned `second_category_ids`. Read `plugin game-versions --game-type <id>` and use its stable values. The package accepts `.zip` only. Before login/upload, local plugin ZIP files are checked for backslash paths in both the central directory and local file headers; DD cannot recognize these paths reliably. Rebuild such ZIPs with forward-slash (`/`) entry names (Windows PowerShell 5 `Compress-Archive` may produce incompatible backslash names). Fupload rejects the package rather than rewriting it. External `detail_url` packages are not downloaded for this check. Authorization always uses `file_type=a19-ui-res`, `business_id=addon`, fixed `file_name=addon.zip`, and `mime_type=application/x-zip-compressed`. Plugin image authorization uses `a19-ui-media/img` with an explicit empty wire file name.
|
|
85
85
|
|
|
86
86
|
## Configuration share
|
|
87
87
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import os
|
|
6
|
+
import struct
|
|
6
7
|
import zipfile
|
|
7
8
|
from dataclasses import dataclass, field
|
|
8
9
|
from typing import Any, Dict, Iterable, Mapping, Optional, Sequence, Tuple
|
|
@@ -10,6 +11,33 @@ from typing import Any, Dict, Iterable, Mapping, Optional, Sequence, Tuple
|
|
|
10
11
|
from .errors import ValidationError
|
|
11
12
|
|
|
12
13
|
|
|
14
|
+
def _validate_dd_plugin_zip(path: str) -> None:
|
|
15
|
+
"""Inspect stored paths before Windows ZipInfo normalizes separators."""
|
|
16
|
+
try:
|
|
17
|
+
with open(path, "rb") as source, zipfile.ZipFile(source) as archive:
|
|
18
|
+
for info in archive.infolist():
|
|
19
|
+
if "\\" in info.orig_filename:
|
|
20
|
+
raise ValidationError(
|
|
21
|
+
"DD plugin ZIP contains backslash paths; rebuild the ZIP with forward-slash (/) entry names",
|
|
22
|
+
path="$.file",
|
|
23
|
+
)
|
|
24
|
+
source.seek(info.header_offset)
|
|
25
|
+
header = source.read(30)
|
|
26
|
+
if len(header) != 30 or header[:4] != b"PK\x03\x04":
|
|
27
|
+
raise zipfile.BadZipFile("invalid local file header")
|
|
28
|
+
name_length = struct.unpack_from("<H", header, 26)[0]
|
|
29
|
+
name = source.read(name_length)
|
|
30
|
+
if len(name) != name_length:
|
|
31
|
+
raise zipfile.BadZipFile("truncated local entry name")
|
|
32
|
+
if b"\\" in name:
|
|
33
|
+
raise ValidationError(
|
|
34
|
+
"DD plugin ZIP contains backslash paths in a local file header; rebuild the ZIP with forward-slash (/) entry names",
|
|
35
|
+
path="$.file",
|
|
36
|
+
)
|
|
37
|
+
except (OSError, zipfile.BadZipFile) as exc:
|
|
38
|
+
raise ValidationError("file must be a valid ZIP archive", path="$.file") from exc
|
|
39
|
+
|
|
40
|
+
|
|
13
41
|
JSON_TYPES = {
|
|
14
42
|
"string": (str,),
|
|
15
43
|
"integer": (int,),
|
|
@@ -308,6 +336,8 @@ class Schema:
|
|
|
308
336
|
):
|
|
309
337
|
scalar_array(name, (str,), "array must contain nonempty strings")
|
|
310
338
|
if self.name.startswith("fupload.v1.dd"):
|
|
339
|
+
if self.name.startswith("fupload.v1.dd.plugin.") and "file" in value:
|
|
340
|
+
_validate_dd_plugin_zip(value["file"])
|
|
311
341
|
object_array("associated_acts", {"sn", "act_type"}, ("sn", "act_type"))
|
|
312
342
|
for name in ("second_category_ids", "vip_levels"):
|
|
313
343
|
if name in value and any(isinstance(item, bool) or not isinstance(item, int) for item in value[name]):
|
|
@@ -191,6 +191,7 @@ def verify_dd_executable(executable: Path) -> Dict[str, str]:
|
|
|
191
191
|
[powershell, "-NoProfile", "-NonInteractive", "-Command", script],
|
|
192
192
|
capture_output=True, text=True, encoding="utf-8", errors="strict",
|
|
193
193
|
timeout=20, check=False, env=environment,
|
|
194
|
+
creationflags=getattr(subprocess, "CREATE_NO_WINDOW", 0),
|
|
194
195
|
)
|
|
195
196
|
if completed.returncode != 0:
|
|
196
197
|
raise FuploadError("DD Authenticode verification process failed", kind="trust_boundary")
|
package/npm/skill-manifest.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": "fupload.npm-skill-manifest.v1",
|
|
3
3
|
"package_name": "@follenfang/fupload",
|
|
4
|
-
"package_version": "0.0.
|
|
5
|
-
"skill_version": "0.0.
|
|
6
|
-
"tree_sha256": "
|
|
4
|
+
"package_version": "0.0.26",
|
|
5
|
+
"skill_version": "0.0.26",
|
|
6
|
+
"tree_sha256": "4af4e44df9949daa9432d47bc5d7913d6dd58442e8436981c22922a1e365b63f",
|
|
7
7
|
"files": [
|
|
8
8
|
{
|
|
9
9
|
"path": "agents/openai.yaml",
|
|
@@ -87,8 +87,8 @@
|
|
|
87
87
|
},
|
|
88
88
|
{
|
|
89
89
|
"path": "references/dd.md",
|
|
90
|
-
"bytes":
|
|
91
|
-
"sha256": "
|
|
90
|
+
"bytes": 21542,
|
|
91
|
+
"sha256": "2bff00091259535980e42fac12f9765f9e51f8beea43dee9bff377c67fa2bce3"
|
|
92
92
|
},
|
|
93
93
|
{
|
|
94
94
|
"path": "references/modus.md",
|
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
{
|
|
114
114
|
"path": "scripts/fupload_cli/__init__.py",
|
|
115
115
|
"bytes": 50,
|
|
116
|
-
"sha256": "
|
|
116
|
+
"sha256": "8affb4fcf748b4f6b76907e88051a6a4aa5110146ea5adbe56231509962b1de4"
|
|
117
117
|
},
|
|
118
118
|
{
|
|
119
119
|
"path": "scripts/fupload_cli/blackbox_web.py",
|
|
@@ -182,8 +182,8 @@
|
|
|
182
182
|
},
|
|
183
183
|
{
|
|
184
184
|
"path": "scripts/fupload_cli/schema.py",
|
|
185
|
-
"bytes":
|
|
186
|
-
"sha256": "
|
|
185
|
+
"bytes": 56696,
|
|
186
|
+
"sha256": "9d690fea8fe7b249c089a24a6c59d783f83d2ffd0215def770cd9849d09e52f8"
|
|
187
187
|
},
|
|
188
188
|
{
|
|
189
189
|
"path": "scripts/fupload_cli/state_machine.py",
|
|
@@ -197,8 +197,8 @@
|
|
|
197
197
|
},
|
|
198
198
|
{
|
|
199
199
|
"path": "scripts/fupload_cli/trust.py",
|
|
200
|
-
"bytes":
|
|
201
|
-
"sha256": "
|
|
200
|
+
"bytes": 9462,
|
|
201
|
+
"sha256": "79d31833a16d71ec132612a4a2fd2f015770df469e7db06933b3ea530022c97d"
|
|
202
202
|
},
|
|
203
203
|
{
|
|
204
204
|
"path": "scripts/fupload.py",
|
|
@@ -208,7 +208,7 @@
|
|
|
208
208
|
{
|
|
209
209
|
"path": "SKILL.md",
|
|
210
210
|
"bytes": 28729,
|
|
211
|
-
"sha256": "
|
|
211
|
+
"sha256": "863223ca2e78adb854511a18fea9c9bead7238d5014b229a0ea21a335409fc90"
|
|
212
212
|
}
|
|
213
213
|
]
|
|
214
214
|
}
|