This commit is contained in:
Nishi 2026-04-12 23:06:29 +09:00
commit d2a3bcb744
Signed by: nishi
GPG key ID: 27EF69B208EB9343
32 changed files with 3298 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
*.a
*.o

24
LICENSE Normal file
View file

@ -0,0 +1,24 @@
Copyright (c) 2026, Pyrite development team
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

24
Makefile Normal file
View file

@ -0,0 +1,24 @@
# This is jst a template... PPR can be built manually pretty easily
CC = gcc
AR = ar
.PHONY: all install clean
.SUFFIXES: .c .o
OBJS = src/core.o
OBJS += src/base/poll.o src/base/file.o src/base/socket.o src/base/arpa.o src/base/string.o src/base/dlfcn.o src/base/unistd.o src/base/stat.o src/base/dirent.o src/base/time.o
OBJS += src/base/mutex.o src/base/thread.o src/base/process.o
OBJS += src/hash/md5.o src/hash/sha256.o src/hash/blake2s.o
OBJS += src/misc/url.o src/misc/wildcard.o
all: libppr.a
.c.o:
$(CC) -c -I include -o $@ $<
libppr.a: $(OBJS)
$(AR) rcs $@ $(OBJS)
clean:
rm -f *.a src/*.o src/*/*.o

15
include/ppr.h Normal file
View file

@ -0,0 +1,15 @@
#ifndef __PPR_H__
#define __PPR_H__
#include <ppr_base.h>
/* hash */
#include <ppr_sha256.h>
#include <ppr_md5.h>
#include <ppr_blake2s.h>
/* misc */
#include <ppr_url.h>
#include <ppr_wildcard.h>
#endif

230
include/ppr_base.h Normal file
View file

@ -0,0 +1,230 @@
#ifndef __PPR_BASE_H__
#define __PPR_BASE_H__
#include <ppr_machdep.h>
/* poll.c definitions */
#define PPR_POLLIN (1 << 0)
#define PPR_POLLPRI (1 << 1)
#define PPR_POLLOUT (1 << 2)
struct ppr_pollfd {
int fd;
short events;
short revents;
void* user;
};
/* file.c definitions */
typedef void PPR_FILE;
/* socket.c definitions */
enum ppr_socket_protocol {
PPR_PF_UNSPEC = 0,
PPR_PF_INET,
PPR_PF_INET6,
PPR_PF_UNIX
};
enum ppr_socket_address {
PPR_AF_UNSPEC = 0,
PPR_AF_INET,
PPR_AF_INET6,
PPR_AF_UNIX
};
enum ppr_socket_type {
PPR_SOCK_STREAM = 0,
PPR_SOCK_DGRAM
};
enum ppr_socket_ip_protocol {
PPR_IPPROTO_TCP = 1,
PPR_IPPROTO_UDP
};
struct ppr_sockaddr {
unsigned short sa_family;
char sa_data[14];
};
union ppr_in_addr_union {
ppr_uint8_t addr8[4];
ppr_uint16_t addr16[2];
ppr_uint32_t addr32[1];
};
struct ppr_in_addr {
union ppr_in_addr_union u;
};
struct ppr_sockaddr_in {
unsigned short sin_family;
ppr_uint16_t sin_port;
struct ppr_in_addr sin_addr;
};
union ppr_in6_addr_union {
ppr_uint8_t addr8[16];
ppr_uint16_t addr16[8];
ppr_uint32_t addr32[4];
};
struct ppr_in6_addr {
union ppr_in6_addr_union u;
};
struct ppr_sockaddr_in6 {
unsigned short sin6_family;
ppr_uint16_t sin6_port;
struct ppr_in6_addr sin6_addr;
};
struct ppr_sockaddr_storage {
unsigned short ss_family;
char ss_pad[128];
};
struct ppr_sockaddr_un {
unsigned short sun_family;
char sun_path[104];
};
/* stat.c definitions */
#define PPR_S_IFREG (1 << 0)
#define PPR_S_IFDIR (1 << 1)
#define PPR_S_ISREG(x) ((x) & PPR_S_IFREG)
#define PPR_S_ISDIR(x) ((x) & PPR_S_IFDIR)
struct ppr_stat {
ppr_size_t st_size;
ppr_time_t st_modtime;
int st_mode;
};
/* dirent.c definitions */
typedef void PPR_DIR;
struct ppr_dirent {
char d_name[512];
char d_fullname[1024];
struct ppr_stat d_stat;
};
/* time.c definitions */
struct ppr_tm {
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
};
/* thread.c definitions */
#if defined(PPR_IS_NETWARE)
struct ppr_semaphore_usage {
long sem;
ppr_bool used;
};
#endif
/* core.c */
void ppr_init(void);
void ppr_uninit(void);
/* poll.c */
int ppr_poll(struct ppr_pollfd* fds, int nfds, int timeout);
/* file.c */
PPR_FILE* ppr_fopen(const char* path, const char* mode);
int ppr_fread(void* ptr, int size, int nmemb, PPR_FILE* stream);
int ppr_fwrite(const void* ptr, int size, int nmemb, PPR_FILE* stream);
void ppr_fclose(PPR_FILE* stream);
/* socket.c */
extern struct ppr_in_addr ppr_inaddr_any;
extern struct ppr_in6_addr ppr_in6addr_any;
void ppr_socket_init(void);
int ppr_socket(int domain, int type, int protocol);
int ppr_recv(int s, void* buf, int len, int flags);
int ppr_send(int s, const void* msg, int len, int flags);
int ppr_bind(int s, const struct ppr_sockaddr* name, int namelen);
int ppr_connect(int s, const struct ppr_sockaddr* name, int namelen);
int ppr_listen(int s, int backlog);
int ppr_accept(int s, struct ppr_sockaddr* addr, int* addrlen);
void ppr_socket_close(int d);
void ppr_socket_uninit(void);
ppr_bool ppr_socket_has_ipv6(void);
/* arpa.c */
ppr_uint16_t ppr_htons(ppr_uint16_t host16);
const char* ppr_inet_ntop(struct ppr_sockaddr* src, char* dst);
struct ppr_sockaddr* ppr_inet_addr(const char* addr, int* len);
/* string.c */
char* ppr_strdup(const char* str);
char* ppr_strvacat(const char* a, ...);
void ppr_strappend(char** dst, const char* src);
char* ppr_strsafehtml(const char* s);
/* dlfcn.c */
void* ppr_dlopen(const char* path);
void* ppr_dlsym(void* handle, const char* symbol);
int ppr_dlclose(void* handle);
/* unistd.c */
int ppr_gethostname(char* name, int namelen);
void ppr_msleep(int ms);
/* stat.c */
int ppr_stat(const char* path, struct ppr_stat* s);
/* thread.c */
#if defined(PPR_IS_NETWARE)
extern struct ppr_semaphore_usage ppr_semaphores[];
long ppr_thread_open_semaphore(long initial);
void ppr_thread_close_semaphore(long sem);
#endif
void* ppr_thread_create(void (*entry)(void* param), void* param);
void ppr_thread_join(void* handle);
void ppr_thread_destroy(void* handle);
void ppr_thread_init(void);
void ppr_thread_uninit(void);
/* mutex.c */
void* ppr_mutex_create(void);
void ppr_mutex_lock(void* handle);
void ppr_mutex_unlock(void* handle);
void ppr_mutex_destroy(void* handle);
/* process.c */
void* ppr_process_create(const char* exec, char** env);
void ppr_process_close(void* handle);
int ppr_process_write(void* handle, const void* data, int len);
int ppr_process_read(void* handle, void* data, int len);
void ppr_process_destroy(void* handle);
/* dirent.c */
PPR_DIR* ppr_opendir(const char* path);
struct ppr_dirent* ppr_readdir(PPR_DIR* handle);
void ppr_closedir(PPR_DIR* handle);
int ppr_scandir(const char* dirname, struct ppr_dirent*** namelist, int (*selectfn)(const struct ppr_dirent* d), int (*compar)(const struct ppr_dirent** d1, const struct ppr_dirent** d2));
int ppr_alphasort(const struct ppr_dirent** d1, const struct ppr_dirent** d2);
/* time.c */
extern void* ppr_gmtime_mutex;
extern void* ppr_localtime_mutex;
ppr_time_t ppr_time(void);
void ppr_gmtime(struct ppr_tm* tm, ppr_time_t t);
void ppr_localtime(struct ppr_tm* tm, ppr_time_t t);
#endif

78
include/ppr_blake2s.h Normal file
View file

@ -0,0 +1,78 @@
/*
BLAKE2 reference source code package - reference C implementations
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#ifndef PPR_BLAKE2S_H
#define PPR_BLAKE2S_H
#include <ppr_machdep.h>
enum ppr_blake2s_constant {
BLAKE2S_BLOCKBYTES = 64,
BLAKE2S_OUTBYTES = 32,
BLAKE2S_KEYBYTES = 32,
BLAKE2S_SALTBYTES = 8,
BLAKE2S_PERSONALBYTES = 8
};
typedef struct ppr_blake2s_state__ {
ppr_uint32_t h[8];
ppr_uint32_t t[2];
ppr_uint32_t f[2];
ppr_uint8_t buf[BLAKE2S_BLOCKBYTES];
ppr_size_t buflen;
ppr_size_t outlen;
ppr_uint8_t last_node;
} ppr_blake2s_state;
#ifdef PPR_HAS_PACK
#pragma pack(1)
#endif
struct ppr_blake2s_param__ {
ppr_uint8_t digest_length; /* 1 */
ppr_uint8_t key_length; /* 2 */
ppr_uint8_t fanout; /* 3 */
ppr_uint8_t depth; /* 4 */
ppr_uint32_t leaf_length; /* 8 */
ppr_uint32_t node_offset; /* 12 */
ppr_uint16_t xof_length; /* 14 */
ppr_uint8_t node_depth; /* 15 */
ppr_uint8_t inner_length; /* 16 */
/* ppr_uint8_t reserved[0]; */
ppr_uint8_t salt[BLAKE2S_SALTBYTES]; /* 24 */
ppr_uint8_t personal[BLAKE2S_PERSONALBYTES]; /* 32 */
};
#ifdef PPR_HAS_PACK
#pragma pack()
#endif
typedef struct ppr_blake2s_param__ ppr_blake2s_param;
#if 0
/* Padded structs result in a compile-time error */
enum {
BLAKE2_DUMMY_1 = 1/(int)(sizeof(ppr_blake2s_param) == BLAKE2S_OUTBYTES)
};
#endif
/* Streaming API */
int ppr_blake2s_init(ppr_blake2s_state* S, ppr_size_t outlen);
int ppr_blake2s_init_key(ppr_blake2s_state* S, ppr_size_t outlen, const void* key, ppr_size_t keylen);
int ppr_blake2s_init_param(ppr_blake2s_state* S, const ppr_blake2s_param* P);
int ppr_blake2s_update(ppr_blake2s_state* S, const void* in, ppr_size_t inlen);
int ppr_blake2s_final(ppr_blake2s_state* S, void* out, ppr_size_t outlen);
/* Simple API */
int ppr_blake2s(void* out, ppr_size_t outlen, const void* in, ppr_size_t inlen, const void* key, ppr_size_t keylen);
#endif

87
include/ppr_int.h Normal file
View file

@ -0,0 +1,87 @@
#ifndef __PPR_INT_H__
#define __PPR_INT_H__
/* generic section */
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <stdarg.h>
#include <time.h>
#if defined(PPR_IS_NETWARE)
#include <sys/stat.h>
#include <nwnamspc.h>
#include <nwadv.h>
#endif
#if defined(PPR_IS_UNIX)
#include <signal.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <dlfcn.h>
#endif
#if defined(PPR_IS_UNIX) || defined(PPR_IS_PSP) || defined(PPR_IS_PS2) || defined(PPR_IS_NETWARE)
#include <unistd.h>
#include <dirent.h>
#endif
/* thread section */
#if defined(PPR_IS_WIN32)
#if !defined(PPR_USE_CREATETHREAD)
#include <process.h>
#endif
#elif defined(PPR_IS_UNIX) || defined(PPR_IS_PSP) || defined(PPR_IS_PS2)
#include <pthread.h>
#define PPR_USE_PTHREAD
#elif defined(PPR_IS_NETWARE)
#include <nwthread.h>
#include <nwsemaph.h>
#endif
/* socket section */
#if defined(PPR_IS_WIN32)
#include <winsock2.h>
#include <ws2tcpip.h>
#include <ws2ipdef.h>
#ifndef IPPROTO_IPV6
#define IPPROTO_IPV6 41
#endif
#ifndef IPV6_V6ONLY
#define IPV6_V6ONLY 27
#endif
#else
#if defined(PPR_HAS_POLL)
#include <poll.h>
#else
#if !defined(PPR_IS_NETWARE)
#include <sys/select.h>
#endif
#endif
#include <sys/socket.h>
#include <sys/types.h>
#if defined(PPR_IS_NETWARE)
#include <sys/bsdskt.h>
#else
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#endif
#if defined(PPR_HAS_UNIX_SOCKET)
#include <sys/un.h>
#endif
#endif
/* windows.h wants to be the last one included */
#if defined(PPR_IS_WIN32)
#include <windows.h>
#endif
#endif

