implemented sceHttpUriParse

This commit is contained in:
georgemoralis 2025-03-01 19:55:50 +02:00
parent db868ea400
commit 01af261ed0
4 changed files with 319 additions and 10 deletions

View File

@ -298,6 +298,7 @@ set(KERNEL_LIB src/core/libraries/kernel/sync/mutex.cpp
set(NETWORK_LIBS src/core/libraries/network/http.cpp
src/core/libraries/network/http.h
src/core/libraries/network/http_error.h
src/core/libraries/network/http2.cpp
src/core/libraries/network/http2.h
src/core/libraries/network/net.cpp

View File

@ -5,6 +5,7 @@
#include "core/libraries/error_codes.h"
#include "core/libraries/libs.h"
#include "core/libraries/network/http.h"
#include "http_error.h"
namespace Libraries::Http {
@ -566,17 +567,244 @@ int PS4_SYSV_ABI sceHttpUriMerge() {
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttpUriParse() {
// Helper function to calculate the length of a URI component
static size_t calculateComponentLength(const char* start, const char* end) {
return (end > start) ? (size_t)(end - start) : 0;
}
// Helper function to parse the port from the URI
static int parsePort(const char* uri, int* offset) {
int port = 0;
int digits = 0;
while (uri[*offset] >= '0' && uri[*offset] <= '9' && digits < 5) {
port = port * 10 + (uri[*offset] - '0');
(*offset)++;
digits++;
}
if (digits == 0 || port > 65535) {
return 0; // Invalid port
}
return port;
}
int PS4_SYSV_ABI sceHttpUriParse(OrbisHttpUriElement* out, const char* srcUri, void* pool,
size_t* require, size_t prepare) {
LOG_INFO(Lib_Http, "srcUri = {}", std::string(srcUri));
if (!srcUri) {
LOG_ERROR(Lib_Http, "invalid values");
return ORBIS_HTTP_ERROR_INVALID_URL;
}
// Initialize the output structure if provided
if (out) {
memset(out, 0, sizeof(OrbisHttpUriElement));
}
// Calculate the required buffer size
size_t requiredBufferSize = 0;
char* currentPos = (char*)srcUri;
// Scheme (e.g., "http:")
char* schemeEnd = strchr(currentPos, ':');
if (!schemeEnd) {
LOG_ERROR(Lib_Http, "invalid url");
return ORBIS_HTTP_ERROR_INVALID_URL;
}
requiredBufferSize +=
calculateComponentLength(currentPos, schemeEnd) + 1; // Include null terminator
currentPos = schemeEnd + 1;
// Check if the URI is opaque or hierarchical
bool isOpaque = true; // Assume opaque by default
if (strncmp(currentPos, "//", 2) == 0) {
isOpaque = false; // Hierarchical if "//" is present
currentPos += 2; // Skip "//"
}
//in case it starts with file://///
if (strncmp(currentPos, "//", 2) == 0) {
currentPos += 2; // Skip "//"
}
// Host and port (e.g., "example.com:8080")
char* hostEnd = strchr(currentPos, '/');
if (!hostEnd) {
hostEnd = currentPos + strlen(currentPos);
}
// Check for credentials (username:password@host)
char* atSymbol = strchr(currentPos, '@');
if (atSymbol && atSymbol < hostEnd) {
requiredBufferSize +=
calculateComponentLength(currentPos, atSymbol) + 1; // Include null terminator
currentPos = atSymbol + 1;
}
// Check for port (host:port)
char* colon = strchr(currentPos, ':');
if (colon && colon < hostEnd) {
requiredBufferSize +=
calculateComponentLength(currentPos, colon) + 1; // Include null terminator
currentPos = colon + 1;
}
// Host
requiredBufferSize +=
calculateComponentLength(currentPos, hostEnd) + 1; // Include null terminator
currentPos = hostEnd;
// Path (e.g., "/path")
char* pathEnd = strchr(currentPos, '?');
if (!pathEnd) {
pathEnd = strchr(currentPos, '#');
if (!pathEnd) {
pathEnd = currentPos + strlen(currentPos);
}
}
requiredBufferSize +=
calculateComponentLength(currentPos, pathEnd) + 1; // Include null terminator
currentPos = pathEnd;
// Query (e.g., "?query=value")
if (*currentPos == '?') {
currentPos++;
char* queryEnd = strchr(currentPos, '#');
if (!queryEnd) {
queryEnd = currentPos + strlen(currentPos);
}
requiredBufferSize +=
calculateComponentLength(currentPos, queryEnd) + 1; // Include null terminator
currentPos = queryEnd;
}
// Fragment (e.g., "#fragment")
if (*currentPos == '#') {
currentPos++;
requiredBufferSize +=
calculateComponentLength(currentPos, currentPos + strlen(currentPos)) +
1; // Include null terminator
}
// Return the required buffer size
if (require) {
*require = requiredBufferSize;
}
// If pool is NULL, we're done
if (!pool) {
return ORBIS_OK;
}
// Check if the provided buffer is large enough
if (prepare < requiredBufferSize) {
LOG_ERROR(Lib_Http, "out of memory");
return ORBIS_HTTP_ERROR_OUT_OF_MEMORY;
}
// Copy the URI components to the buffer
char* buffer = (char*)pool;
strncpy(buffer, srcUri, prepare);
buffer[prepare - 1] = '\0'; // Ensure null termination
// Parse and assign the components to the output structure if provided
if (out) {
// Scheme
schemeEnd = strchr(buffer, ':');
*schemeEnd = '\0';
out->scheme = buffer;
buffer = schemeEnd + 1;
// Opaque flag
out->opaque = isOpaque;
// Host and port
if (!isOpaque) {
buffer += 2; // Skip "//"
}
hostEnd = strchr(buffer, '/');
if (!hostEnd) {
hostEnd = buffer + strlen(buffer);
}
// Credentials (username:password@host)
atSymbol = strchr(buffer, '@');
if (atSymbol && atSymbol < hostEnd) {
*atSymbol = '\0';
colon = strchr(buffer, ':');
if (colon) {
*colon = '\0';
out->username = buffer;
out->password = colon + 1;
} else {
out->username = buffer;
}
buffer = atSymbol + 1;
}
// Port (host:port)
colon = strchr(buffer, ':');
if (colon && colon < hostEnd) {
*colon = '\0';
int offset = colon + 1 - buffer;
out->port = parsePort(buffer, &offset);
if (out->port == 0) {
LOG_ERROR(Lib_Http, "invalid url");
return ORBIS_HTTP_ERROR_INVALID_URL;
}
}
// Host
*hostEnd = '\0';
out->hostname = buffer;
buffer = hostEnd + 1;
// Path
pathEnd = strchr(buffer, '?');
if (!pathEnd) {
pathEnd = strchr(buffer, '#');
if (!pathEnd) {
pathEnd = buffer + strlen(buffer);
}
}
*pathEnd = '\0';
out->path = buffer;
buffer = pathEnd + 1;
// Query
if (*buffer == '?') {
buffer++;
char* queryEnd = strchr(buffer, '#');
if (!queryEnd) {
queryEnd = buffer + strlen(buffer);
}
*queryEnd = '\0';
out->query = buffer;
buffer = queryEnd + 1;
}
// Fragment
if (*buffer == '#') {
buffer++;
out->fragment = buffer;
}
// Initialize the reserved field to zero
memset(out->reserved, 0, sizeof(out->reserved)); // RE indicates some works here but haven't
// been added not sure if it neccesary
}
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttpUriSweepPath(char* dst, const char* src, size_t srcSize) {
LOG_ERROR(Lib_Http, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttpUriSweepPath() {
LOG_ERROR(Lib_Http, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttpUriUnescape() {
int PS4_SYSV_ABI sceHttpUriUnescape(char* out, size_t* require, size_t prepare, const char* in) {
LOG_ERROR(Lib_Http, "(STUBBED) called");
return ORBIS_OK;
}

View File

@ -11,6 +11,19 @@ class SymbolsResolver;
namespace Libraries::Http {
struct OrbisHttpUriElement {
bool opaque;
char* scheme;
char* username;
char* password;
char* hostname;
char* path;
char* query;
char* fragment;
u16 port;
u8 reserved[10];
};
int PS4_SYSV_ABI sceHttpAbortRequest();
int PS4_SYSV_ABI sceHttpAbortRequestForce();
int PS4_SYSV_ABI sceHttpAbortWaitRequest();
@ -122,9 +135,10 @@ int PS4_SYSV_ABI sceHttpUriBuild();
int PS4_SYSV_ABI sceHttpUriCopy();
int PS4_SYSV_ABI sceHttpUriEscape();
int PS4_SYSV_ABI sceHttpUriMerge();
int PS4_SYSV_ABI sceHttpUriParse();
int PS4_SYSV_ABI sceHttpUriSweepPath();
int PS4_SYSV_ABI sceHttpUriUnescape();
int PS4_SYSV_ABI sceHttpUriParse(OrbisHttpUriElement* out, const char* srcUri, void* pool,
size_t* require, size_t prepare);
int PS4_SYSV_ABI sceHttpUriSweepPath(char* dst, const char* src, size_t srcSize);
int PS4_SYSV_ABI sceHttpUriUnescape(char* out, size_t* require, size_t prepare, const char* in);
int PS4_SYSV_ABI sceHttpWaitRequest();
void RegisterlibSceHttp(Core::Loader::SymbolsResolver* sym);

View File

@ -0,0 +1,66 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/libraries/error_codes.h"
constexpr int ORBIS_HTTP_ERROR_BEFORE_INIT = 0x80431001;
constexpr int ORBIS_HTTP_ERROR_ALREADY_INITED = 0x80431020;
constexpr int ORBIS_HTTP_ERROR_BUSY = 0x80431021;
constexpr int ORBIS_HTTP_ERROR_OUT_OF_MEMORY = 0x80431022;
constexpr int ORBIS_HTTP_ERROR_NOT_FOUND = 0x80431025;
constexpr int ORBIS_HTTP_ERROR_INVALID_VERSION = 0x8043106a;
constexpr int ORBIS_HTTP_ERROR_INVALID_ID = 0x80431100;
constexpr int ORBIS_HTTP_ERROR_OUT_OF_SIZE = 0x80431104;
constexpr int ORBIS_HTTP_ERROR_INVALID_VALUE = 0x804311fe;
constexpr int ORBIS_HTTP_ERROR_INVALID_URL = 0x80433060;
constexpr int ORBIS_HTTP_ERROR_UNKNOWN_SCHEME = 0x80431061;
constexpr int ORBIS_HTTP_ERROR_NETWORK = 0x80431063;
constexpr int ORBIS_HTTP_ERROR_BAD_RESPONSE = 0x80431064;
constexpr int ORBIS_HTTP_ERROR_BEFORE_SEND = 0x80431065;
constexpr int ORBIS_HTTP_ERROR_AFTER_SEND = 0x80431066;
constexpr int ORBIS_HTTP_ERROR_TIMEOUT = 0x80431068;
constexpr int ORBIS_HTTP_ERROR_UNKNOWN_AUTH_TYPE = 0x80431069;
constexpr int ORBIS_HTTP_ERROR_UNKNOWN_METHOD = 0x8043106b;
constexpr int ORBIS_HTTP_ERROR_READ_BY_HEAD_METHOD = 0x8043106f;
constexpr int ORBIS_HTTP_ERROR_NOT_IN_COM = 0x80431070;
constexpr int ORBIS_HTTP_ERROR_NO_CONTENT_LENGTH = 0x80431071;
constexpr int ORBIS_HTTP_ERROR_CHUNK_ENC = 0x80431072;
constexpr int ORBIS_HTTP_ERROR_TOO_LARGE_RESPONSE_HEADER = 0x80431073;
constexpr int ORBIS_HTTP_ERROR_SSL = 0x80431075;
constexpr int ORBIS_HTTP_ERROR_INSUFFICIENT_STACKSIZE = 0x80431076;
constexpr int ORBIS_HTTP_ERROR_ABORTED = 0x80431080;
constexpr int ORBIS_HTTP_ERROR_UNKNOWN = 0x80431081;
constexpr int ORBIS_HTTP_ERROR_EAGAIN = 0x80431082;
constexpr int ORBIS_HTTP_ERROR_PROXY = 0x80431084;
constexpr int ORBIS_HTTP_ERROR_BROKEN = 0x80431085;
constexpr int ORBIS_HTTP_ERROR_PARSE_HTTP_NOT_FOUND = 0x80432025;
constexpr int ORBIS_HTTP_ERROR_PARSE_HTTP_INVALID_RESPONSE = 0x80432060;
constexpr int ORBIS_HTTP_ERROR_PARSE_HTTP_INVALID_VALUE = 0x804321fe;
constexpr int ORBIS_HTTP_ERROR_RESOLVER_EPACKET = 0x80436001;
constexpr int ORBIS_HTTP_ERROR_RESOLVER_ENODNS = 0x80436002;
constexpr int ORBIS_HTTP_ERROR_RESOLVER_ETIMEDOUT = 0x80436003;
constexpr int ORBIS_HTTP_ERROR_RESOLVER_ENOSUPPORT = 0x80436004;
constexpr int ORBIS_HTTP_ERROR_RESOLVER_EFORMAT = 0x80436005;
constexpr int ORBIS_HTTP_ERROR_RESOLVER_ESERVERFAILURE = 0x80436006;
constexpr int ORBIS_HTTP_ERROR_RESOLVER_ENOHOST = 0x80436007;
constexpr int ORBIS_HTTP_ERROR_RESOLVER_ENOTIMPLEMENTED = 0x80436008;
constexpr int ORBIS_HTTP_ERROR_RESOLVER_ESERVERREFUSED = 0x80436009;
constexpr int ORBIS_HTTP_ERROR_RESOLVER_ENORECORD = 0x8043600a;
constexpr int ORBIS_HTTPS_ERROR_CERT = 0x80435060;
constexpr int ORBIS_HTTPS_ERROR_HANDSHAKE = 0x80435061;
constexpr int ORBIS_HTTPS_ERROR_IO = 0x80435062;
constexpr int ORBIS_HTTPS_ERROR_INTERNAL = 0x80435063;
constexpr int ORBIS_HTTPS_ERROR_PROXY = 0x80435064;
constexpr int ORBIS_HTTPS_ERROR_SSL_INTERNAL = 0x01;
constexpr int ORBIS_HTTPS_ERROR_SSL_INVALID_CERT = 0x02;
constexpr int ORBIS_HTTPS_ERROR_SSL_CN_CHECK = 0x04;
constexpr int ORBIS_HTTPS_ERROR_SSL_NOT_AFTER_CHECK = 0x08;
constexpr int ORBIS_HTTPS_ERROR_SSL_NOT_BEFORE_CHECK = 0x10;
constexpr int ORBIS_HTTPS_ERROR_SSL_UNKNOWN_CA = 0x20;