@@ -51,6 +51,8 @@ endif()
5151
5252# ---------------------------------------------------------------------------
5353# Helper: download a single file (skip if already cached)
54+ # Uses curl for authenticated requests to handle GitHub's 302 redirects
55+ # properly (CMake file(DOWNLOAD) doesn't forward auth headers on redirect).
5456# ---------------------------------------------------------------------------
5557function (_driver_download url output_path )
5658 if (EXISTS "${output_path} " )
@@ -63,41 +65,137 @@ function(_driver_download url output_path)
6365 message (STATUS " Downloading: ${url} " )
6466
6567 if (GITHUB_TOKEN)
66- file (DOWNLOAD "${url} " "${output_path} "
67- HTTPHEADER "Authorization: token ${GITHUB_TOKEN} "
68- STATUS _status
69- TLS_VERIFY ON )
68+ # Use curl to handle GitHub's 302 redirects for private repo assets.
69+ # CMake's file(DOWNLOAD) won't send auth headers after redirect to S3.
70+ find_program (_CURL curl REQUIRED )
71+ execute_process (
72+ COMMAND "${_CURL} " -fsSL
73+ -H "Authorization: token ${GITHUB_TOKEN} "
74+ -H "Accept: application/octet-stream"
75+ -o "${output_path} "
76+ "${url} "
77+ RESULT_VARIABLE _code
78+ ERROR_VARIABLE _err )
79+ if (NOT _code EQUAL 0)
80+ message (WARNING " curl download failed (${_code} ): ${_err} " )
81+ file (REMOVE "${output_path} " )
82+ return ()
83+ endif ()
7084 else ()
7185 file (DOWNLOAD "${url} " "${output_path} "
7286 STATUS _status
7387 TLS_VERIFY ON )
88+ list (GET _status 0 _code)
89+ if (NOT _code EQUAL 0)
90+ list (GET _status 1 _msg)
91+ message (WARNING " Download failed (${_code} ): ${_msg} " )
92+ file (REMOVE "${output_path} " )
93+ return ()
94+ endif ()
7495 endif ()
7596
76- list (GET _status 0 _code)
77- if (NOT _code EQUAL 0)
78- list (GET _status 1 _msg)
79- message (WARNING " Download failed (${_code} ): ${_msg} " )
80- file (REMOVE "${output_path} " )
81- return ()
82- endif ()
83-
84- file (SIZE "${output_path} " _size )
85- if (_size EQUAL 0)
86- message (WARNING " Downloaded file is empty: ${output_path} " )
87- file (REMOVE "${output_path} " )
97+ if (EXISTS "${output_path} " )
98+ file (SIZE "${output_path} " _size )
99+ if (_size EQUAL 0)
100+ message (WARNING " Downloaded file is empty: ${output_path} " )
101+ file (REMOVE "${output_path} " )
102+ endif ()
88103 endif ()
89104endfunction ()
90105
91106# ---------------------------------------------------------------------------
92- # ZakoVirtualMouse (individual release assets)
107+ # ZakoVirtualMouse (private repo — use GitHub API for authenticated downloads)
108+ # For private repos, browser_download_url returns 302→S3 which rejects
109+ # forwarded auth headers. We must use the GitHub REST API asset endpoint
110+ # with Accept: application/octet-stream.
93111# ---------------------------------------------------------------------------
94112function (_fetch_vmouse )
95113 message (STATUS "Fetching ZakoVirtualMouse ${VMOUSE_DRIVER_VERSION} ..." )
96- set (_base "https://github.com/${_VMOUSE_REPO} /releases/download/${VMOUSE_DRIVER_VERSION} " )
97114
98- foreach (_f ZakoVirtualMouse.dll ZakoVirtualMouse.inf ZakoVirtualMouse.cat)
99- _driver_download ("${_base} /${_f} " "${VMOUSE_DRIVER_DIR} /${_f} " )
115+ set (_files ZakoVirtualMouse.dll ZakoVirtualMouse.inf ZakoVirtualMouse.cat)
116+
117+ # Check if all files already cached
118+ set (_all_cached TRUE )
119+ foreach (_f ${_files} )
120+ if (NOT EXISTS "${VMOUSE_DRIVER_DIR} /${_f} " )
121+ set (_all_cached FALSE )
122+ break ()
123+ endif ()
100124 endforeach ()
125+ if (_all_cached)
126+ message (STATUS " All vmouse files already cached" )
127+ return ()
128+ endif ()
129+
130+ if (NOT GITHUB_TOKEN)
131+ message (WARNING " GITHUB_TOKEN required for private repo ${_VMOUSE_REPO} " )
132+ return ()
133+ endif ()
134+
135+ find_program (_CURL curl REQUIRED )
136+ file (MAKE_DIRECTORY "${VMOUSE_DRIVER_DIR} " )
137+
138+ # Query release assets via GitHub API
139+ set (_api_url "https://api.github.com/repos/${_VMOUSE_REPO} /releases/tags/${VMOUSE_DRIVER_VERSION} " )
140+ set (_json "${DRIVER_DEPS_CACHE} /_vmouse_release.json" )
141+ execute_process (
142+ COMMAND "${_CURL} " -fsSL
143+ -H "Authorization: token ${GITHUB_TOKEN} "
144+ -H "Accept: application/vnd.github+json"
145+ -o "${_json} "
146+ "${_api_url} "
147+ RESULT_VARIABLE _rc
148+ ERROR_VARIABLE _err )
149+ if (NOT _rc EQUAL 0)
150+ message (WARNING " Failed to query vmouse release API (${_rc} ): ${_err} " )
151+ return ()
152+ endif ()
153+
154+ # For each required file, find its asset id and download via API
155+ foreach (_f ${_files} )
156+ if (EXISTS "${VMOUSE_DRIVER_DIR} /${_f} " )
157+ continue ()
158+ endif ()
159+
160+ # Extract asset download URL from JSON using regex
161+ # The API JSON contains entries like:
162+ # "name": "ZakoVirtualMouse.dll", ... "url": "https://api.github.com/repos/.../assets/12345"
163+ file (READ "${_json} " _json_content )
164+
165+ # Find block for this asset: locate "name": "<filename>" then extract nearest "url"
166+ # We use string(REGEX) to find the asset API url
167+ string (REGEX MATCH "\" url\" [^}]*\" name\" :[ ]*\" ${_f} \" " _match_after "${_json_content} " )
168+ string (REGEX MATCH "\" name\" :[ ]*\" ${_f} \" [^}]*\" url\" " _match_before "${_json_content} " )
169+
170+ set (_asset_api_url "" )
171+ # Try to extract the url from the assets array
172+ # GitHub API returns assets like: { "url": "https://api.github.com/repos/.../assets/ID", ... "name": "file" }
173+ string (REGEX MATCH "\" url\" :[ ]*\" (https://api\\ .github\\ .com/repos/[^\" ]+/assets/[0-9]+)\" [^}]*\" name\" :[ ]*\" ${_f} \" " _m "${_json_content} " )
174+ if (_m)
175+ set (_asset_api_url "${CMAKE_MATCH_1} " )
176+ endif ()
177+
178+ if (NOT _asset_api_url)
179+ message (WARNING " Could not find asset URL for ${_f} in release JSON" )
180+ continue ()
181+ endif ()
182+
183+ message (STATUS " Downloading ${_f} via API: ${_asset_api_url} " )
184+ execute_process (
185+ COMMAND "${_CURL} " -fsSL
186+ -H "Authorization: token ${GITHUB_TOKEN} "
187+ -H "Accept: application/octet-stream"
188+ -o "${VMOUSE_DRIVER_DIR} /${_f} "
189+ "${_asset_api_url} "
190+ RESULT_VARIABLE _rc
191+ ERROR_VARIABLE _err )
192+ if (NOT _rc EQUAL 0)
193+ message (WARNING " Download failed for ${_f} (${_rc} ): ${_err} " )
194+ file (REMOVE "${VMOUSE_DRIVER_DIR} /${_f} " )
195+ endif ()
196+ endforeach ()
197+
198+ file (REMOVE "${_json} " )
101199endfunction ()
102200
103201# ---------------------------------------------------------------------------
0 commit comments