100
include/ppr_machdep.h Normal file
View file

@ -0,0 +1,100 @@
#ifndef __PPR_MACHDEP_H__
#define __PPR_MACHDEP_H__
#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__sun__)
#define PPR_IS_UNIX
#elif defined(_WIN32)
#define PPR_IS_WIN32
#elif defined(_PSP)
#define PPR_IS_PSP
#elif defined(_EE)
#define PPR_IS_PS2
#elif defined(__NETWARE__)
#define PPR_IS_NETWARE
#endif
/*** Platform differences */
#if defined(PPR_IS_WIN32) || defined(PPR_IS_NETWARE)
#define ppr_newline "\r\n"
#else
#define ppr_newline "\n"
#endif
#undef PPR_HAS_IPV6
#undef PPR_HAS_POLL
#undef PPR_HAS_FORK
#undef PPR_HAS_UNIX_SOCKET
#undef PPR_USE_SOCKLEN_T
/* Windows */
#if defined(PPR_IS_WIN32)
#define PPR_HAS_IPV6
#endif
/* PSP/PS2 */
#if defined(PPR_IS_PSP) || defined(PPR_IS_PS2)
#define PPR_USE_SOCKLEN_T
#endif
/* NetWare */
#if defined(PPR_IS_NETWARE)
/* Nothing */
#endif
/* BSD family */
#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__sun__)
#define PPR_HAS_IPV6
#define PPR_HAS_POLL
#define PPR_HAS_FORK
#define PPR_HAS_UNIX_SOCKET
#define PPR_USE_SOCKLEN_T
#endif
/*** Compiler differences ***/
#undef PPR_HAS_PACK
#if defined(__WATCOMC__) || defined(__GNUC__)
#define PPR_HAS_PACK
#endif
typedef unsigned char ppr_bool;
#define ppr_false 0
#define ppr_true 1
#if defined(_MSC_VER) || defined(__WATCOMC__)
typedef unsigned __int8 ppr_uint8_t;
typedef unsigned __int16 ppr_uint16_t;
typedef unsigned __int32 ppr_uint32_t;
typedef __int8 ppr_int8_t;
typedef __int16 ppr_int16_t;
typedef __int32 ppr_int32_t;
typedef __int64 ppr_size_t;
#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) || defined(__clang__))
typedef unsigned char ppr_uint8_t;
typedef unsigned short ppr_uint16_t;
typedef unsigned int ppr_uint32_t;
typedef signed char ppr_int8_t;
typedef short ppr_int16_t;
typedef int ppr_int32_t;
typedef long long ppr_size_t;
#else
typedef unsigned char ppr_uint8_t;
typedef unsigned short ppr_uint16_t;
typedef unsigned int ppr_uint32_t;
typedef signed char ppr_int8_t;
typedef short ppr_int16_t;
typedef int ppr_int32_t;
typedef long ppr_size_t;
#endif
typedef ppr_size_t ppr_time_t;
#endif

43
include/ppr_md5.h Normal file
View file

@ -0,0 +1,43 @@
/*
**********************************************************************
** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
** **
** License to copy and use this software is granted provided that **
** it is identified as the "RSA Data Security, Inc. MD5 Message **
** Digest Algorithm" in all material mentioning or referencing this **
** software or this function. **
** **
** License is also granted to make and use derivative works **
** provided that such works are identified as "derived from the RSA **
** Data Security, Inc. MD5 Message Digest Algorithm" in all **
** material mentioning or referencing the derived work. **
** **
** RSA Data Security, Inc. makes no representations concerning **
** either the merchantability of this software or the suitability **
** of this software for any particular purpose. It is provided "as **
** is" without express or implied warranty of any kind. **
** **
** These notices must be retained in any copies of any part of this **
** documentation and/or software. **
**********************************************************************
*/
#ifndef __PPR_MD5_H__
#define __PPR_MD5_H__
#include <ppr_machdep.h>
typedef struct ppr_md5_context ppr_md5_context_t;
struct ppr_md5_context {
ppr_uint32_t i[2]; /* number of _bits_ handled mod 2^64 */
ppr_uint32_t buf[4]; /* scratch buffer */
unsigned char in[64]; /* input buffer */
unsigned char digest[16]; /* actual digest after MD5Final call */
};
void ppr_md5_init(ppr_md5_context_t* mdContext);
void ppr_md5_update(ppr_md5_context_t* mdContext, const void* inBuf, unsigned int inLen);
void ppr_md5_final(ppr_md5_context_t* mdContext);
#endif

8
include/ppr_sha256.h Normal file
View file

@ -0,0 +1,8 @@
#ifndef __PPR_SHA256_H__
#define __PPR_SHA256_H__
#include <ppr_machdep.h>
void ppr_sha256(void* output, const void* data, ppr_size_t len);
#endif

25
include/ppr_url.h Normal file
View file

@ -0,0 +1,25 @@
#ifndef __PPR_URL_H__
#define __PPR_URL_H__
#include <ppr_machdep.h>
typedef struct ppr_url ppr_url_t;
struct ppr_url {
char* scheme;
char* userinfo;
char* host;
int port;
char* path;
char* query;
char* fragment;
};
ppr_bool ppr_url_decode(char* out, const char* input, int len);
ppr_bool ppr_url_encode(char* out, const char* input, int len);
void ppr_url_init(ppr_url_t* url);
ppr_bool ppr_url_parse(ppr_url_t* url, const char* str);
void ppr_url_deinit(ppr_url_t* url);
#endif

8
include/ppr_wildcard.h Normal file
View file

@ -0,0 +1,8 @@
#ifndef __PPR_WILDCARD_H__
#define __PPR_WILDCARD_H__
#include <ppr_machdep.h>
ppr_bool ppr_wildcard(const char* wildcard, const char* target);
#endif

247
src/base/arpa.c Normal file
View file

@ -0,0 +1,247 @@
#include <ppr.h>
#include <ppr_int.h>
ppr_uint16_t ppr_htons(ppr_uint16_t host16) {
#if defined(PPR_IS_NETWARE)
unsigned char buf[2];
buf[0] = (host16 >> 8) & 0xff;
buf[1] = (host16 >> 0) & 0xff;
return *(ppr_uint16_t*)buf;
#else
return htons(host16);
#endif
}
static int sort_v6(const void* _a, const void* _b) {
int* a = (int*)_a;
int* b = (int*)_b;
if(a[1] > b[1]) return -1;
if(a[1] < b[1]) return 1;
return 0;
}
const char* ppr_inet_ntop(struct ppr_sockaddr* src, char* dst) {
if(src->sa_family == PPR_AF_INET) {
struct ppr_sockaddr_in* addr = (struct ppr_sockaddr_in*)src;
int i;
dst[0] = 0;
for(i = 0; i < 4; i++) {
if(i > 0) strcat(dst, ".");
sprintf(dst + strlen(dst), "%d", (int)addr->sin_addr.u.addr8[i]);
}
return dst;
} else if(src->sa_family == PPR_AF_INET6) {
struct ppr_sockaddr_in6* addr = (struct ppr_sockaddr_in6*)src;
int i;
char v6[8][5];
int l[8][2]; /* index, count */
int c = -1;
int z = 0;
int max = 8;
dst[0] = 0;
for(i = 0; i < 16; i += 2) {
v6[i / 2][0] = 0;
if(addr->sin6_addr.u.addr8[i + 0] > 0) {
sprintf(v6[i / 2], "%x", (int)addr->sin6_addr.u.addr8[i + 0]);
}
if(addr->sin6_addr.u.addr8[i + 0] > 0 && !(addr->sin6_addr.u.addr8[i + 1] & 0xf0)) strcat(v6[i / 2], "0");
sprintf(v6[i / 2] + strlen(v6[i / 2]), "%x", (int)addr->sin6_addr.u.addr8[i + 1]);
}
for(i = 0; i < 8; i++) l[i][0] = l[i][1] = 0;
for(i = 7; i >= 0; i--) {
if(z && strcmp(v6[i], "0") == 0) {
l[c][0] = i;
l[c][1]++;
continue;
} else if(z) {
z = 0;
}
if(strcmp(v6[i], "0") == 0) {
z = 1;
c++;
l[c][0] = i;
l[c][1] = 1;
} else {
}
}
qsort(l, 8, sizeof(int) * 2, sort_v6);
dst[0] = 0;
for(i = 0; i < max; i++) {
if(i > 0 || l[0][1] == 8) strcat(dst, ":");
if(i == l[0][0] && l[0][1] > 0) {
if(i == 0 || (i + l[0][1] - 1) == (max - 1)) strcat(dst, ":");
i += l[0][1] - 1;
} else {
strcat(dst, v6[i]);
}
}
if(memcmp(dst, "::ffff:", 7) == 0) {
struct ppr_sockaddr_in in;
dst[7] = 0;
in.sin_family = PPR_AF_INET;
memcpy(&in.sin_addr, &addr->sin6_addr.u.addr8[12], 4);
ppr_inet_ntop((struct ppr_sockaddr*)&in, dst + 7);
}
return dst;
}
return NULL;
}
struct ppr_sockaddr* ppr_inet_addr(const char* addr, int* len) {
int d = 0;
int i;
const char* v4[4];
v4[0] = addr;
for(i = 0; addr[i] != 0; i++) {
if(addr[i] == '.') {
d++;
v4[d] = &addr[i + 1];
} else if('0' <= addr[i] && addr[i] <= '9') {
} else {
break;
}
}
/* IPv4 */
if(d == 3 && addr[i] == 0) {
struct ppr_sockaddr_in* in = malloc(sizeof(*in));
in->sin_family = PPR_AF_INET;
for(i = 0; i < 4; i++) in->sin_addr.u.addr8[i] = atoi(v4[i]);
*len = sizeof(*in);
return (struct ppr_sockaddr*)in;
}
for(i = 0; addr[i] != 0; i++) {
if(addr[i] == '[' && i == 0) {
} else if(addr[i] == ']' && i == (strlen(addr) - 1)) {
} else if(addr[i] == ':') {
} else if('0' <= addr[i] && addr[i] <= '9') {
} else if('a' <= addr[i] && addr[i] <= 'f') {
} else if('A' <= addr[i] && addr[i] <= 'F') {
} else {
break;
}
}
/* IPv6 */
if(addr[i] == 0) {
const char* b = addr;
int e = 0;
struct ppr_sockaddr_in6* in6 = malloc(sizeof(*in6));
int incr = 0;
in6->sin6_family = PPR_AF_INET6;
memset(in6->sin6_addr.u.addr8, 0, 16);
for(i = 0;; i++) {
if(addr[i] == 0 || addr[i] == ']' || addr[i] == ':') {
char* n = malloc(&addr[i] - b + 1);
n[&addr[i] - b] = 0;
memcpy(n, b, &addr[i] - b);
if(strlen(n) == 0) {
e++;
} else {
int j;
int f = strlen(n) - 1;
int old = incr;
int inc = 0;
e = 0;
incr++;
for(j = f; j >= 0; j--) {
char byte = n[j];
if('0' <= byte && byte <= '9') {
byte = byte - '0';
} else if('a' <= byte && byte <= 'f') {
byte = byte - 'a' + 10;
} else if('A' <= byte && byte <= 'F') {
byte = byte - 'A' + 10;
}
in6->sin6_addr.u.addr8[incr] = in6->sin6_addr.u.addr8[incr] | (byte << (4 * inc));
inc++;
if(j == (f - 1)) {
incr--;
inc = 0;
}
}
incr = old + 2;
if(incr > 16) {
free(n);
free(in6);
return NULL;
}
}
free(n);
if(e == 2) {
int len = 16 - incr;
int c = 0;
int j;
for(j = i + 1; addr[j] != ']' && addr[j] != 0; j++) {
if(j == (i + 1) && !(addr[j] == ']' || addr[j] == 0)) c++;
if(addr[j] == ':') c++;
}
incr += len - c * 2;
if(incr > 16) {
free(in6);
return NULL;
}
}
b = &addr[i + 1];
if(addr[i] == 0 || addr[i] == ']') break;
} else if(addr[i] == '[') {
b = &addr[i + 1];
}
}
*len = sizeof(*in6);
return (struct ppr_sockaddr*)in6;
}
return NULL;
}

