ScriptHost

Check-in [7bd330879c]
Login

Check-in [7bd330879c]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Executable flag for `PhysFS::force_file`
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 7bd330879c5606bf102476ac1e15845d2314a815d2616da08a84f49d8b5a2036
User & Date: murphy 2024-10-22 15:33:17.500
Context
2024-10-26
20:49
Updated NuGet package references check-in: c68e361c3a user: murphy tags: trunk
2024-10-22
15:33
Executable flag for `PhysFS::force_file` check-in: 7bd330879c user: murphy tags: trunk
2024-10-21
03:09
Added missing includes (savepoint) check-in: 78acd2168a user: murphy tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to webview-host/README.md.
35
36
37
38
39
40
41
42
43
44
45
46
- `con:` means an interactive console allows the user to see incoming and generate outgoing messages.
- Any other value is taken as the path to an executable. A new process is spawned for any web view that sends its first message. An identifier of the web view is passed as an argument to the executable. Incoming messages are written to the process' standard input, outgoing messages are read from standard output, both in [netstring](https://cr.yp.to/proto/netstrings.txt) format.

## Using the Library

To use the *WebView Host* functionality in your own programs, you need to create a `WebEnvironment` object. This can be done either through the C++ constructor `Murphy::WebView::WebEnvironment::WebEnvironment(int &argc, char **&argv)` or through the plain C entry point `web_environment_new(int *argc, char ***argv)`. The `WebEnvironment` should be owned by one thread that runs its event loop using `Murphy::WebView::WebEnvironment::run()` or `web_environment_run(WebEnvironment *env)`.

Using `Murphy::WebView::WebEnvironment::create_view(const WebWindowPlacement &place, std::shared_ptr<WebView> parent = nullptr, int cmdShow = -1)` or `web_environment_create_view(WebEnvironment *env, const WebWindowPlacement *place, uintptr_t parent_id, int cmd_show)` you can create new web views in a given environment. A new `WebView` is initially empty. Content can be loaded from URLs or data buffers, for example with `Murphy::WebView::WebView::load_uri(std::string uri)` or `web_view_load_uri(WebEnvironment *env, uintptr_t view_id, const char *uri)`.

The C++ API uses exceptions to represent fatal error conditions. The C API returns boolean `false`, `nullptr` or similar in case of errors and sets a thread-local error state that can be queried using `web_environment_last_error(const char **category, int *code)`.

For details, refer to the `webview.h` header or the API documentation generated with [Doxygen](https://www.doxygen.nl/index.html).







|




35
36
37
38
39
40
41
42
43
44
45
46
- `con:` means an interactive console allows the user to see incoming and generate outgoing messages.
- Any other value is taken as the path to an executable. A new process is spawned for any web view that sends its first message. An identifier of the web view is passed as an argument to the executable. Incoming messages are written to the process' standard input, outgoing messages are read from standard output, both in [netstring](https://cr.yp.to/proto/netstrings.txt) format.

## Using the Library

To use the *WebView Host* functionality in your own programs, you need to create a `WebEnvironment` object. This can be done either through the C++ constructor `Murphy::WebView::WebEnvironment::WebEnvironment(int &argc, char **&argv)` or through the plain C entry point `web_environment_new(int *argc, char ***argv)`. The `WebEnvironment` should be owned by one thread that runs its event loop using `Murphy::WebView::WebEnvironment::run()` or `web_environment_run(WebEnvironment *env)`.

Using `Murphy::WebView::WebEnvironment::create_view(const WebWindowPlacement &place, std::shared_ptr<WebView> parent = nullptr)` or `web_environment_create_view(WebEnvironment *env, const WebWindowPlacement *place, uintptr_t parent_id)` you can create new web views in a given environment. A new `WebView` is initially empty. Content can be loaded from URLs or data buffers, for example with `Murphy::WebView::WebView::load_uri(std::string uri)` or `web_view_load_uri(WebEnvironment *env, uintptr_t view_id, const char *uri)`.

The C++ API uses exceptions to represent fatal error conditions. The C API returns boolean `false`, `nullptr` or similar in case of errors and sets a thread-local error state that can be queried using `web_environment_last_error(const char **category, int *code)`.

For details, refer to the `webview.h` header or the API documentation generated with [Doxygen](https://www.doxygen.nl/index.html).
Changes to webview-host/include/murphy/fsutil.h.
55
56
57
58
59
60
61
62
63
64
65
66
67
/// Write an entire block of memory through PhysicsFS.
WEBVIEW_API std::error_code write_all(PHYSFS_File *file, const void *data, std::size_t size);
static inline std::error_code write_all(PHYSFS_File *file, const char *data) { return write_all(file, data, std::strlen(data)); }
static inline std::error_code write_all(PHYSFS_File *file, const std::string &data) { return write_all(file, data.data(), data.size()); }

/// Ensure that a copy of a file is stored in the regular filesystem.
/// Replace the PhysicsFS path on input by a regular file system path on output.
WEBVIEW_API std::error_code force_file(std::string &path);

}

}
}







|





55
56
57
58
59
60
61
62
63
64
65
66
67
/// Write an entire block of memory through PhysicsFS.
WEBVIEW_API std::error_code write_all(PHYSFS_File *file, const void *data, std::size_t size);
static inline std::error_code write_all(PHYSFS_File *file, const char *data) { return write_all(file, data, std::strlen(data)); }
static inline std::error_code write_all(PHYSFS_File *file, const std::string &data) { return write_all(file, data.data(), data.size()); }