125
src/base/dirent.c Normal file
View file

@ -0,0 +1,125 @@
#include <ppr.h>
#include <ppr_int.h>
#if defined(PPR_IS_WIN32)
typedef struct dir {
ppr_bool next;
HANDLE hFind;
WIN32_FIND_DATA ffd;
char* path;
struct ppr_dirent dirent;
} dir_t;
#else
typedef struct dir {
DIR* dir;
char* path;
struct ppr_dirent dirent;
} dir_t;
#endif
PPR_DIR* ppr_opendir(const char* path) {
dir_t* dir = malloc(sizeof(*dir));
#if defined(PPR_IS_WIN32)
char* p = ppr_strvacat(path, (path[strlen(path) - 1] == '/' || path[strlen(path) - 1] == '\\') ? "" : (strchr(path, '/') != NULL ? "/" : "\\"), "*", NULL);
if((dir->hFind = FindFirstFile(p, &dir->ffd)) == INVALID_HANDLE_VALUE) {
free(p);
free(dir);
return NULL;
}
free(p);
dir->next = ppr_true;
#else
if((dir->dir = opendir(path)) == NULL) {
free(dir);
return NULL;
}
#endif
dir->path = ppr_strdup(path);
return (PPR_DIR*)dir;
}
struct ppr_dirent* ppr_readdir(PPR_DIR* handle) {
dir_t* dir = handle;
#if defined(PPR_IS_WIN32)
if(!dir->next) return NULL;
strcpy(dir->dirent.d_name, dir->ffd.cFileName);
#else
struct dirent* d;
if((d = readdir(dir->dir)) == NULL) return NULL;
strcpy(dir->dirent.d_name, d->d_name);
#endif
strcpy(dir->dirent.d_fullname, dir->path);
if(dir->path[strlen(dir->path) - 1] != '/' && dir->path[strlen(dir->path) - 1] != '\\') {
#if defined(PPR_IS_WIN32)
strcat(dir->dirent.d_fullname, strchr(dir->path, '/') != NULL ? "/" : "\\");
#else
strcat(dir->dirent.d_fullname, "/");
#endif
}
strcat(dir->dirent.d_fullname, dir->dirent.d_name);
memset(&dir->dirent.d_stat, 0, sizeof(dir->dirent.d_stat));
ppr_stat(dir->dirent.d_fullname, &dir->dirent.d_stat);
return &dir->dirent;
}
void ppr_closedir(PPR_DIR* handle) {
dir_t* dir = handle;
#if defined(PPR_IS_WIN32)
FindClose(dir->hFind);
#else
closedir(dir->dir);
#endif
free(dir->path);
free(dir);
}
int ppr_scandir(const char* dirname, struct ppr_dirent*** namelist, int (*selectfn)(const struct ppr_dirent* d), int (*compar)(const struct ppr_dirent** d1, const struct ppr_dirent** d2)) {
PPR_DIR* dir = ppr_opendir(dirname);
struct ppr_dirent* d;
int n = 0;
int n2 = 0;
if(dir == NULL) return -1;
while((d = ppr_readdir(dir)) != NULL) n++;
ppr_closedir(dir);
if((dir = ppr_opendir(dirname)) == NULL) return -1;
*namelist = malloc(sizeof(**namelist) * n);
while(n2 < n && (d = ppr_readdir(dir)) != NULL) {
if(selectfn != NULL && !selectfn(d)) continue;
(*namelist)[n2] = malloc(sizeof(***namelist));
memcpy((*namelist)[n2], d, sizeof(*d));
n2++;
}
ppr_closedir(dir);
qsort(*namelist, n2, sizeof(**namelist), (int (*)(const void* d1, const void* d2))compar);
return n2;
}
int ppr_alphasort(const struct ppr_dirent** d1, const struct ppr_dirent** d2) {
return strcmp((*d1)->d_name, (*d2)->d_name);
}

45
src/base/dlfcn.c Normal file
View file

@ -0,0 +1,45 @@
#include <ppr.h>
#include <ppr_int.h>
void* ppr_dlopen(const char* path) {
#if defined(PPR_IS_WIN32)
return LoadLibrary(path);
#elif defined(PPR_IS_UNIX)
return dlopen(path, RTLD_LAZY | RTLD_LOCAL);
#elif defined(PPR_IS_NETWARE)
unsigned int handle = FindNLMHandle(path);
if(handle == 0) {
spawnlp(P_NOWAIT | P_SPAWN_IN_CURRENT_DOMAIN, path, NULL);
handle = FindNLMHandle(path);
}
return (void*)handle;
#else
return NULL;
#endif
}
void* ppr_dlsym(void* handle, const char* symbol) {
#if defined(PPR_IS_WIN32)
return GetProcAddress(handle, symbol);
#elif defined(PPR_IS_UNIX)
return dlsym(handle, symbol);
#elif defined(PPR_IS_NETWARE)
return ImportSymbol((unsigned int)handle, symbol);
#else
return NULL;
#endif
}
int ppr_dlclose(void* handle) {
#if defined(PPR_IS_WIN32)
return FreeLibrary(handle) ? 0 : 1;
#elif defined(PPR_IS_UNIX)
return dlclose(handle);
#elif defined(PPR_IS_NETWARE)
return 0;
#else
return -1;
#endif
}

61
src/base/file.c Normal file
View file

@ -0,0 +1,61 @@
#include <ppr.h>
#include <ppr_int.h>
PPR_FILE* ppr_fopen(const char* path, const char* mode) {
#if defined(PPR_IS_WIN32)
DWORD ac = 0;
DWORD dis = 0;
DWORD fl = FILE_ATTRIBUTE_NORMAL;
HANDLE h;
if(mode[0] == 'r') {
ac = GENERIC_READ;
dis = OPEN_EXISTING;
} else if(mode[0] == 'w') {
ac = GENERIC_WRITE;
dis = CREATE_ALWAYS;
} else if(mode[0] == 'a') {
ac = GENERIC_WRITE | FILE_APPEND_DATA;
dis = OPEN_ALWAYS;
}
h = CreateFile(path, ac, FILE_SHARE_READ, NULL, dis, fl, NULL);
if(h == INVALID_HANDLE_VALUE) return NULL;
return (PPR_FILE*)h;
#else
return (PPR_FILE*)fopen(path, mode);
#endif
}
int ppr_fread(void* ptr, int size, int nmemb, PPR_FILE* stream) {
#if defined(PPR_IS_WIN32)
DWORD dw;
if(!ReadFile((HANDLE)stream, ptr, size * nmemb, &dw, NULL)) return -1;
return dw;
#else
return fread(ptr, size, nmemb, (FILE*)stream);
#endif
}
int ppr_fwrite(const void* ptr, int size, int nmemb, PPR_FILE* stream) {
#if defined(PPR_IS_WIN32)
DWORD dw;
if(!WriteFile((HANDLE)stream, ptr, size * nmemb, &dw, NULL)) return -1;
return dw;
#else
return fwrite(ptr, size, nmemb, (FILE*)stream);
#endif
}
void ppr_fclose(PPR_FILE* stream) {
#if defined(PPR_IS_WIN32)
CloseHandle((HANDLE)stream);
#else
fclose((FILE*)stream);
#endif
}

62
src/base/mutex.c Normal file
View file

@ -0,0 +1,62 @@
#include <ppr.h>
#include <ppr_int.h>
void* ppr_mutex_create(void) {
#if defined(PPR_IS_WIN32)
return CreateEvent(NULL, FALSE, TRUE, NULL);
#elif defined(PPR_USE_PTHREAD)
pthread_mutex_t* mutex = malloc(sizeof(*mutex));
pthread_mutex_init(mutex, NULL);
return mutex;
#elif defined(PPR_IS_NETWARE)
LONG* mutex = malloc(sizeof(*mutex));
*mutex = ppr_thread_open_semaphore(1);
return mutex;
#else
return NULL;
#endif
}
void ppr_mutex_lock(void* handle) {
#if defined(PPR_IS_WIN32)
WaitForSingleObject(handle, INFINITE);
#elif defined(PPR_USE_PTHREAD)
pthread_mutex_lock(handle);
#elif defined(PPR_IS_NETWARE)
WaitOnLocalSemaphore(*(LONG*)handle);
#else
(void)handle;
#endif
}
void ppr_mutex_unlock(void* handle) {
#if defined(PPR_IS_WIN32)
SetEvent(handle);
#elif defined(PPR_USE_PTHREAD)
pthread_mutex_unlock(handle);
#elif defined(PPR_IS_NETWARE)
SignalLocalSemaphore(*(LONG*)handle);
#else
(void)handle;
#endif
}
void ppr_mutex_destroy(void* handle) {
#if defined(PPR_IS_WIN32)
CloseHandle(handle);
#elif defined(PPR_USE_PTHREAD)
pthread_mutex_destroy(handle);
free(handle);
#elif defined(PPR_IS_NETWARE)
ppr_thread_close_semaphore(*(LONG*)handle);
free(handle);
#else
(void)handle;
#endif
}

62
src/base/poll.c Normal file
View file

@ -0,0 +1,62 @@
#include <ppr.h>
#include <ppr_int.h>
int ppr_poll(struct ppr_pollfd* fds, int nfds, int timeout) {
#if defined(PPR_HAS_POLL)
struct pollfd* pfds = malloc(sizeof(*pfds) * nfds);
int i;
int st;
for(i = 0; i < nfds; i++) {
pfds[i].fd = fds[i].fd;
pfds[i].events = 0;
fds[i].revents = 0;
if(fds[i].events & PPR_POLLIN) pfds[i].events |= POLLIN;
if(fds[i].events & PPR_POLLPRI) pfds[i].events |= POLLPRI;
if(fds[i].events & PPR_POLLOUT) pfds[i].events |= POLLOUT;
}
st = poll(pfds, nfds, timeout);
if(st > 0) {
for(i = 0; i < nfds; i++) {
if(pfds[i].revents & POLLIN) fds[i].revents |= PPR_POLLIN;
if(pfds[i].revents & POLLPRI) fds[i].revents |= PPR_POLLPRI;
if(pfds[i].revents & POLLOUT) fds[i].revents |= PPR_POLLOUT;
}
}
free(pfds);
return st;
#else
fd_set rfds;
fd_set wfds;
int i;
struct timeval tv;
int st;
FD_ZERO(&rfds);
FD_ZERO(&wfds);
for(i = 0; i < nfds; i++) {
if(fds[i].events & PPR_POLLIN) FD_SET(fds[i].fd, &rfds);
if(fds[i].events & PPR_POLLOUT) FD_SET(fds[i].fd, &wfds);
fds[i].revents = 0;
}
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
st = select(FD_SETSIZE, &rfds, &wfds, NULL, &tv);
for(i = 0; i < nfds; i++) {
if(FD_ISSET(fds[i].fd, &rfds)) fds[i].revents |= PPR_POLLIN;
if(FD_ISSET(fds[i].fd, &wfds)) fds[i].revents |= PPR_POLLOUT;
}
return st;
#endif
}

271
src/base/process.c Normal file
View file

@ -0,0 +1,271 @@
#include <ppr.h>
#include <ppr_int.h>
typedef struct process {
#if defined(PPR_IS_WIN32)
HANDLE process;
HANDLE thread;
HANDLE h_stdin;
HANDLE h_stdout;
HANDLE h_stderr;
#elif defined(PPR_IS_UNIX)
pid_t pid;
int fd_stdin;
int fd_stdout;
int fd_stderr;
#else
void* reserved;
#endif
} process_t;
static ppr_bool is_allowed_env(const char* n) {
char* p = ppr_strdup(n);
char* s;
if((s = strchr(p, '=')) != NULL) s[0] = 0;
if(strcmp(p, "PATH") == 0) return ppr_true;
return ppr_false;
}
void* ppr_process_create(const char* exec, char** env) {
#if defined(PPR_IS_WIN32)
process_t* proc = malloc(sizeof(*proc));
SECURITY_ATTRIBUTES attr;
HANDLE pipe_stdin[2];
HANDLE pipe_stdout[2];
HANDLE pipe_stderr[2];
char path[2048];
char* envs;
PROCESS_INFORMATION pi;
STARTUPINFO si;
char* d_envs = GetEnvironmentStrings();
char* d_envs2;
int envs_len = 0;
int i;
d_envs2 = d_envs;
while(*d_envs2) {
if(is_allowed_env(d_envs2)) envs_len += strlen(d_envs2) + 1;
d_envs2 += strlen(d_envs2) + 1;
}
for(i = 0; env[i] != NULL; i++) envs_len += strlen(env[i]) + 1;
envs_len++;
envs = malloc(envs_len);
envs_len = 0;
d_envs2 = d_envs;
while(*d_envs2) {
if(is_allowed_env(d_envs2)) {
strcpy(envs + envs_len, d_envs2);
envs_len += strlen(d_envs2) + 1;
}
d_envs2 += strlen(d_envs2) + 1;
}
for(i = 0; env[i] != NULL; i++) {
strcpy(envs + envs_len, env[i]);
envs_len += strlen(env[i]) + 1;
}
FreeEnvironmentStrings(d_envs);
envs[envs_len] = 0;
memset(&pi, 0, sizeof(pi));
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES;
sprintf(path, "\"%s\"", exec);
memset(&attr, 0, sizeof(attr));
attr.nLength = sizeof(attr);
attr.bInheritHandle = TRUE;
CreatePipe(&pipe_stdin[0], &pipe_stdin[1], &attr, 0);
SetHandleInformation(pipe_stdin[1], HANDLE_FLAG_INHERIT, 0);
CreatePipe(&pipe_stdout[0], &pipe_stdout[1], &attr, 0);
SetHandleInformation(pipe_stdout[0], HANDLE_FLAG_INHERIT, 0);
CreatePipe(&pipe_stderr[0], &pipe_stderr[1], &attr, 0);
SetHandleInformation(pipe_stderr[0], HANDLE_FLAG_INHERIT, 0);
si.hStdInput = pipe_stdin[0];
si.hStdOutput = pipe_stdout[1];
si.hStdError = pipe_stderr[1];
if(!CreateProcess(NULL, path, NULL, NULL, TRUE, 0, envs, NULL, &si, &pi)) {
int i;
free(proc);
free(envs);
for(i = 0; i < 2; i++) {
CloseHandle(pipe_stdin[i]);
CloseHandle(pipe_stdout[i]);
CloseHandle(pipe_stderr[i]);
}
return NULL;
} else {
CloseHandle(pipe_stdin[0]);
CloseHandle(pipe_stdout[1]);
CloseHandle(pipe_stderr[1]);
proc->process = pi.hProcess;
proc->thread = pi.hThread;
proc->h_stdin = pipe_stdin[1];
proc->h_stdout = pipe_stdout[0];
proc->h_stderr = pipe_stderr[0];
}
free(envs);
return proc;
#elif defined(PPR_IS_UNIX)
process_t* proc = malloc(sizeof(*proc));
int pipe_stdin[2];
int pipe_stdout[2];
int pipe_stderr[2];
char** envs = NULL;
int i;
int c = 0;
extern char** environ;
for(i = 0; environ[i] != NULL; i++) {
if(is_allowed_env(environ[i])) c++;
}
for(i = 0; env != NULL && env[i] != NULL; i++) c++;
envs = malloc(sizeof(*envs) * (c + 1));
c = 0;
for(i = 0; environ[i] != NULL; i++) {
if(is_allowed_env(environ[i])) envs[c++] = environ[i];
}
for(i = 0; env != NULL && env[i] != NULL; i++) envs[c++] = env[i];
envs[c] = 0;
pipe(pipe_stdin);
pipe(pipe_stdout);
pipe(pipe_stderr);
if((proc->pid = fork()) == 0) {
int basefd = pipe_stdout[1] > pipe_stderr[1] ? pipe_stdout[1] : pipe_stderr[1];
int infd = basefd + 3;
int outfd = basefd + 4;
int errfd = basefd + 5;
free(proc);
close(pipe_stdin[1]);
close(pipe_stdout[0]);
close(pipe_stderr[0]);
dup2(pipe_stdin[0], infd);
dup2(pipe_stdout[1], outfd);
dup2(pipe_stderr[1], errfd);
close(pipe_stdin[0]);
close(pipe_stdout[1]);
close(pipe_stderr[1]);
dup2(infd, 0);
dup2(outfd, 1);
dup2(errfd, 2);
close(infd);
close(outfd);
close(errfd);
execle(exec, exec, NULL, envs);
_exit(-1);
} else {
close(pipe_stdin[0]);
close(pipe_stdout[1]);
close(pipe_stderr[1]);
proc->fd_stdin = pipe_stdin[1];
proc->fd_stdout = pipe_stdout[0];
proc->fd_stderr = pipe_stderr[0];
}
free(envs);
return proc;
#else
return NULL;
#endif
}
void ppr_process_close(void* handle) {
process_t* proc = handle;
#if defined(PPR_IS_WIN32)
CloseHandle(proc->h_stdin);
proc->h_stdin = NULL;
#elif defined(PPR_IS_UNIX)
close(proc->fd_stdin);
proc->fd_stdin = -1;
#endif
}
int ppr_process_write(void* handle, const void* data, int len) {
process_t* proc = handle;
#if defined(PPR_IS_WIN32)
DWORD r;
if(!WriteFile(proc->h_stdin, data, len, &r, NULL)) return -1;
return r;
#elif defined(PPR_IS_UNIX)
return write(proc->fd_stdin, data, len);
#else
return -1;
#endif
}
int ppr_process_read(void* handle, void* data, int len) {
process_t* proc = handle;
#if defined(PPR_IS_WIN32)
DWORD r;
if(!ReadFile(proc->h_stdout, data, len, &r, NULL)) return -1;
return r;
#elif defined(PPR_IS_UNIX)
return read(proc->fd_stdout, data, len);
#else
return -1;
#endif
}
void ppr_process_destroy(void* handle) {
process_t* proc = handle;
#if defined(PPR_IS_WIN32)
if(proc->h_stdin != NULL) CloseHandle(proc->h_stdin);
CloseHandle(proc->h_stdout);
CloseHandle(proc->h_stderr);
WaitForSingleObject(proc->process, INFINITE);
CloseHandle(proc->process);
CloseHandle(proc->thread);
#elif defined(PPR_IS_UNIX)
int st;
if(proc->fd_stdin >= 0) close(proc->fd_stdin);
close(proc->fd_stdout);
close(proc->fd_stderr);
do {
waitpid(proc->pid, &st, 0);
} while(!WIFEXITED(st));
#endif
free(proc);
}

276
src/base/socket.c Normal file
View file

@ -0,0 +1,276 @@
#include <ppr.h>
#include <ppr_int.h>
#if !defined(IPPROTO_TCP)
#define IPPROTO_TCP 0
#endif
#if !defined(IPPROTO_UDP)
#define IPPROTO_UDP 0
#endif
#if defined(PPR_IS_NETWARE)
struct in_addr {
ppr_uint32_t s_addr;
};
struct sockaddr_in {
ppr_uint16_t sin_family;
ppr_uint16_t sin_port;
struct in_addr sin_addr;
ppr_uint8_t sin_zero[8];
};
#endif
void ppr_socket_init(void) {
#if defined(PPR_IS_WIN32)
WSADATA wsa;
WSAStartup(MAKEWORD(2, 0), &wsa);
#elif defined(PPR_IS_UNIX)
signal(SIGPIPE, SIG_IGN);
#endif
}
void ppr_socket_uninit(void) {
#if defined(PPR_IS_WIN32)
WSACleanup();
#elif defined(PPR_IS_UNIX)
#endif
}
int ppr_socket(int domain, int type, int protocol) {
int d = PF_UNSPEC, t = 0, p = 0;
int s;
int nbyt;
if(domain == PPR_PF_INET) {
d = PF_INET;
#if defined(PPR_HAS_IPV6)
} else if(domain == PPR_PF_INET6) {
d = PF_INET6;
#endif
#if defined(PPR_HAS_UNIX_SOCKET)
} else if(domain == PPR_PF_UNIX) {
d = PF_UNIX;
#endif
}
if(type == PPR_SOCK_STREAM) {
t = SOCK_STREAM;
} else if(type == PPR_SOCK_DGRAM) {
t = SOCK_DGRAM;
}
if(protocol == PPR_IPPROTO_TCP) {
p = IPPROTO_TCP;
} else if(protocol == PPR_IPPROTO_UDP) {
p = IPPROTO_UDP;
}
s = socket(d, t, p);
#if defined(PPR_IS_WIN32)
if(s == INVALID_SOCKET) s = -1;
#endif
if(s >= 0 && t == SOCK_STREAM && p == IPPROTO_TCP) {
int yes = 1;
setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (void*)&yes, sizeof(yes));
}
#if defined(PPR_HAS_IPV6)
if(s >= 0 && d == PF_INET6) {
int yes = 1;
setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&yes, sizeof(yes));
}
#endif
if(s >= 0) {
nbyt = 65535;
setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char*)&nbyt, sizeof(nbyt));
nbyt = 65535;
setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char*)&nbyt, sizeof(nbyt));
}
return s;
}
/* we ignore flags for now */
int ppr_recv(int s, void* buf, int len, int flags) {
(void)flags;
return recv(s, buf, len, 0);
}
int ppr_send(int s, const void* msg, int len, int flags) {
(void)flags;
return send(s, (void*)msg, len, 0);
}
static struct sockaddr* conv_to_sa(int* outlen, const struct ppr_sockaddr* input, int namelen) {
struct sockaddr* out = NULL;
if(input->sa_family == PPR_AF_INET && namelen == sizeof(struct ppr_sockaddr_in)) {
struct ppr_sockaddr_in* addr = (struct ppr_sockaddr_in*)input;
struct sockaddr_in addr4;
addr4.sin_family = AF_INET;
addr4.sin_addr.s_addr = addr->sin_addr.u.addr32[0];
addr4.sin_port = addr->sin_port;
out = malloc(sizeof(addr4));
memcpy(out, &addr4, sizeof(addr4));
*outlen = sizeof(addr4);
#if defined(PPR_HAS_IPV6)
} else if(input->sa_family == PPR_AF_INET6 && namelen == sizeof(struct ppr_sockaddr_in6)) {
struct ppr_sockaddr_in6* addr = (struct ppr_sockaddr_in6*)input;
struct sockaddr_in6 addr6;
addr6.sin6_family = AF_INET6;
memcpy(addr6.sin6_addr.s6_addr, &addr->sin6_addr.u.addr8, 16);
addr6.sin6_port = addr->sin6_port;
out = malloc(sizeof(addr6));
memcpy(out, &addr6, sizeof(addr6));
*outlen = sizeof(addr6);
#endif
#if defined(PPR_HAS_UNIX_SOCKET)
} else if(input->sa_family == PPR_AF_UNIX && namelen == sizeof(struct ppr_sockaddr_un)) {
struct ppr_sockaddr_un* addr = (struct ppr_sockaddr_un*)input;
struct sockaddr_un addru;
addru.sun_family = AF_UNIX;
strcpy(addru.sun_path, addr->sun_path);
out = malloc(sizeof(addru));
memcpy(out, &addru, sizeof(addru));
*outlen = sizeof(addru);
#endif
}
return out;
}
int ppr_bind(int s, const struct ppr_sockaddr* name, int namelen) {
int st = -1;
int yes = 1;
struct sockaddr* sa;
int len;
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&yes, sizeof(yes));
if((sa = conv_to_sa(&len, name, namelen)) != NULL) {
st = bind(s, sa, len);
free(sa);
}
return st;
}
int ppr_connect(int s, const struct ppr_sockaddr* name, int namelen) {
int st = -1;
struct sockaddr* sa;
int len;
if((sa = conv_to_sa(&len, name, namelen)) != NULL) {
st = connect(s, sa, len);
free(sa);
}
return st;
}
int ppr_listen(int s, int backlog) {
return listen(s, backlog);
}
int ppr_accept(int s, struct ppr_sockaddr* addr, int* addrlen) {
unsigned char buffer[256];
struct sockaddr* sa = (struct sockaddr*)buffer;
int r;
#if defined(PPR_USE_SOCKLEN_T)
socklen_t l
#else
int l
#endif
= *addrlen;
r = accept(s, sa, &l);
*addrlen = l;
#if defined(PPR_IS_WIN32)
if(r == INVALID_SOCKET) r = -1;
#endif
if(r < 0) return r;
if(sa->sa_family == AF_INET) {
struct ppr_sockaddr_in* taddr = (struct ppr_sockaddr_in*)addr;
struct sockaddr_in* addr4 = (struct sockaddr_in*)buffer;
taddr->sin_family = PPR_AF_INET;
taddr->sin_addr.u.addr32[0] = addr4->sin_addr.s_addr;
taddr->sin_port = addr4->sin_port;
*addrlen = sizeof(*taddr);
#if defined(PPR_HAS_IPV6)
} else if(sa->sa_family == AF_INET6) {
struct ppr_sockaddr_in6* taddr = (struct ppr_sockaddr_in6*)addr;
struct sockaddr_in6* addr6 = (struct sockaddr_in6*)buffer;
taddr->sin6_family = PPR_AF_INET6;
memcpy(taddr->sin6_addr.u.addr32, addr6->sin6_addr.s6_addr, 16);
taddr->sin6_port = addr6->sin6_port;
*addrlen = sizeof(*taddr);
#endif
#if defined(PPR_HAS_UNIX_SOCKET)
} else if(sa->sa_family == AF_UNIX) {
struct ppr_sockaddr_un* taddr = (struct ppr_sockaddr_un*)addr;
struct sockaddr_un* addru = (struct sockaddr_un*)buffer;
taddr->sun_family = PPR_AF_UNIX;
strcpy(taddr->sun_path, addru->sun_path);
*addrlen = sizeof(*taddr);
#endif
}
return r;
}
void ppr_socket_close(int d) {
#if defined(PPR_IS_WIN32)
shutdown(d, SD_BOTH);
closesocket(d);
#elif defined(PPR_IS_UNIX)
shutdown(d, SHUT_RD);
close(d);
#endif
}
ppr_bool ppr_socket_has_ipv6(void) {
#if defined(PPR_HAS_IPV6)
#if defined(PPR_IS_WIN32)
DWORD v = GetVersion();
DWORD majorv, minorv;
majorv = LOBYTE(LOWORD(v));
minorv = HIBYTE(LOWORD(v));
if(majorv > 5 && (majorv == 5 && minorv >= 1)) return ppr_true;
return ppr_false;
#else
return ppr_true;
#endif
#else
return ppr_false;
#endif
}
struct ppr_in_addr ppr_inaddr_any = {
{{0, 0, 0, 0}}};
struct ppr_in6_addr ppr_in6addr_any = {
{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}};