/// Ensure that a copy of a file is stored in the regular filesystem.
/// Replace the PhysicsFS path on input by a regular file system path on output.
WEBVIEW_API std::error_code force_file(std::string &path, bool executable);

}

}
}
Changes to webview-host/src/fsutil.cxx.
10
11
12
13
14
15
16




17
18
19
20
21
22
23
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
#include <murphy/fsutil.h>





using namespace std;

namespace Murphy {
namespace WebView {

const error_category &physfs_category() noexcept







>
>
>
>







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
#include <murphy/fsutil.h>

#if !defined(_WIN32)
#	include <sys/stat.h>
#endif

using namespace std;

namespace Murphy {
namespace WebView {

const error_category &physfs_category() noexcept
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294












295
296
297
298
299
300
301
			if (result != PHYSFS_ERR_OK) return error_code(result, physfs_category());
		}
	}

	return {};
}

error_code force_file(string &path)
{
	const char *const separator = PHYSFS_getDirSeparator();
	for (unsigned fuel = 2; fuel > 0; --fuel) {
		if (const char *const real_dir = PHYSFS_getRealDir(path.c_str())) {
			size_t real_len = strlen(real_dir);
			if (real_len > 0 && strchr(separator, real_dir[--real_len])) {
				path = string(real_dir, real_len) + separator + clean_path(path, separator);












				return error_code();
			}
		}

		if (fuel > 1) {
			string data;
			auto error = read_file(path.c_str(), data);







|







>
>
>
>
>
>
>
>
>
>
>
>







284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
			if (result != PHYSFS_ERR_OK) return error_code(result, physfs_category());
		}
	}

	return {};
}

error_code force_file(string &path, bool const executable)
{
	const char *const separator = PHYSFS_getDirSeparator();
	for (unsigned fuel = 2; fuel > 0; --fuel) {
		if (const char *const real_dir = PHYSFS_getRealDir(path.c_str())) {
			size_t real_len = strlen(real_dir);
			if (real_len > 0 && strchr(separator, real_dir[--real_len])) {
				path = string(real_dir, real_len) + separator + clean_path(path, separator);
#				if !defined(_WIN32)
				if (executable && fuel < 2) {
					struct stat sb;
					if (WEBVIEW_LIKELY(stat(path.c_str(), &sb) == 0)) {
						auto &mode = sb.st_mode;
						if (mode & S_IRUSR) mode |= S_IXUSR;
						if (mode & S_IRGRP) mode |= S_IXGRP;
						if (mode & S_IROTH) mode |= S_IXOTH;
						chmod(path.c_str(), mode);
					}
				}
#				endif
				return error_code();
			}
		}

		if (fuel > 1) {
			string data;
			auto error = read_file(path.c_str(), data);
Changes to webview-host/src/process.cxx.
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
		log_f(DEBG, "Message Processor: work_dir = [!pre]\"%.*s\"[/pre]", int(work_dir.size()), work_dir.data());
	}
	else {
		log_f(DEBG, "Message Processor: work_dir = <current>");
	}

	exe_file = exe;
	auto error = PhysFS::force_file(exe_file);
	if (WEBVIEW_LIKELY(!error)) {
		log_f(DEBG, "Message Processor: exe_file = [!pre]\"%.*s\"[/pre]", int(exe_file.size()), exe_file.data());
	}
	else {
		throw system_error(error);
	}
}







|







223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
		log_f(DEBG, "Message Processor: work_dir = [!pre]\"%.*s\"[/pre]", int(work_dir.size()), work_dir.data());
	}
	else {
		log_f(DEBG, "Message Processor: work_dir = <current>");
	}

	exe_file = exe;
	auto error = PhysFS::force_file(exe_file, /*executable*/ true);
	if (WEBVIEW_LIKELY(!error)) {
		log_f(DEBG, "Message Processor: exe_file = [!pre]\"%.*s\"[/pre]", int(exe_file.size()), exe_file.data());
	}
	else {
		throw system_error(error);
	}
}
Changes to webview-host/src/webview_win32.cxx.
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
		wcex.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1);
		wcex.lpszMenuName = NULL;

		auto error = make_error_code(errc::no_such_file_or_directory);
		if (!icon_file_.empty()) {
			wstring icon_wide;
#			if defined(WEBVIEW_PHYSFS)
			error = PhysFS::force_file(icon_file_);
			if (WEBVIEW_UNLIKELY(error)) goto skip;
#			endif
			icon_wide = widen_utf8(icon_file_);
			wcex.hIcon = static_cast<HICON>(LoadImageW(
				hInstance_, icon_wide.c_str(),
				IMAGE_ICON, cx_icon, cy_icon,
				LR_DEFAULTCOLOR | LR_LOADFROMFILE







|







749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
		wcex.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1);
		wcex.lpszMenuName = NULL;

		auto error = make_error_code(errc::no_such_file_or_directory);
		if (!icon_file_.empty()) {
			wstring icon_wide;
#			if defined(WEBVIEW_PHYSFS)
			error = PhysFS::force_file(icon_file_, /*executable*/ false);
			if (WEBVIEW_UNLIKELY(error)) goto skip;
#			endif
			icon_wide = widen_utf8(icon_file_);
			wcex.hIcon = static_cast<HICON>(LoadImageW(
				hInstance_, icon_wide.c_str(),
				IMAGE_ICON, cx_icon, cy_icon,
				LR_DEFAULTCOLOR | LR_LOADFROMFILE