48
src/base/stat.c Normal file
View file

@ -0,0 +1,48 @@
#include <ppr.h>
#include <ppr_int.h>
int ppr_stat(const char* path, struct ppr_stat* s) {
#if defined(PPR_IS_WIN32)
WIN32_FILE_ATTRIBUTE_DATA fad;
ULARGE_INTEGER mtime;
if(!GetFileAttributesEx(path, GetFileExInfoStandard, &fad)) return -1;
memcpy(&mtime, &fad.ftLastWriteTime, sizeof(mtime));
s->st_size = 0;
s->st_modtime = (mtime.QuadPart / 10000000) / 11644473600;
s->st_mode = 0;
s->st_mode |= PPR_S_IFREG;
if(fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
s->st_mode &= ~PPR_S_IFREG;
s->st_mode |= PPR_S_IFDIR;
}
if(PPR_S_ISREG(s->st_mode)) {
PPR_FILE* f = ppr_fopen(path, "r"); /* :))))))) */
s->st_size = GetFileSize((HANDLE)f, NULL);
ppr_fclose(f);
}
return 0;
#elif defined(PPR_IS_UNIX) || defined(PPR_IS_NETWARE)
struct stat st;
int sc;
sc = stat(path, &st);
if(sc != 0) return sc;
s->st_size = st.st_size;
s->st_modtime = st.st_mtime;
s->st_mode = 0;
if(S_ISREG(st.st_mode)) s->st_mode |= PPR_S_IFREG;
if(S_ISDIR(st.st_mode)) s->st_mode |= PPR_S_IFDIR;
return sc;
#else
return -1;
#endif
}

73
src/base/string.c Normal file
View file

@ -0,0 +1,73 @@
#include <ppr.h>
#include <ppr_int.h>
char* ppr_strdup(const char* str) {
char* r = malloc(strlen(str) + 1);
strcpy(r, str);
return r;
}
char* ppr_strvacat(const char* a, ...) {
int l = 1 + strlen(a);
va_list va;
char* s;
char* r;
va_start(va, a);
while((s = va_arg(va, char*)) != NULL) {
l += strlen(s);
}
va_end(va);
r = malloc(l);
strcpy(r, a);
va_start(va, a);
while((s = va_arg(va, char*)) != NULL) {
strcat(r, s);
}
va_end(va);
return r;
}
void ppr_strappend(char** dst, const char* src) {
char* n = ppr_strvacat(*dst, src, NULL);
free(*dst);
*dst = n;
}
char* ppr_strsafehtml(const char* s) {
char* r = malloc(strlen(s) * 5 + 1);
int i;
int n = 0;
for(i = 0; s[i] != 0; i++) {
if(s[i] == '&') {
r[n++] = '&';
r[n++] = 'a';
r[n++] = 'm';
r[n++] = 'p';
r[n++] = ';';
} else if(s[i] == '<') {
r[n++] = '&';
r[n++] = 'l';
r[n++] = 't';
r[n++] = ';';
} else if(s[i] == '>') {
r[n++] = '&';
r[n++] = 'g';
r[n++] = 't';
r[n++] = ';';
} else {
r[n++] = s[i];
}
}
r[n] = 0;
return r;
}

227
src/base/thread.c Normal file
View file

@ -0,0 +1,227 @@
#include <ppr.h>
#include <ppr_int.h>
typedef struct arg {
void (*entry)(void* param);
void* param;
#if defined(PPR_IS_NETWARE)
LONG waitsem;
#endif
} arg_t;
#if defined(PPR_IS_NETWARE)
typedef struct thread {
int thread;
LONG waitsem;
} thread_t;
struct ppr_thread_usage {
ppr_bool used;
thread_t* thread;
};
struct ppr_semaphore_usage ppr_semaphores[1024];
struct ppr_thread_usage ppr_threads[1024];
#endif
#if defined(PPR_IS_NETWARE)
long ppr_thread_open_semaphore(long initial) {
long sem = OpenLocalSemaphore(initial);
int i;
for(i = 0; i < sizeof(ppr_semaphores) / sizeof(ppr_semaphores[0]); i++) {
if(!ppr_semaphores[i].used) {
ppr_semaphores[i].used = ppr_true;
ppr_semaphores[i].sem = sem;
break;
}
}
return sem;
}
void ppr_thread_close_semaphore(long sem) {
int i;
for(i = 0; i < sizeof(ppr_semaphores) / sizeof(ppr_semaphores[0]); i++) {
if(ppr_semaphores[i].used && ppr_semaphores[i].sem == sem) {
ppr_semaphores[i].used = ppr_false;
break;
}
}
CloseLocalSemaphore(sem);
}
#endif
void ppr_thread_init(void) {
#if defined(PPR_IS_NETWARE)
int i;
for(i = 0; i < sizeof(ppr_semaphores) / sizeof(ppr_semaphores[0]); i++) {
ppr_semaphores[i].used = ppr_false;
}
for(i = 0; i < sizeof(ppr_threads) / sizeof(ppr_threads[0]); i++) {
ppr_threads[i].used = ppr_false;
}
#endif
}
void ppr_thread_uninit(void) {
#if defined(PPR_IS_NETWARE)
int i;
for(i = 0; i < sizeof(ppr_threads) / sizeof(ppr_threads[0]); i++) {
if(ppr_threads[i].used) {
ppr_thread_join(ppr_threads[i].thread);
ppr_thread_destroy(ppr_threads[i].thread);
}
}
for(i = 0; i < sizeof(ppr_semaphores) / sizeof(ppr_semaphores[0]); i++) {
if(ppr_semaphores[i].used) {
ppr_thread_close_semaphore(ppr_semaphores[i].sem);
}
}
#endif
}
#if defined(PPR_IS_WIN32)
#if defined(PPR_USE_CREATETHREAD)
static DWORD WINAPI thread_entry(void* _param) {
#else
static unsigned int WINAPI thread_entry(void* _param) {
#endif
arg_t* arg = _param;
void (*entry)(void* param) = arg->entry;
void* param = arg->param;
free(arg);
entry(param);
#if defined(PPR_USE_CREATETHREAD)
ExitThread(0);
#else
_endthreadex(0);
#endif
return 0;
}
#elif defined(PPR_USE_PTHREAD)
static void* thread_entry(void* _param) {
arg_t* arg = _param;
void (*entry)(void* param) = arg->entry;
void* param = arg->param;
free(arg);
entry(param);
pthread_exit(NULL);
return NULL;
}
#elif defined(PPR_IS_NETWARE)
static void thread_entry(void* _param) {
arg_t* arg = _param;
void (*entry)(void* param) = arg->entry;
void* param = arg->param;
LONG waitsem = arg->waitsem;
free(arg);
entry(param);
SignalLocalSemaphore(waitsem);
ExitThread(EXIT_THREAD, 0);
}
#endif
void* ppr_thread_create(void (*entry)(void* param), void* param) {
#if defined(PPR_IS_WIN32)
arg_t* arg = malloc(sizeof(*arg));
#if defined(PPR_USE_CREATETHREAD)
DWORD id;
#else
unsigned int id;
#endif
arg->entry = entry;
arg->param = param;
return (void*)
#if defined(PPR_USE_CREATETHREAD)
CreateThread
#else
_beginthreadex
#endif
(NULL, 0, thread_entry, arg, 0, &id);
#elif defined(PPR_USE_PTHREAD)
pthread_t* t = malloc(sizeof(*t));
arg_t* arg = malloc(sizeof(*arg));
arg->entry = entry;
arg->param = param;
pthread_create(t, NULL, thread_entry, arg);
return t;
#elif defined(PPR_IS_NETWARE)
thread_t* t = malloc(sizeof(*t));
arg_t* arg = malloc(sizeof(*arg));
arg->entry = entry;
arg->param = param;
arg->waitsem = ppr_thread_open_semaphore(0);
t->waitsem = arg->waitsem;
t->thread = BeginThread(thread_entry, NULL, 8192, arg);
return t;
#else
(void)entry;
(void)param;
return NULL;
#endif
}
void ppr_thread_join(void* handle) {
#if defined(PPR_IS_WIN32)
WaitForSingleObject(handle, INFINITE);
#elif defined(PPR_USE_PTHREAD)
void* ret;
pthread_join(*(pthread_t*)handle, &ret);
#elif defined(PPR_IS_NETWARE)
thread_t* t = handle;
WaitOnLocalSemaphore(t->waitsem);
#else
(void)handle;
#endif
}
void ppr_thread_destroy(void* handle) {
#if defined(PPR_IS_WIN32)
CloseHandle(handle);
#elif defined(PPR_USE_PTHREAD)
free(handle);
#elif defined(PPR_IS_NETWARE)
thread_t* t = handle;
int i;
ppr_thread_close_semaphore(t->waitsem);
for(i = 0; i < sizeof(ppr_threads) / sizeof(ppr_threads[0]); i++) {
if(ppr_threads[i].used && ppr_threads[i].thread == handle) {
ppr_threads[i].used = ppr_false;
break;
}
}
free(handle);
#else
(void)handle;
#endif
}

45
src/base/time.c Normal file
View file

@ -0,0 +1,45 @@
#include <ppr.h>
#include <ppr_int.h>
void* ppr_gmtime_mutex;
void* ppr_localtime_mutex;
ppr_time_t ppr_time(void) {
time_t t = time(NULL);
return t;
}
static void tm_to_ppr(struct ppr_tm* to, struct tm* from) {
to->tm_sec = from->tm_sec;
to->tm_min = from->tm_min;
to->tm_hour = from->tm_hour;
to->tm_mday = from->tm_mday;
to->tm_mon = from->tm_mon;
to->tm_year = from->tm_year;
to->tm_wday = from->tm_wday;
to->tm_yday = from->tm_yday;
to->tm_isdst = from->tm_isdst;
}
void ppr_gmtime(struct ppr_tm* tm, ppr_time_t t) {
struct tm from_tm;
time_t from = t;
ppr_mutex_lock(ppr_gmtime_mutex);
from_tm = *gmtime(&from);
ppr_mutex_unlock(ppr_gmtime_mutex);
tm_to_ppr(tm, &from_tm);
}
void ppr_localtime(struct ppr_tm* tm, ppr_time_t t) {
struct tm from_tm;
time_t from = t;
ppr_mutex_lock(ppr_localtime_mutex);
from_tm = *localtime(&from);
ppr_mutex_unlock(ppr_localtime_mutex);
tm_to_ppr(tm, &from_tm);
}

33
src/base/unistd.c Normal file
View file

@ -0,0 +1,33 @@
#include <ppr.h>
#include <ppr_int.h>
int ppr_gethostname(char* name, int namelen) {
#if defined(PPR_IS_PS2)
if(namelen < 4) return -1;
strcpy(name, "PS2");
return 0;
#elif defined(PPR_IS_NETWARE)
if(namelen < 8) return -1;
strcpy(name, "netware");
return 0;
#else
return gethostname(name, namelen);
#endif
}
void ppr_msleep(int ms) {
#if defined(PPR_IS_WIN32)
Sleep(ms);
#elif defined(PPR_IS_NETWARE)
delay(ms);
#else
struct timespec ts;
ts.tv_sec = ms / 1000;
ts.tv_nsec = (ms % 1000) * 1000000;
nanosleep(&ts, NULL);
#endif
}

22
src/core.c Normal file
View file

@ -0,0 +1,22 @@
#include <ppr.h>
#include <ppr_int.h>
void ppr_init(void) {
ppr_socket_init();
ppr_thread_init();
#if defined(PPR_IS_NETWARE)
SetCurrentNameSpace(NW_NS_LONG);
#endif
ppr_gmtime_mutex = ppr_mutex_create();
ppr_localtime_mutex = ppr_mutex_create();
}
void ppr_uninit(void) {
ppr_mutex_destroy(ppr_localtime_mutex);
ppr_mutex_destroy(ppr_gmtime_mutex);
ppr_thread_uninit();
ppr_socket_uninit();
}

368
src/hash/blake2s.c Normal file
View file

@ -0,0 +1,368 @@
/*
BLAKE2 reference source code package - reference C implementations
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#include <ppr.h>
#include <ppr_int.h>
#include "blake2s_int.h"
static const ppr_uint32_t ppr_blake2s_IV[8] =
{
0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL};
static const ppr_uint8_t ppr_blake2s_sigma[10][16] =
{
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
{14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
{11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4},
{7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8},
{9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13},
{2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9},
{12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11},
{13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10},
{6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5},
{10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0},
};
static void ppr_blake2s_set_lastnode(ppr_blake2s_state* S) {
S->f[1] = (ppr_uint32_t)-1;
}
/* Some helper functions, not necessarily useful */
static int ppr_blake2s_is_lastblock(const ppr_blake2s_state* S) {
return S->f[0] != 0;
}
static void ppr_blake2s_set_lastblock(ppr_blake2s_state* S) {
if(S->last_node) ppr_blake2s_set_lastnode(S);
S->f[0] = (ppr_uint32_t)-1;
}
static void ppr_blake2s_increment_counter(ppr_blake2s_state* S, const ppr_uint32_t inc) {
S->t[0] += inc;
S->t[1] += (S->t[0] < inc);
}
static void ppr_blake2s_init0(ppr_blake2s_state* S) {
ppr_size_t i;
memset(S, 0, sizeof(ppr_blake2s_state));
for(i = 0; i < 8; ++i) S->h[i] = ppr_blake2s_IV[i];
}
/* init2 xors IV with input parameter block */
int ppr_blake2s_init_param(ppr_blake2s_state* S, const ppr_blake2s_param* P) {
ppr_size_t i;
#ifdef PPR_HAS_PACK
unsigned char* p = (unsigned char*)P;
#else
unsigned char p[32];
unsigned char* ptr = &p[0];
#endif
ppr_blake2s_init0(S);
#ifndef PPR_HAS_PACK
#define COPY(x) \
{ \
memcpy(ptr, &(x), sizeof((x))); \
ptr += sizeof((x)); \
}
COPY(P->digest_length);
COPY(P->key_length);
COPY(P->fanout);
COPY(P->depth);
COPY(P->leaf_length);
COPY(P->node_offset);
COPY(P->xof_length);
COPY(P->node_depth);
COPY(P->inner_length);
COPY(P->salt);
COPY(P->personal);
#undef COPY
#endif
/* IV XOR ParamBlock */
for(i = 0; i < 8; ++i)
S->h[i] ^= load32(&p[i * 4]);
S->outlen = P->digest_length;
return 0;
}
/* Sequential ppr_blake2s initialization */
int ppr_blake2s_init(ppr_blake2s_state* S, ppr_size_t outlen) {
ppr_blake2s_param P[1];
/* Move interval verification here? */
if((!outlen) || (outlen > BLAKE2S_OUTBYTES)) return -1;
P->digest_length = (ppr_uint8_t)outlen;
P->key_length = 0;
P->fanout = 1;
P->depth = 1;
store32(&P->leaf_length, 0);
store32(&P->node_offset, 0);
store16(&P->xof_length, 0);
P->node_depth = 0;
P->inner_length = 0;
/* memset(P->reserved, 0, sizeof(P->reserved) ); */
memset(P->salt, 0, sizeof(P->salt));
memset(P->personal, 0, sizeof(P->personal));
return ppr_blake2s_init_param(S, P);
}
int ppr_blake2s_init_key(ppr_blake2s_state* S, ppr_size_t outlen, const void* key, ppr_size_t keylen) {
ppr_blake2s_param P[1];
if((!outlen) || (outlen > BLAKE2S_OUTBYTES)) return -1;
if(!key || !keylen || keylen > BLAKE2S_KEYBYTES) return -1;
P->digest_length = (ppr_uint8_t)outlen;
P->key_length = (ppr_uint8_t)keylen;
P->fanout = 1;
P->depth = 1;
store32(&P->leaf_length, 0);
store32(&P->node_offset, 0);
store16(&P->xof_length, 0);
P->node_depth = 0;
P->inner_length = 0;
/* memset(P->reserved, 0, sizeof(P->reserved) ); */
memset(P->salt, 0, sizeof(P->salt));
memset(P->personal, 0, sizeof(P->personal));
if(ppr_blake2s_init_param(S, P) < 0) return -1;
{
ppr_uint8_t block[BLAKE2S_BLOCKBYTES];
memset(block, 0, BLAKE2S_BLOCKBYTES);
memcpy(block, key, keylen);
ppr_blake2s_update(S, block, BLAKE2S_BLOCKBYTES);
secure_zero_memory(block, BLAKE2S_BLOCKBYTES); /* Burn the key from stack */
}
return 0;
}
#define G(r, i, a, b, c, d) \
do { \
a = a + b + m[ppr_blake2s_sigma[r][2 * i + 0]]; \
d = rotr32(d ^ a, 16); \
c = c + d; \
b = rotr32(b ^ c, 12); \
a = a + b + m[ppr_blake2s_sigma[r][2 * i + 1]]; \
d = rotr32(d ^ a, 8); \
c = c + d; \
b = rotr32(b ^ c, 7); \
} while(0)
#define ROUND(r) \
do { \
G(r, 0, v[0], v[4], v[8], v[12]); \
G(r, 1, v[1], v[5], v[9], v[13]); \
G(r, 2, v[2], v[6], v[10], v[14]); \
G(r, 3, v[3], v[7], v[11], v[15]); \
G(r, 4, v[0], v[5], v[10], v[15]); \
G(r, 5, v[1], v[6], v[11], v[12]); \
G(r, 6, v[2], v[7], v[8], v[13]); \
G(r, 7, v[3], v[4], v[9], v[14]); \
} while(0)
static void ppr_blake2s_compress(ppr_blake2s_state* S, const ppr_uint8_t in[BLAKE2S_BLOCKBYTES]) {
ppr_uint32_t m[16];
ppr_uint32_t v[16];
ppr_size_t i;
for(i = 0; i < 16; ++i) {
m[i] = load32(in + i * sizeof(m[i]));
}
for(i = 0; i < 8; ++i) {
v[i] = S->h[i];
}
v[8] = ppr_blake2s_IV[0];
v[9] = ppr_blake2s_IV[1];
v[10] = ppr_blake2s_IV[2];
v[11] = ppr_blake2s_IV[3];
v[12] = S->t[0] ^ ppr_blake2s_IV[4];
v[13] = S->t[1] ^ ppr_blake2s_IV[5];
v[14] = S->f[0] ^ ppr_blake2s_IV[6];
v[15] = S->f[1] ^ ppr_blake2s_IV[7];
ROUND(0);
ROUND(1);
ROUND(2);
ROUND(3);
ROUND(4);
ROUND(5);
ROUND(6);
ROUND(7);
ROUND(8);
ROUND(9);
for(i = 0; i < 8; ++i) {
S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
}
}
#undef G
#undef ROUND
int ppr_blake2s_update(ppr_blake2s_state* S, const void* pin, ppr_size_t inlen) {
const unsigned char* in = (const unsigned char*)pin;
if(inlen > 0) {
ppr_size_t left = S->buflen;
ppr_size_t fill = BLAKE2S_BLOCKBYTES - left;
if(inlen > fill) {
S->buflen = 0;
memcpy(S->buf + left, in, fill); /* Fill buffer */
ppr_blake2s_increment_counter(S, BLAKE2S_BLOCKBYTES);
ppr_blake2s_compress(S, S->buf); /* Compress */
in += fill;
inlen -= fill;
while(inlen > BLAKE2S_BLOCKBYTES) {
ppr_blake2s_increment_counter(S, BLAKE2S_BLOCKBYTES);
ppr_blake2s_compress(S, in);
in += BLAKE2S_BLOCKBYTES;
inlen -= BLAKE2S_BLOCKBYTES;
}
}
memcpy(S->buf + S->buflen, in, inlen);
S->buflen += inlen;
}
return 0;
}
int ppr_blake2s_final(ppr_blake2s_state* S, void* out, ppr_size_t outlen) {
ppr_uint8_t buffer[BLAKE2S_OUTBYTES] = {0};
ppr_size_t i;
if(out == NULL || outlen < S->outlen)
return -1;
if(ppr_blake2s_is_lastblock(S))
return -1;
ppr_blake2s_increment_counter(S, (ppr_uint32_t)S->buflen);
ppr_blake2s_set_lastblock(S);
memset(S->buf + S->buflen, 0, BLAKE2S_BLOCKBYTES - S->buflen); /* Padding */
ppr_blake2s_compress(S, S->buf);
for(i = 0; i < 8; ++i) /* Output full hash to temp buffer */
store32(buffer + sizeof(S->h[i]) * i, S->h[i]);
memcpy(out, buffer, outlen);
secure_zero_memory(buffer, sizeof(buffer));
return 0;
}
int ppr_blake2s(void* out, ppr_size_t outlen, const void* in, ppr_size_t inlen, const void* key, ppr_size_t keylen) {
ppr_blake2s_state S[1];
/* Verify parameters */
if(NULL == in && inlen > 0) return -1;
if(NULL == out) return -1;
if(NULL == key && keylen > 0) return -1;
if(!outlen || outlen > BLAKE2S_OUTBYTES) return -1;
if(keylen > BLAKE2S_KEYBYTES) return -1;
if(keylen > 0) {
if(ppr_blake2s_init_key(S, outlen, key, keylen) < 0) return -1;
} else {
if(ppr_blake2s_init(S, outlen) < 0) return -1;
}
ppr_blake2s_update(S, (const ppr_uint8_t*)in, inlen);
ppr_blake2s_final(S, out, outlen);
return 0;
}
#if defined(SUPERCOP)
int crypto_hash(unsigned char* out, unsigned char* in, unsigned long long inlen) {
return ppr_blake2s(out, BLAKE2S_OUTBYTES, in, inlen, NULL, 0);
}
#endif
#if defined(BLAKE2S_SELFTEST)
#include <string.h>
#include "blake2-kat.h"
int main(void) {
ppr_uint8_t key[BLAKE2S_KEYBYTES];
ppr_uint8_t buf[BLAKE2_KAT_LENGTH];
ppr_size_t i, step;
for(i = 0; i < BLAKE2S_KEYBYTES; ++i)
key[i] = (ppr_uint8_t)i;
for(i = 0; i < BLAKE2_KAT_LENGTH; ++i)
buf[i] = (ppr_uint8_t)i;
/* Test simple API */
for(i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
ppr_uint8_t hash[BLAKE2S_OUTBYTES];
ppr_blake2s(hash, BLAKE2S_OUTBYTES, buf, i, key, BLAKE2S_KEYBYTES);
if(0 != memcmp(hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES)) {
goto fail;
}
}
/* Test streaming API */
for(step = 1; step < BLAKE2S_BLOCKBYTES; ++step) {
for(i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
ppr_uint8_t hash[BLAKE2S_OUTBYTES];
ppr_blake2s_state S;
ppr_uint8_t* p = buf;
ppr_size_t mlen = i;
int err = 0;
if((err = ppr_blake2s_init_key(&S, BLAKE2S_OUTBYTES, key, BLAKE2S_KEYBYTES)) < 0) {
goto fail;
}
while(mlen >= step) {
if((err = ppr_blake2s_update(&S, p, step)) < 0) {
goto fail;
}
mlen -= step;
p += step;
}
if((err = ppr_blake2s_update(&S, p, mlen)) < 0) {
goto fail;
}
if((err = ppr_blake2s_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
goto fail;
}
if(0 != memcmp(hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES)) {
goto fail;
}
}
}
puts("ok");
return 0;
fail:
puts("error");
return -1;
}
#endif

73
src/hash/blake2s_int.h Normal file
View file

@ -0,0 +1,73 @@
/*
BLAKE2 reference source code package - reference C implementations
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#ifndef BLAKE2S_INT_H
#define BLAKE2S_INT_H
#include <ppr_machdep.h>
#include <string.h>
#define BLAKE2S_INLINE static __inline
BLAKE2S_INLINE ppr_uint32_t load32(const void* src) {
#if defined(NATIVE_LITTLE_ENDIAN)
ppr_uint32_t w;
memcpy(&w, src, sizeof w);
return w;
#else
const ppr_uint8_t* p = (const ppr_uint8_t*)src;
return ((ppr_uint32_t)(p[0]) << 0) |
((ppr_uint32_t)(p[1]) << 8) |
((ppr_uint32_t)(p[2]) << 16) |
((ppr_uint32_t)(p[3]) << 24);
#endif
}
BLAKE2S_INLINE void store16(void* dst, ppr_uint16_t w) {
#if defined(NATIVE_LITTLE_ENDIAN)
memcpy(dst, &w, sizeof w);
#else
ppr_uint8_t* p = (ppr_uint8_t*)dst;
*p++ = (ppr_uint8_t)w;
w >>= 8;
*p++ = (ppr_uint8_t)w;
#endif
}
BLAKE2S_INLINE void store32(void* dst, ppr_uint32_t w) {
#if defined(NATIVE_LITTLE_ENDIAN)
memcpy(dst, &w, sizeof w);
#else
ppr_uint8_t* p = (ppr_uint8_t*)dst;
p[0] = (ppr_uint8_t)(w >> 0);
p[1] = (ppr_uint8_t)(w >> 8);
p[2] = (ppr_uint8_t)(w >> 16);
p[3] = (ppr_uint8_t)(w >> 24);
#endif
}
BLAKE2S_INLINE ppr_uint32_t rotr32(const ppr_uint32_t w, const unsigned c) {
return (w >> c) | (w << (32 - c));
}
#include <stddef.h>
/* prevents compiler optimizing out memset() */
BLAKE2S_INLINE void secure_zero_memory(void* v, ppr_size_t n) {
static void* (*const volatile memset_v)(void*, int, size_t) = &memset;
memset_v(v, 0, n);
}
#endif

254
src/hash/md5.c Normal file
View file

@ -0,0 +1,254 @@
#include <ppr.h>
#include <ppr_int.h>
/*
**********************************************************************
** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
** **
** License to copy and use this software is granted provided that **
** it is identified as the "RSA Data Security, Inc. MD5 Message **
** Digest Algorithm" in all material mentioning or referencing this **
** software or this function. **
** **
** License is also granted to make and use derivative works **
** provided that such works are identified as "derived from the RSA **
** Data Security, Inc. MD5 Message Digest Algorithm" in all **
** material mentioning or referencing the derived work. **
** **
** RSA Data Security, Inc. makes no representations concerning **
** either the merchantability of this software or the suitability **
** of this software for any particular purpose. It is provided "as **
** is" without express or implied warranty of any kind. **
** **
** These notices must be retained in any copies of any part of this **
** documentation and/or software. **
**********************************************************************
*/
/* forward declaration */
static void Transform(ppr_uint32_t* buf, ppr_uint32_t* in);
static unsigned char PADDING[64] = {
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
/* F, G and H are basic MD5 functions: selection, majority, parity */
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
/* ROTATE_LEFT rotates x left n bits */
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
/* Rotation is separate from addition to prevent recomputation */
#define FF(a, b, c, d, x, s, ac) \
{ \
(a) += F((b), (c), (d)) + (x) + (ppr_uint32_t)(ac); \
(a) = ROTATE_LEFT((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) \
{ \
(a) += G((b), (c), (d)) + (x) + (ppr_uint32_t)(ac); \
(a) = ROTATE_LEFT((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) \
{ \
(a) += H((b), (c), (d)) + (x) + (ppr_uint32_t)(ac); \
(a) = ROTATE_LEFT((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) \
{ \
(a) += I((b), (c), (d)) + (x) + (ppr_uint32_t)(ac); \
(a) = ROTATE_LEFT((a), (s)); \
(a) += (b); \
}
void ppr_md5_init(ppr_md5_context_t* mdContext) {
mdContext->i[0] = mdContext->i[1] = (ppr_uint32_t)0;
/* Load magic initialization constants.
*/
mdContext->buf[0] = (ppr_uint32_t)0x67452301;
mdContext->buf[1] = (ppr_uint32_t)0xefcdab89;
mdContext->buf[2] = (ppr_uint32_t)0x98badcfe;
mdContext->buf[3] = (ppr_uint32_t)0x10325476;
}
void ppr_md5_update(ppr_md5_context_t* mdContext, const void* inBuf, unsigned int inLen) {
ppr_uint32_t in[16];
int mdi;
unsigned int i, ii;
const unsigned char* buf = inBuf;
/* compute number of bytes mod 64 */
mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
/* update number of bits */
if((mdContext->i[0] + ((ppr_uint32_t)inLen << 3)) < mdContext->i[0])
mdContext->i[1]++;
mdContext->i[0] += ((ppr_uint32_t)inLen << 3);
mdContext->i[1] += ((ppr_uint32_t)inLen >> 29);
while(inLen--) {
/* add new character to buffer, increment mdi */
mdContext->in[mdi++] = *buf++;
/* transform if necessary */
if(mdi == 0x40) {
for(i = 0, ii = 0; i < 16; i++, ii += 4)
in[i] = (((ppr_uint32_t)mdContext->in[ii + 3]) << 24) |
(((ppr_uint32_t)mdContext->in[ii + 2]) << 16) |
(((ppr_uint32_t)mdContext->in[ii + 1]) << 8) |
((ppr_uint32_t)mdContext->in[ii]);
Transform(mdContext->buf, in);
mdi = 0;
}
}
}
void ppr_md5_final(ppr_md5_context_t* mdContext) {
ppr_uint32_t in[16];
int mdi;
unsigned int i, ii;
unsigned int padLen;
/* save number of bits */
in[14] = mdContext->i[0];
in[15] = mdContext->i[1];
/* compute number of bytes mod 64 */
mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
/* pad out to 56 mod 64 */
padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
ppr_md5_update(mdContext, PADDING, padLen);
/* append length in bits and transform */
for(i = 0, ii = 0; i < 14; i++, ii += 4)
in[i] = (((ppr_uint32_t)mdContext->in[ii + 3]) << 24) |
(((ppr_uint32_t)mdContext->in[ii + 2]) << 16) |
(((ppr_uint32_t)mdContext->in[ii + 1]) << 8) |
((ppr_uint32_t)mdContext->in[ii]);
Transform(mdContext->buf, in);
/* store buffer in digest */
for(i = 0, ii = 0; i < 4; i++, ii += 4) {
mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);
mdContext->digest[ii + 1] =
(unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
mdContext->digest[ii + 2] =
(unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
mdContext->digest[ii + 3] =
(unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
}
}
/* Basic MD5 step. Transform buf based on in.
*/
static void Transform(ppr_uint32_t* buf, ppr_uint32_t* in) {
ppr_uint32_t a = buf[0], b = buf[1], c = buf[2], d = buf[3];
/* Round 1 */
#define S11 7
#define S12 12
#define S13 17
#define S14 22
FF(a, b, c, d, in[0], S11, 3614090360); /* 1 */
FF(d, a, b, c, in[1], S12, 3905402710); /* 2 */
FF(c, d, a, b, in[2], S13, 606105819); /* 3 */
FF(b, c, d, a, in[3], S14, 3250441966); /* 4 */
FF(a, b, c, d, in[4], S11, 4118548399); /* 5 */
FF(d, a, b, c, in[5], S12, 1200080426); /* 6 */
FF(c, d, a, b, in[6], S13, 2821735955); /* 7 */
FF(b, c, d, a, in[7], S14, 4249261313); /* 8 */
FF(a, b, c, d, in[8], S11, 1770035416); /* 9 */
FF(d, a, b, c, in[9], S12, 2336552879); /* 10 */
FF(c, d, a, b, in[10], S13, 4294925233); /* 11 */
FF(b, c, d, a, in[11], S14, 2304563134); /* 12 */
FF(a, b, c, d, in[12], S11, 1804603682); /* 13 */
FF(d, a, b, c, in[13], S12, 4254626195); /* 14 */
FF(c, d, a, b, in[14], S13, 2792965006); /* 15 */
FF(b, c, d, a, in[15], S14, 1236535329); /* 16 */
/* Round 2 */
#define S21 5
#define S22 9
#define S23 14
#define S24 20
GG(a, b, c, d, in[1], S21, 4129170786); /* 17 */
GG(d, a, b, c, in[6], S22, 3225465664); /* 18 */
GG(c, d, a, b, in[11], S23, 643717713); /* 19 */
GG(b, c, d, a, in[0], S24, 3921069994); /* 20 */
GG(a, b, c, d, in[5], S21, 3593408605); /* 21 */
GG(d, a, b, c, in[10], S22, 38016083); /* 22 */
GG(c, d, a, b, in[15], S23, 3634488961); /* 23 */
GG(b, c, d, a, in[4], S24, 3889429448); /* 24 */
GG(a, b, c, d, in[9], S21, 568446438); /* 25 */
GG(d, a, b, c, in[14], S22, 3275163606); /* 26 */
GG(c, d, a, b, in[3], S23, 4107603335); /* 27 */
GG(b, c, d, a, in[8], S24, 1163531501); /* 28 */
GG(a, b, c, d, in[13], S21, 2850285829); /* 29 */
GG(d, a, b, c, in[2], S22, 4243563512); /* 30 */
GG(c, d, a, b, in[7], S23, 1735328473); /* 31 */
GG(b, c, d, a, in[12], S24, 2368359562); /* 32 */
/* Round 3 */
#define S31 4
#define S32 11
#define S33 16
#define S34 23
HH(a, b, c, d, in[5], S31, 4294588738); /* 33 */
HH(d, a, b, c, in[8], S32, 2272392833); /* 34 */
HH(c, d, a, b, in[11], S33, 1839030562); /* 35 */
HH(b, c, d, a, in[14], S34, 4259657740); /* 36 */
HH(a, b, c, d, in[1], S31, 2763975236); /* 37 */
HH(d, a, b, c, in[4], S32, 1272893353); /* 38 */
HH(c, d, a, b, in[7], S33, 4139469664); /* 39 */
HH(b, c, d, a, in[10], S34, 3200236656); /* 40 */
HH(a, b, c, d, in[13], S31, 681279174); /* 41 */
HH(d, a, b, c, in[0], S32, 3936430074); /* 42 */
HH(c, d, a, b, in[3], S33, 3572445317); /* 43 */
HH(b, c, d, a, in[6], S34, 76029189); /* 44 */
HH(a, b, c, d, in[9], S31, 3654602809); /* 45 */
HH(d, a, b, c, in[12], S32, 3873151461); /* 46 */
HH(c, d, a, b, in[15], S33, 530742520); /* 47 */
HH(b, c, d, a, in[2], S34, 3299628645); /* 48 */
/* Round 4 */
#define S41 6
#define S42 10
#define S43 15
#define S44 21
II(a, b, c, d, in[0], S41, 4096336452); /* 49 */
II(d, a, b, c, in[7], S42, 1126891415); /* 50 */
II(c, d, a, b, in[14], S43, 2878612391); /* 51 */
II(b, c, d, a, in[5], S44, 4237533241); /* 52 */
II(a, b, c, d, in[12], S41, 1700485571); /* 53 */
II(d, a, b, c, in[3], S42, 2399980690); /* 54 */
II(c, d, a, b, in[10], S43, 4293915773); /* 55 */
II(b, c, d, a, in[1], S44, 2240044497); /* 56 */
II(a, b, c, d, in[8], S41, 1873313359); /* 57 */
II(d, a, b, c, in[15], S42, 4264355552); /* 58 */
II(c, d, a, b, in[6], S43, 2734768916); /* 59 */
II(b, c, d, a, in[13], S44, 1309151649); /* 60 */
II(a, b, c, d, in[4], S41, 4149444226); /* 61 */
II(d, a, b, c, in[11], S42, 3174756917); /* 62 */
II(c, d, a, b, in[2], S43, 718787259); /* 63 */
II(b, c, d, a, in[9], S44, 3951481745); /* 64 */
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}

121
src/hash/sha256.c Normal file
View file

@ -0,0 +1,121 @@
#include <ppr.h>
#include <ppr_int.h>
const ppr_uint32_t sha256_initial_h[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
const ppr_uint32_t sha256_round_k[64] = {0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
static ppr_uint32_t sha256_endian_read32(ppr_uint8_t* input) {
ppr_uint32_t output = 0;
output |= (input[0] << 24);
output |= (input[1] << 16);
output |= (input[2] << 8);
output |= (input[3] << 0);
return output;
}
static ppr_uint32_t sha256_ror(ppr_uint32_t input, ppr_uint32_t by) {
return (input >> by) | (((input & ((1 << by) - 1))) << (32 - by));
}
void ppr_sha256(void* output, const void* data, ppr_size_t len) {
ppr_uint8_t padding[80];
ppr_size_t current = (len + 1) % 64;
/* want to be == 56 % 64. */
ppr_size_t needed = (64 + 56 - current) % 64;
ppr_size_t extra = needed + 9;
ppr_size_t total = len + extra;
int i, j;
ppr_size_t cursor;
ppr_uint32_t v[8];
ppr_size_t l;
for(i = 1; i < 80; i++)
padding[i] = 0;
padding[0] = 0x80;
l = len * 8;
for(i = 7; i >= 0; i--) {
padding[total - len - 8 + i] = l & 0xff;
l = l >> 8;
}
for(i = 0; i < 8; i++)
v[i] = sha256_initial_h[i];
for(cursor = 0; cursor * 64 < total; cursor++) {
ppr_uint32_t t[8];
ppr_uint32_t w[64];
for(i = 0; i < 8; i++)
t[i] = v[i];
if(cursor * 64 + 64 <= len) {
for(j = 0; j < 16; j++) {
w[j] = sha256_endian_read32(
(ppr_uint8_t*)data + cursor * 64 + j * 4);
}
} else {
if(cursor * 64 < len) {
ppr_size_t size = len - cursor * 64;
if(size > 0) memcpy(w, (ppr_uint8_t*)data + cursor * 64, size);
memcpy((ppr_uint8_t*)w + size, padding, 64 - size);
} else {
ppr_size_t off = (cursor * 64 - len) % 64;
memcpy((ppr_uint8_t*)w, padding + off, 64);
}
for(j = 0; j < 16; j++) {
w[j] = sha256_endian_read32((ppr_uint8_t*)&w[j]);
}
}
for(j = 16; j < 64; j++) {
ppr_uint32_t s1 = sha256_ror(w[j - 2], 17) ^ sha256_ror(w[j - 2], 19) ^ (w[j - 2] >> 10);
ppr_uint32_t s0 = sha256_ror(w[j - 15], 7) ^ sha256_ror(w[j - 15], 18) ^ (w[j - 15] >> 3);
w[j] = s1 + w[j - 7] + s0 + w[j - 16];
}
for(j = 0; j < 64; j++) {
ppr_uint32_t ch = (t[4] & t[5]) ^ (~t[4] & t[6]);
ppr_uint32_t maj = (t[0] & t[1]) ^ (t[0] & t[2]) ^ (t[1] & t[2]);
ppr_uint32_t S0 = sha256_ror(t[0], 2) ^ sha256_ror(t[0], 13) ^ sha256_ror(t[0], 22);
ppr_uint32_t S1 = sha256_ror(t[4], 6) ^ sha256_ror(t[4], 11) ^ sha256_ror(t[4], 25);
ppr_uint32_t t1 = t[7] + S1 + ch + sha256_round_k[j] + w[j];
ppr_uint32_t t2 = S0 + maj;
t[7] = t[6];
t[6] = t[5];
t[5] = t[4];
t[4] = t[3] + t1;
t[3] = t[2];
t[2] = t[1];
t[1] = t[0];
t[0] = t1 + t2;
}
for(i = 0; i < 8; i++) v[i] += t[i];
}
for(i = 0; i < 8; i++) {
ppr_uint8_t* out = (ppr_uint8_t*)output + i * 4;
ppr_uint32_t val = v[i];
for(j = 3; j >= 0; j--) {
out[j] = val & 0xff;
val = val >> 8;
}
}
}

218
src/misc/url.c Normal file
View file

@ -0,0 +1,218 @@
#include <ppr.h>
#include <ppr_int.h>
static int hex(const char in) {
if('0' <= in && in <= '9') return in - '0';
if('a' <= in && in <= 'f') return in - 'a' + 10;
if('A' <= in && in <= 'F') return in - 'A' + 10;
return 0;
}
ppr_bool ppr_url_decode(char* out, const char* input, int len) {
int i;
for(i = 0; input[i] != 0; i++) {
if((int)strlen(out) == len) {
return ppr_false;
} else if(input[i] == '%') {
if(strlen(input + i) >= 3) {
int n = strlen(out);
out[n] = (hex(input[i + 1]) << 4) | (hex(input[i + 2]));
out[n + 1] = 0;
i += 2;
}
} else {
int n = strlen(out);
out[n] = input[i];
out[n + 1] = 0;
}
}
return ppr_true;
}
ppr_bool ppr_url_encode(char* out, const char* input, int len) {
int i;
for(i = 0; input[i] != 0; i++) {
if(strlen(out) == len) {
return ppr_false;
} else if(input[i] == '%') {
if(strlen(input + i) >= 3 && strlen(out) <= (len - 3)) {
int n = strlen(out);
out[n] = '%';
out[n + 1] = '2';
out[n + 2] = '5';
out[n + 3] = 0;
}
} else {
int n = strlen(out);
out[n] = input[i];
out[n + 1] = 0;
}
}
return ppr_true;
}
void ppr_url_init(ppr_url_t* url) {
memset(url, 0, sizeof(*url));
}
enum STATE {
USERINFO = 0,
HOST,
PORT,
PATH,
QUERY,
FRAGMENT
};
ppr_bool ppr_url_parse(ppr_url_t* url, const char* str) {
const char* st; /* tmp */
const char* sp; /* pointer */
ppr_bool has_userinfo = ppr_false;
int state = 0;
ppr_bool br = ppr_false;
if((st = strstr(str, "://")) == NULL) return ppr_false;
for(sp = str; sp != st; sp++) {
char c = *sp;
if('A' <= c && c <= 'Z') continue;
if('a' <= c && c <= 'z') continue;
if(sp == str) {
ppr_url_deinit(url);
return ppr_false;
}
if('0' <= c && c <= '9') continue;
if(c == '+' || c == '-' || c == '.') continue;
ppr_url_deinit(url);
return ppr_false;
}
url->scheme = malloc(sp - str + 1);
memcpy(url->scheme, str, sp - str);
url->scheme[sp - str] = 0;
str = st + 3;
if((st = strchr(str, '/')) == NULL) st = str + strlen(str);
for(sp = str; sp != st; sp++) {
if((*sp) == '@') {
has_userinfo = ppr_true;
break;
}
}
if(has_userinfo) {
state = USERINFO;
} else {
state = HOST;
}
for(sp = str;; sp++) {
char c = *sp;
if(state == USERINFO && c == '@') {
url->userinfo = malloc(sp - str + 1);
memcpy(url->userinfo, str, sp - str);
url->userinfo[sp - str] = 0;
str = sp + 1;
state = HOST;
} else if(state == HOST && !br && c == '[') {
br = ppr_true;
} else if(state == HOST && br && c == ']') {
br = ppr_false;
} else if(state == HOST && !br && (c == 0 || c == ':' || c == '/')) {
url->host = malloc(sp - str + 1);
memcpy(url->host, str, sp - str);
url->host[sp - str] = 0;
if(c == 0) {
break;
} else if(c == ':') {
str = sp + 1;
state = PORT;
} else {
str = sp;
state = PATH;
}
} else if(state == PORT && (c == 0 || c == '/')) {
char* p = malloc(sp - str + 1);
memcpy(p, str, sp - str);
p[sp - str] = 0;
url->port = atoi(p);
free(p);
if(c == 0) {
break;
} else {
str = sp; /* intended */
state = PATH;
}
} else if(state == PATH && (c == 0 || c == '?' || c == '#')) {
url->path = malloc(sp - str + 1);
memcpy(url->path, str, sp - str);
url->path[sp - str] = 0;
str = sp + 1;
if(c == 0) {
break;
} else if(c == '?') {
state = QUERY;
} else {
state = FRAGMENT;
}
} else if(state == QUERY && (c == 0 || c == '#')) {
url->query = malloc(sp - str + 1);
memcpy(url->query, str, sp - str);
url->query[sp - str] = 0;
str = sp + 1;
if(c == 0) {
break;
} else {
state = FRAGMENT;
}
} else if(state == FRAGMENT && c == 0) {
url->fragment = malloc(sp - str + 1);
memcpy(url->fragment, str, sp - str);
url->fragment[sp - str] = 0;
break;
} else if(c == 0) {
ppr_url_deinit(url);
return ppr_false;
}
}
return ppr_true;
}
void ppr_url_deinit(ppr_url_t* url) {
if(url->scheme != NULL) free(url->scheme);
if(url->userinfo != NULL) free(url->userinfo);
if(url->host != NULL) free(url->host);
if(url->path != NULL) free(url->path);
if(url->query != NULL) free(url->query);
if(url->fragment != NULL) free(url->fragment);
memset(url, 0, sizeof(*url));
}

23
src/misc/wildcard.c Normal file
View file

@ -0,0 +1,23 @@
#include <ppr.h>
#include <ppr_int.h>
ppr_bool ppr_wildcard(const char* wildcard, const char* target) {
const char *pw = wildcard, *pt = target;
while(1) {
if(*pt == 0) {
while(*pw == '*') pw++;
return *pw == 0;
} else if(*pw == 0) {
return 0;
} else if(*pw == '*') {
return *(pw + 1) == 0 || ppr_wildcard(pw, pt + 1) || ppr_wildcard(pw + 1, pt);
} else if(*pw == '?' || (tolower((int)*pw) == tolower((int)*pt))) {
pw++;
pt++;
continue;
} else {
return 0;
}
}
}