├── .travis.yml ├── Array.c ├── Array.h ├── CGI.c ├── CGI.h ├── CHANGELOG ├── CONTRIBUTING ├── COPYING ├── COPYING.LESSER ├── CommandLineParser.c ├── CommandLineParser.h ├── Compression.c ├── Compression.h ├── ConnectionChain.c ├── ConnectionChain.h ├── Container.c ├── Container.h ├── ContentType.c ├── ContentType.h ├── DataParser.c ├── DataParser.h ├── DataProcessing.c ├── DataProcessing.h ├── Encodings.c ├── Encodings.h ├── Encryption.c ├── Encryption.h ├── Entropy.c ├── Entropy.h ├── Errors.c ├── Errors.h ├── Expect.c ├── Expect.h ├── FileSystem.c ├── FileSystem.h ├── Gemini.c ├── Gemini.h ├── GeneralFunctions.c ├── GeneralFunctions.h ├── HMAC.c ├── HMAC.h ├── Hash.c ├── Hash.h ├── HashCRC32.c ├── HashCRC32.h ├── HashJH.c ├── HashJH.h ├── HashMD5.c ├── HashMD5.h ├── HashOpenSSL.c ├── HashOpenSSL.h ├── HashSHA.c ├── HashSHA.h ├── HashWhirlpool.c ├── HashWhirlpool.h ├── Http.c ├── Http.h ├── HttpChunkedTransfer.c ├── HttpChunkedTransfer.h ├── HttpServer.c ├── HttpServer.h ├── HttpUtil.c ├── HttpUtil.h ├── IPAddress.c ├── IPAddress.h ├── Inet.c ├── Inet.h ├── KeyCodes.h ├── LICENSE ├── LibSettings.c ├── LibSettings.h ├── LineEdit.c ├── LineEdit.h ├── List.c ├── List.h ├── Log.c ├── Log.h ├── Makefile.in ├── Markup.c ├── Markup.h ├── OAuth.c ├── OAuth.h ├── OTP.c ├── OTP.h ├── OpenSSL.c ├── OpenSSL.h ├── PasswordFile.c ├── PasswordFile.h ├── PatternMatch.c ├── PatternMatch.h ├── Process.c ├── Process.h ├── Pty.c ├── Pty.h ├── Quickstart.md ├── README.md ├── RawData.c ├── RawData.h ├── Seccomp.c ├── Seccomp.h ├── SecureMem.c ├── SecureMem.h ├── Server.c ├── Server.h ├── Smtp.c ├── Smtp.h ├── Socket.c ├── Socket.h ├── SpawnPrograms.c ├── SpawnPrograms.h ├── Ssh.c ├── Ssh.h ├── StrLenCache.c ├── StrLenCache.h ├── Stream.c ├── Stream.h ├── StreamAuth.c ├── StreamAuth.h ├── String.c ├── String.h ├── StringList.c ├── StringList.h ├── SysInfo.c ├── SysInfo.h ├── Terminal.c ├── Terminal.h ├── TerminalBar.c ├── TerminalBar.h ├── TerminalCalendar.c ├── TerminalCalendar.h ├── TerminalChoice.c ├── TerminalChoice.h ├── TerminalKeys.c ├── TerminalKeys.h ├── TerminalMenu.c ├── TerminalMenu.h ├── TerminalProgress.c ├── TerminalProgress.h ├── TerminalTheme.c ├── TerminalTheme.h ├── TerminalWidget.c ├── TerminalWidget.h ├── Time.c ├── Time.h ├── Tokenizer.c ├── Tokenizer.h ├── URL.c ├── URL.h ├── Unicode.c ├── Unicode.h ├── UnitsOfMeasure.c ├── UnitsOfMeasure.h ├── UnixSocket.c ├── UnixSocket.h ├── Users.c ├── Users.h ├── Vars.c ├── Vars.h ├── WebSocket.c ├── WebSocket.h ├── base64.c ├── base64.h ├── baseXX.c ├── baseXX.h ├── configure ├── configure.ac ├── crc32.c ├── crc32.h ├── defines.h ├── examples ├── CMON.c ├── Config.c ├── Errors.c ├── FileCopy.c ├── HMAC.c ├── Hash.c ├── HttpServer.c ├── JSON.c ├── LineEdit.c ├── ListLimits.c ├── Makefile ├── Maps.c ├── ParseRSS.c ├── PasswordFile.c ├── README ├── SSLClient.c ├── Smtp.c ├── SpawnContainer.c ├── StrLen.c ├── SysInfo.c ├── TTYTest.c ├── TermBar.c ├── TermCalendar.c ├── TermChoice.c ├── TermMenu.c ├── TermProgress.c ├── Terminal.c ├── Tokenize.c ├── Vars.c ├── Websocket.c ├── WebsocketServer.c ├── YAML.c ├── asciiblast.conf ├── base32.c ├── base64.c ├── calendar.c ├── chroot.c ├── container.c ├── decrypt.c ├── encrypt.c ├── fmtduration.c ├── invoke.conf ├── movetest.c ├── nonewprivs.c ├── pattest.c ├── pbkdf2.c ├── seccomp.c ├── ssh-listfiles.c ├── ssh-time.c ├── ssh-tunnel.c └── uudecode.c ├── includes.h ├── install-sh ├── jh_ref.c ├── jh_ref.h ├── libUseful.h ├── libuseful.luarocks.in ├── md5-global.h ├── md5.h ├── md5c.c ├── sha1.c ├── sha1.h ├── sha2.c ├── sha2.h ├── unicode-names.conf ├── whirlpool.c └── whirlpool.h /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | 3 | os: 4 | - linux 5 | - osx 6 | 7 | compiler: 8 | - clang 9 | - gcc 10 | -------------------------------------------------------------------------------- /Array.c: -------------------------------------------------------------------------------- 1 | #include "includes.h" 2 | #include "Array.h" 3 | 4 | void **ArrayAdd(void **Array, void *Item) 5 | { 6 | void *ptr; 7 | int count=0; 8 | 9 | if (! Array) Array=calloc(10, sizeof(void *)); 10 | else 11 | { 12 | for (ptr=*Array; ptr !=NULL; ptr++) 13 | { 14 | count++; 15 | } 16 | } 17 | 18 | Array=realloc(Array, (count+10) * sizeof(void *)); 19 | Array[count]=Item; 20 | Array[count+1]=NULL; 21 | return(Array); 22 | } 23 | 24 | 25 | void *ArrayGetItem(void *array[], int pos) 26 | { 27 | int i; 28 | for (i=0; i <= pos; i++) 29 | { 30 | if (array[i]==NULL) return(NULL); 31 | if (i==pos) return(array[i]); 32 | } 33 | return(NULL); 34 | } 35 | 36 | 37 | 38 | void ArrayDestroy(void **Array, ARRAY_ITEM_DESTROY_FUNC DestroyFunc) 39 | { 40 | void **ptr; 41 | 42 | for (ptr=Array; *ptr != NULL; ptr++) DestroyFunc(*ptr); 43 | if (Array != NULL) free(Array); 44 | } 45 | 46 | -------------------------------------------------------------------------------- /Array.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_ARRAY_H 7 | #define LIBUSEFUL_ARRAY_H 8 | 9 | /* 10 | These functions create growable arrays of objects 11 | 12 | */ 13 | 14 | 15 | 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | typedef void (*ARRAY_ITEM_DESTROY_FUNC)(void *); 21 | 22 | #define StringArrayAdd(a, s) ( (char **) ArrayAdd((void **) (a), (void *) (s)) ) 23 | #define StringArrayDestroy(a) ArrayDestroy((void **) (a), (Destroy)) 24 | 25 | void **ArrayAdd(void **Array, void *Item); 26 | 27 | //return item at 'pos' in array WITHOUT GOING PAST A NULL. Returns NULL if item can't be reached. 28 | void *ArrayGetItem(void *array[], int pos); 29 | 30 | void ArrayDestroy(void **Array, ARRAY_ITEM_DESTROY_FUNC DestroyFunc); 31 | 32 | 33 | #ifdef __cplusplus 34 | } 35 | #endif 36 | 37 | 38 | 39 | #endif 40 | 41 | -------------------------------------------------------------------------------- /CGI.c: -------------------------------------------------------------------------------- 1 | #include "CGI.h" 2 | 3 | char *CGIReadDocument(char *RetStr, STREAM *S) 4 | { 5 | const char *ptr; 6 | 7 | ptr=getenv("CONTENT_LENGTH"); 8 | if (StrValid(ptr)) 9 | { 10 | S->Size=atoi(ptr); 11 | } 12 | 13 | RetStr=STREAMReadDocument(RetStr, S); 14 | return(RetStr); 15 | } 16 | -------------------------------------------------------------------------------- /CGI.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_CGI_H 7 | #define LIBUSEFUL_CGI_H 8 | 9 | #include "includes.h" 10 | 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | 17 | //simple utility function that checks for a document size in 18 | //the environment variable CONTENT_LENGTH, and then reads bytes up to that size 19 | char *CGIReadDocument(char *RetStr, STREAM *S); 20 | 21 | #ifdef __cplusplus 22 | } 23 | #endif 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /CONTRIBUTING: -------------------------------------------------------------------------------- 1 | LibUseful is currently managed through a repo at github: https://github.com/ColumPaget/libUseful 2 | 3 | Please note that any contributions must be releasable under the Lesser GPL v3, as libUseful can be built under either the GPLv3 or Lesser GPLv3, but the Lesser GPLv3 covers most of the code. 4 | 5 | Thanks go to the following for their contributions: 6 | 7 | Polynomial-C@github.com 8 | mistydemeo@github.com 9 | andreasstieger@github.com 10 | barracuda156@github.com 11 | 12 | -------------------------------------------------------------------------------- /CommandLineParser.c: -------------------------------------------------------------------------------- 1 | #include "CommandLineParser.h" 2 | 3 | void CommandLineParserInit(CMDLINE *CmdLine, int argc, char *argv[]) 4 | { 5 | if (argc < 0) CmdLine->argc=0; 6 | if (! argv) CmdLine->argc=0; 7 | else CmdLine->argc=argc; 8 | CmdLine->argv=(const char **) argv; 9 | } 10 | 11 | 12 | CMDLINE *CommandLineParserCreate(int argc, char *argv[]) 13 | { 14 | CMDLINE *CmdLine; 15 | 16 | CmdLine=(CMDLINE *) calloc(1,sizeof(CMDLINE)); 17 | CommandLineParserInit(CmdLine, argc, argv); 18 | 19 | return(CmdLine); 20 | } 21 | 22 | const char *CommandLineCurr(CMDLINE *CmdLine) 23 | { 24 | const char *ptr=NULL; 25 | 26 | if (CmdLine->curr < CmdLine->argc) 27 | { 28 | ptr=CmdLine->argv[CmdLine->curr]; 29 | } 30 | 31 | return(ptr); 32 | } 33 | 34 | 35 | 36 | const char *CommandLineNext(CMDLINE *CmdLine) 37 | { 38 | const char *ptr=NULL; 39 | 40 | if (CmdLine->curr < CmdLine->argc) 41 | { 42 | CmdLine->curr++; 43 | ptr=CmdLine->argv[CmdLine->curr]; 44 | } 45 | 46 | return(ptr); 47 | } 48 | 49 | const char *CommandLineFirst(CMDLINE *CmdLine) 50 | { 51 | CmdLine->curr=0; 52 | return(CommandLineNext(CmdLine)); 53 | } 54 | 55 | 56 | const char *CommandLinePeek(CMDLINE *CmdLine) 57 | { 58 | const char *ptr=NULL; 59 | 60 | if ((CmdLine->curr+1) < CmdLine->argc) 61 | { 62 | ptr=CmdLine->argv[CmdLine->curr+1]; 63 | } 64 | 65 | return(ptr); 66 | } 67 | 68 | -------------------------------------------------------------------------------- /CommandLineParser.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_CMDLINE_H 7 | #define LIBUSEFUL_CMDLINE_H 8 | 9 | #include "includes.h" 10 | 11 | // handles parsing a command line, and safely handling iterating through 12 | // the list of items. Thus, if there is an item that expects to have an 13 | // argument, but the argument isn't there, CommandLineNext will just return "" 14 | 15 | typedef struct 16 | { 17 | unsigned int argc; 18 | unsigned int curr; 19 | const char **argv; 20 | } CMDLINE; 21 | 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | //initiallize a CMDLINE object. Only needed if using a CMDLINE as a static object, rather 28 | //than dynamically allocated with CommandLineParserCreate 29 | void CommandLineParserInit(CMDLINE *CmdLine, int argc, char *argv[]); 30 | 31 | //dynamically create a CMDLINE object. Either this or CommandLineParserInit are used, not both 32 | CMDLINE *CommandLineParserCreate(int argc, char *argv[]); 33 | 34 | //get current command-line argument 35 | const char *CommandLineCurr(CMDLINE *CmdLine); 36 | 37 | //get next command-line argument, advancing argument pointer 38 | const char *CommandLineNext(CMDLINE *CmdLine); 39 | 40 | //get next command-line argument, WITHOUT advancing argument pointer 41 | const char *CommandLinePeek(CMDLINE *CmdLine); 42 | 43 | //get first command-line argument 44 | const char *CommandLineFirst(CMDLINE *CmdLine); 45 | 46 | #ifdef __cplusplus 47 | } 48 | #endif 49 | 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /Compression.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | 7 | #ifndef LIBUSEFUL_COMPRESSION_H 8 | #define LIBUSEFUL_COMPRESSION_H 9 | 10 | /* 11 | For most users 'zlibProcessorInit' is not important, as it's an 12 | internal function used by 'DataProcessing.h. 13 | 14 | 15 | The 'Alg' argument of CompressBytes and DeCompressBytes specifies the compression algorithm. 16 | Currently supported are "deflate", "zlib", "gzip", "gz", "bzip2", "bz2" and "xz". 17 | 18 | "zlib" is a shorthand for "deflate", "gz" for "gzip", and "bz2" for "bzip2". 19 | 20 | bzip2 and xz are currently implemented by spawning a copy of the bzip2 or xz command-line programs. 21 | Only deflate/gzip is implemented at the library level. Thus bz2 and xz won't work if the appropriate 22 | program is not available. 23 | 24 | If libUseful has been compiled without zlib, then gzip also falls back to using the gzip program. 25 | 26 | CompressBytes and DeCompressBytes both expect 'Out' to be a pointer to a libUseful style string (a block of memory 27 | allocated on the heap using malloc, calloc or realloc. DO NOT USE SIMPLE char ARRAYS ALLOCATED ON THE STACK. 28 | 29 | If there is not enough space in this string for the output these functions will use 'realloc' to make space. This 30 | means you can even pass them a NULL string like this: 31 | 32 | char *Compressed=NULL; 33 | 34 | len=CompressBytes(&Compressed, "gzip", "will it shrink? will it shrink?",31, 1); 35 | 36 | 37 | CompressBytes will allocate memory as needed. This memory must then be freed with 'free' or 'DestroyString'. 38 | 39 | Input data is provided via the 'In' pointer. This can be binary data, so the number of bytes is supplied in 'Len'. 40 | 41 | CompressBytes takes a 'Level' value which specifies the tradeoff between speed and output size. For gzip '1' is 42 | fastest, and '9' tells gzip to try it's hardest to produce the smallest output. 43 | 44 | The return value of Both CompressBytes and DecompressBytes is the length of data placed in 'Out'. 45 | */ 46 | 47 | 48 | #include "includes.h" 49 | #include "Stream.h" 50 | #include "DataProcessing.h" 51 | 52 | #ifdef __cplusplus 53 | extern "C" { 54 | #endif 55 | 56 | //auto-detect compression type from first bytes in the stream 57 | //this function assumes it is passed an open stream that is 58 | //positioned at the start of file or stream. Returns 'gzip', 'bzip2', 'xz', 'lzip' or "" if no match 59 | const char *STREAMDetectCompression(STREAM *S); 60 | 61 | 62 | //these are normally only used internally by libUseful 63 | TProcessingModule *LU_CompressionModuleCreate(const char *Name, const char *Args); 64 | TProcessingModule *LU_DeCompressionModuleCreate(const char *Name, const char *Args); 65 | 66 | int zlibProcessorInit(TProcessingModule *ProcMod, const char *Args, unsigned char **Header, int *HeadLen); 67 | int CompressBytes(char **Out, const char *Alg, const char *In, unsigned long Len, int Level); 68 | int DeCompressBytes(char **Out, const char *Alg, const char *In, unsigned long Len); 69 | 70 | #ifdef __cplusplus 71 | } 72 | #endif 73 | 74 | 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /Container.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | 7 | #ifndef LIBUSEFUL_CONTAINER_H 8 | #define LIBUSEFUL_CONTAINER_H 9 | 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | 16 | #define _GNU_SOURCE 17 | #include 18 | #include 19 | 20 | //this module relates to namespaces/containers. Much of this is pretty linux specific, and would be called 21 | //via 'ProcessApplyConfig' rather than calling this function directly. 22 | 23 | int ContainerApplyConfig(int Flags, const char *Config); 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /ContentType.c: -------------------------------------------------------------------------------- 1 | #include "ContentType.h" 2 | 3 | const char *ContentTypeForFile(const char *File) 4 | { 5 | const char *ptr; 6 | 7 | ptr=strrchr(File, '.'); 8 | if (StrValid(ptr)) 9 | { 10 | if (strcasecmp(ptr, ".pdf")==0) return("application/pdf"); 11 | if (strcasecmp(ptr, ".rtf")==0) return("application/rtf"); 12 | if (strcasecmp(ptr, ".xml")==0) return("application/xml"); 13 | if (strcasecmp(ptr, ".zip")==0) return("application/zip"); 14 | if (strcasecmp(ptr, ".csv")==0) return("text/csv"); 15 | if (strcasecmp(ptr, ".txt")==0) return("text/plain"); 16 | if (strcasecmp(ptr, ".htm")==0) return("text/html"); 17 | if (strcasecmp(ptr, ".html")==0) return("text/html"); 18 | if (strcasecmp(ptr, ".md")==0) return("text/markdown"); 19 | if (strcasecmp(ptr, ".ics")==0) return("text/calendar"); 20 | if (strcasecmp(ptr, ".ical")==0) return("text/calendar"); 21 | if (strcasecmp(ptr, ".gif")==0) return("image/gif"); 22 | if (strcasecmp(ptr, ".jpg")==0) return("image/jpeg"); 23 | if (strcasecmp(ptr, ".png")==0) return("image/png"); 24 | if (strcasecmp(ptr, ".svg")==0) return("image/svg"); 25 | if (strcasecmp(ptr, ".jp2")==0) return("image/jp2"); 26 | if (strcasecmp(ptr, ".jpx")==0) return("image/jpx"); 27 | if (strcasecmp(ptr, ".webm")==0) return("image/webm"); 28 | if (strcasecmp(ptr, ".wav")==0) return("audio/wav"); 29 | if (strcasecmp(ptr, ".mp3")==0) return("audio/mpeg"); 30 | if (strcasecmp(ptr, ".ogg")==0) return("audio/ogg"); 31 | if (strcasecmp(ptr, ".oga")==0) return("audio/ogg"); 32 | if (strcasecmp(ptr, ".flac")==0) return("audio/flac"); 33 | if (strcasecmp(ptr, ".mka")==0) return("audio/x-matroska"); 34 | if (strcasecmp(ptr, ".mp4")==0) return("video/mp4"); 35 | if (strcasecmp(ptr, ".ogv")==0) return("video/theora"); 36 | if (strcasecmp(ptr, ".mkv")==0) return("video/x-matroska"); 37 | } 38 | 39 | return("octet-stream"); 40 | } 41 | -------------------------------------------------------------------------------- /ContentType.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_CONTENT_TYPE_H 7 | #define LIBUSEFUL_CONTENT_TYPE_H 8 | 9 | #include "includes.h" 10 | 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | const char *ContentTypeForFile(const char *File); 17 | 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /Encryption.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | 7 | /* 8 | This module provides a data processor that uses openssl for encryption and decryption. 9 | The resulting output is openssl compatible 'Salted__' format, with pbkdf2 interrated 10000 times 10 | */ 11 | 12 | 13 | #ifndef LIBUSEFUL_ENCRYPTION_H 14 | #define LIBUSEFUL_ENCRYPTION_H 15 | 16 | 17 | #include "includes.h" 18 | 19 | #include "DataProcessing.h" 20 | 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | TProcessingModule *libCryptoProcessorCreate(); 27 | 28 | 29 | #ifdef __cplusplus 30 | } 31 | #endif 32 | 33 | 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /Entropy.c: -------------------------------------------------------------------------------- 1 | #include "Entropy.h" 2 | #include "Encodings.h" 3 | #include "Hash.h" 4 | #include 5 | 6 | #ifdef HAVE_SYS_RANDOM 7 | #include 8 | #endif 9 | 10 | #ifdef HAVE_GETENTROPY 11 | 12 | static int GetEntropyFromGetEntropy(char *RandomBytes, int ReqLen) 13 | { 14 | int len=0, chunk, result; 15 | 16 | while (len < ReqLen) 17 | { 18 | chunk=ReqLen-len; 19 | if (chunk > 256) chunk=256; 20 | //get entropy does not return length, instead it returns 0 on success 21 | //and success means it provided the requested number of bytes 22 | result=getentropy(RandomBytes+len, chunk); 23 | if (result != 0) break; 24 | len+=chunk; 25 | } 26 | 27 | return(len); 28 | } 29 | 30 | #endif 31 | 32 | 33 | static int GetEntropyFromFile(const char *Path, char *RandomBytes, int ReqLen) 34 | { 35 | int len=0, result; 36 | int fd; 37 | 38 | fd=open(Path,O_RDONLY); 39 | if (fd > -1) 40 | { 41 | while(len < ReqLen) 42 | { 43 | result=read(fd,RandomBytes+len,ReqLen-len); 44 | if (result < 0) break; 45 | len+=result; 46 | } 47 | close(fd); 48 | } 49 | return(len); 50 | } 51 | 52 | 53 | //desperately try and generate some random bytes if all better methods fail 54 | static int GetEntropyEmergencyFallback(char **RandomBytes, int ReqLen) 55 | { 56 | clock_t ClocksStart, ClocksEnd; 57 | char *Tempstr=NULL; 58 | struct utsname uts; 59 | int len=0, i; 60 | 61 | ClocksStart=clock(); 62 | //how many clock cycles used here will depend on overall 63 | //machine activity/performance/number of running processes 64 | for (i=0; i < 100; i++) sleep(0); 65 | uname(&uts); 66 | ClocksEnd=clock(); 67 | srand(time(NULL) + ClocksEnd); 68 | 69 | Tempstr=FormatStr(Tempstr,"%lu:%lu:%lu:%lu:%lu:%llu\n",getpid(),getuid(),rand(),ClocksStart,ClocksEnd,GetTime(TIME_MILLISECS)); 70 | //This stuff should be unique to a machine 71 | Tempstr=CatStr(Tempstr, uts.sysname); 72 | Tempstr=CatStr(Tempstr, uts.nodename); 73 | Tempstr=CatStr(Tempstr, uts.machine); 74 | Tempstr=CatStr(Tempstr, uts.release); 75 | Tempstr=CatStr(Tempstr, uts.version); 76 | 77 | 78 | len=HashBytes(RandomBytes, "sha512", Tempstr, StrLen(Tempstr), 0); 79 | if (len > ReqLen) len=ReqLen; 80 | 81 | Destroy(Tempstr); 82 | 83 | return(len); 84 | } 85 | 86 | 87 | int GenerateRandomBytes(char **RetBuff, int ReqLen, int Encoding) 88 | { 89 | int len=0; 90 | char *RandomBytes=NULL; 91 | 92 | RandomBytes=SetStrLen(RandomBytes,ReqLen); 93 | #ifdef HAVE_GETENTROPY 94 | len=GetEntropyFromGetEntropy(RandomBytes, ReqLen); 95 | #endif 96 | if (len==0) len=GetEntropyFromFile("/dev/urandom", RandomBytes, ReqLen); 97 | if (len==0) len=GetEntropyEmergencyFallback(&RandomBytes, ReqLen); 98 | 99 | if (Encoding==0) 100 | { 101 | //don't use CopyStrLen, as 'RandomBytes' can include '\0' 102 | *RetBuff=SetStrLen(*RetBuff, len); 103 | memcpy(*RetBuff, RandomBytes, len); 104 | } 105 | else *RetBuff=EncodeBytes(*RetBuff, RandomBytes, len, Encoding); 106 | 107 | Destroy(RandomBytes); 108 | 109 | return(len); 110 | } 111 | 112 | 113 | 114 | 115 | char *GetRandomData(char *RetStr, int ReqLen, char *AllowedChars) 116 | { 117 | char *Tempstr=NULL; 118 | int i, len; 119 | uint8_t val, max_val; 120 | 121 | max_val=StrLen(AllowedChars); 122 | RetStr=CopyStr(RetStr,""); 123 | len=GenerateRandomBytes(&Tempstr, ReqLen, 0); 124 | 125 | for (i=0; i < len ; i++) 126 | { 127 | val=Tempstr[i]; 128 | RetStr=AddCharToStr(RetStr,AllowedChars[val % max_val]); 129 | } 130 | 131 | 132 | DestroyString(Tempstr); 133 | return(RetStr); 134 | } 135 | 136 | 137 | char *GetRandomHexStr(char *RetBuff, int len) 138 | { 139 | return(GetRandomData(RetBuff,len,HEX_CHARS)); 140 | } 141 | 142 | 143 | char *GetRandomAlphabetStr(char *RetBuff, int len) 144 | { 145 | return(GetRandomData(RetBuff,len,ALPHA_CHARS)); 146 | } 147 | 148 | -------------------------------------------------------------------------------- /Entropy.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_ENTROPY_H 7 | #define LIBUSEFUL_ENTROPY_H 8 | 9 | #include "defines.h" 10 | #include "includes.h" 11 | 12 | //functions related to entropy. Will try using the 'getentropy' function, or else reading from /dev/urandom 13 | //or finally will make a somewhat desperate effort to get entropy from time data 14 | 15 | 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | //Creates a bunch of random bytes using /dev/urandom if available, otherwise falling back to weaker methods 21 | int GenerateRandomBytes(char **RetBuff, int ReqLen, int Encoding); 22 | 23 | //get a hexidecimamlly encoded random string 24 | char *GetRandomHexStr(char *RetBuff, int len); 25 | 26 | //get a random string containing only the characters in 'AllowedChars' 27 | char *GetRandomData(char *RetBuff, int len, char *AllowedChars); 28 | 29 | //get a random string of alphanumeric characters 30 | char *GetRandomAlphabetStr(char *RetBuff, int len); 31 | 32 | 33 | #ifdef __cplusplus 34 | } 35 | #endif 36 | 37 | 38 | #endif 39 | 40 | 41 | -------------------------------------------------------------------------------- /Errors.c: -------------------------------------------------------------------------------- 1 | #include "Errors.h" 2 | #include "includes.h" 3 | #include 4 | 5 | static ListNode *Errors=NULL; 6 | 7 | void ErrorDestroy(void *p_Err) 8 | { 9 | TError *Err; 10 | 11 | Err=(TError *) p_Err; 12 | DestroyString(Err->where); 13 | DestroyString(Err->file); 14 | DestroyString(Err->msg); 15 | free(Err); 16 | } 17 | 18 | 19 | void ErrorsClear() 20 | { 21 | ListDestroy(Errors, ErrorDestroy); 22 | } 23 | 24 | ListNode *ErrorsGet() 25 | { 26 | return(Errors); 27 | } 28 | 29 | 30 | static bool ErrorOutputWanted(int flags) 31 | { 32 | bool result=TRUE; 33 | 34 | //if stderr isn't a tty then don't print, unless ERRFLAG_NOTTY is set 35 | //(this is used to disable this check when we consider syslog debugging too) 36 | if ( 37 | (! (flags & ERRFLAG_NOTTY)) && 38 | (! isatty(2)) 39 | ) 40 | { 41 | if (! LibUsefulGetBool("Error:notty")) result=FALSE; 42 | } 43 | 44 | //if this error is a debug error, then don't print unless either LIBUSEFUL_DEBUG environment variable is set 45 | //or the libUseful:Debug internal value is set 46 | if (flags & ERRFLAG_DEBUG) 47 | { 48 | result=FALSE; 49 | if (StrValid(getenv("LIBUSEFUL_DEBUG"))) result=TRUE; 50 | if (LibUsefulGetBool("libUseful:Debug")) result=TRUE; 51 | } 52 | 53 | return(result); 54 | } 55 | 56 | 57 | void InternalRaiseError(int flags, const char *where, const char *file, int line, const char *FmtStr, ...) 58 | { 59 | char *Tempstr=NULL; 60 | va_list args; 61 | const char *ptr=""; 62 | int errno_save; 63 | ListNode *Curr, *Next;; 64 | uint64_t Now; 65 | TError *Err; 66 | 67 | if (flags & ERRFLAG_CLEAR) ErrorsClear(); 68 | 69 | errno_save=errno; 70 | va_start(args,FmtStr); 71 | Tempstr=VFormatStr(Tempstr,FmtStr,args); 72 | va_end(args); 73 | 74 | if (! Errors) Errors=ListCreate(); 75 | if (flags & ERRFLAG_ERRNO) ptr=strerror(errno_save); 76 | 77 | //first consider if we want to print out a message on stderr 78 | if (ErrorOutputWanted(flags)) 79 | { 80 | if (! LibUsefulGetBool("Error:Silent")) fprintf(stderr,"DEBUG: %s %s:%d %s. %s\n", where, file, line, Tempstr, ptr); 81 | } 82 | 83 | //now consider if we want to syslog an error message. Pass ERRFLAG_NOTTY as it doesn't matter if stderr is not a 84 | //tty for this case. ERRFLAG_NOTTY is a setting here, not at test that uses '&' 85 | if (ErrorOutputWanted(flags | ERRFLAG_NOTTY)) 86 | { 87 | if ((flags & ERRFLAG_SYSLOG) || LibUsefulGetBool("Error:Syslog")) syslog(LOG_ERR,"DEBUG: %s %s:%d %s. %s", where, file, line, Tempstr, ptr); 88 | } 89 | 90 | //if this Error is just debugging, then never add it to the list of errors 91 | if (! (flags & ERRFLAG_DEBUG)) 92 | { 93 | Now=GetTime(TIME_MILLISECS); 94 | Err=(TError *) calloc(1,sizeof(TError)); 95 | Err->errval=errno_save; 96 | Err->when=Now; 97 | Err->where=CopyStr(Err->where, where); 98 | Err->file=CopyStr(Err->file, file); 99 | Err->line=line; 100 | Err->msg=CopyStr(Err->msg, Tempstr); 101 | 102 | Curr=ListInsertItem(Errors, Err); 103 | Curr=ListGetNext(Curr); 104 | while (Curr) 105 | { 106 | Next=ListGetNext(Curr); 107 | Err=(TError *) Curr->Item; 108 | if ((Now - Err->when) > 2000) 109 | { 110 | ListDeleteNode(Curr); 111 | ErrorDestroy(Err); 112 | } 113 | Curr=Next; 114 | } 115 | } 116 | 117 | 118 | if (flags & ERRFLAG_ABORT) 119 | { 120 | abort(); 121 | sleep(1); 122 | syslog(LOG_CRIT,"Still running after attempted abort. possible shenanigans."); 123 | _exit(1); 124 | } 125 | 126 | 127 | DestroyString(Tempstr); 128 | } 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /Expect.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_EXPECT_H 7 | #define LIBUSEFUL_EXPECT_H 8 | 9 | /* 10 | These functions handle 'chat' style dialogues on a STREAM connection. 11 | 12 | Read Stream.h to understand the STREAM object. STREAMS can be pipes to other processes, network connections, etc. 13 | 14 | */ 15 | 16 | 17 | #include "Stream.h" 18 | 19 | #define DIALOG_END 1 20 | #define DIALOG_FAIL 2 21 | #define DIALOG_OPTIONAL 4 22 | #define DIALOG_TIMEOUT 8 23 | 24 | typedef struct 25 | { 26 | int Flags; 27 | int Match; 28 | char *Expect; 29 | char *Reply; 30 | } TExpectDialog; 31 | 32 | 33 | #ifdef __cplusplus 34 | extern "C" { 35 | #endif 36 | 37 | //Consume data from a stream, waiting for it to be silent for 'wait' seconds, then return; 38 | int STREAMExpectSilence(STREAM *S, int wait); 39 | 40 | /* 41 | consume data from a stream, until the string pointed to be 'Expect' is seen. Then send the string 42 | pointed to by 'Reply' and return 43 | */ 44 | int STREAMExpectAndReply(STREAM *S, const char *Expect, const char *Reply); 45 | 46 | /* 47 | Add a Expect/Reply pair to a list (See List.h for details of libUseful lists.) A number of these can be 48 | chained together in the list which is then passed to 'STREAMExpectDialog'. 'STREAMExpectDialog' will 49 | work through the list, expecting to match one Expect/Reply pair after another in a conversation of 50 | 'expect' matches and sent replies. 51 | 52 | The 'Flags' option can have the following values: 53 | 54 | DIALOG_END 55 | If the 'Expect' value is seen, then the dialog has successfully completed. STREAMExpectDialog 56 | will immediately return TRUE, even if there are other items yet to be processed 57 | 58 | DIALOG_FAIL 59 | If the 'Expect' value is seen, then the dialog has failed. STREAMExpectDialog will immedialtely 60 | return FALSE, even if there are other items yet to be processed 61 | 62 | DIALOG_OPTIONAL 63 | If this item isn't seen, but one after it is seen, then skip over this item. 64 | 65 | the list used by STREAMExpectDialog should be destroyed like this: 66 | 67 | ListDestroy(DialogList, ExpectDialogDestroy); 68 | */ 69 | 70 | void ExpectDialogAdd(ListNode *Dialogs, char *Expect, char *Reply, int Flags); 71 | int STREAMExpectDialog(STREAM *S, ListNode *Dialogs, int Timeout); 72 | 73 | void ExpectDialogDestroy(void *Item); 74 | 75 | #ifdef __cplusplus 76 | } 77 | #endif 78 | 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /Gemini.c: -------------------------------------------------------------------------------- 1 | #include "Gemini.h" 2 | #include "URL.h" 3 | 4 | STREAM *GeminiOpen(const char *URL, const char *Config) 5 | { 6 | STREAM *S; 7 | char *Tempstr=NULL, *Token=NULL; 8 | char *Proto=NULL, *Host=NULL, *PortStr=NULL; 9 | const char *ptr; 10 | 11 | ParseURL(URL, &Proto, &Host, &PortStr, NULL, NULL, NULL, NULL); 12 | if (! StrValid(PortStr)) PortStr=CopyStr(PortStr, "1965"); 13 | 14 | Tempstr=MCopyStr(Tempstr, "tls://", Host, ":", PortStr, NULL); 15 | S=STREAMCreate(); 16 | if (STREAMConnect(S, Tempstr, Config)) 17 | { 18 | Tempstr=MCopyStr(Tempstr, URL, "\r\n", NULL); 19 | STREAMWriteLine(Tempstr, S); 20 | STREAMFlush(S); 21 | 22 | Tempstr=STREAMReadLine(Tempstr, S); 23 | ptr=GetToken(Tempstr, "\\S", &Token, 0); 24 | if (StrValid(Token)) 25 | { 26 | STREAMSetValue(S, "gemini:StatusCode", Token); 27 | switch(*Token) 28 | { 29 | case '1': 30 | STREAMSetValue(S, "gemini:Query", ptr); 31 | break; 32 | 33 | case '2': 34 | STREAMSetValue(S, "gemini:ContentType", ptr); 35 | break; 36 | 37 | case '3': 38 | Token=ResolveURL(Token, URL, ptr); 39 | if (! STREAMConnect(S, Token, Config)) 40 | { 41 | STREAMClose(S); 42 | S=NULL; 43 | } 44 | break; 45 | } 46 | } 47 | } 48 | 49 | Destroy(Tempstr); 50 | Destroy(Token); 51 | Destroy(PortStr); 52 | Destroy(Proto); 53 | Destroy(Host); 54 | 55 | return(S); 56 | } 57 | -------------------------------------------------------------------------------- /Gemini.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | //provides support for the gemini protocol. you would normally not use 7 | //this function, but instead S=STREAMOpen("gemini://myhost","r"); 8 | 9 | #ifndef LIBUSEFUL_GEMINI_H 10 | #define LIBUSEFUL_GEMINI_H 11 | 12 | #include "Stream.h" 13 | 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | 20 | STREAM *GeminiOpen(const char *URL, const char *Config); 21 | 22 | #ifdef __cplusplus 23 | } 24 | #endif 25 | 26 | 27 | 28 | #endif 29 | 30 | 31 | -------------------------------------------------------------------------------- /GeneralFunctions.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_GENERAL_H 7 | #define LIBUSEFUL_GENERAL_H 8 | 9 | #include 10 | #include "defines.h" 11 | #include "includes.h" 12 | 13 | /* 14 | A number of general functions that don't fit anywhere else 15 | */ 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | //Destroy an allocated object. Will not crash if passed NULL. 22 | void Destroy(void *Obj); 23 | 24 | //reverse bytes within a uint32, There doesn't seem to be a POSIX function for this, 25 | //hence this one. 26 | uint32_t reverse_uint32(uint32_t Input); 27 | 28 | //take a string of up to 8 '1' and '0' characters and convert them to an integer value 29 | uint8_t parse_bcd_byte(const char *In); 30 | 31 | //encoded bytes into a string of '1' or '0' characters 32 | char *encode_bcd_bytes(char *RetStr, unsigned const char *Bytes, int Len); 33 | 34 | //fill 'size' bytes pointed to by 'Str' with char 'fill'. 'Str' is treated as a volatile, which is intended to prevent 35 | //the compiler from optimizing this function out. Use this function to blank memory holding sensitive information, as 36 | //the compiler might decide that blanking memory before freeing it serves no purpose and will this optimize the 37 | //function out. 'volatile' should prevent this. 38 | void xmemset(volatile char *Str, char fill, off_t size); 39 | 40 | //setenv that returns TRUE or FALSE rather than returning 0 on success 41 | int xsetenv(const char *Name, const char *Value); 42 | 43 | //increment a char * by 'count' but DO NOT GO PAST A NULL CHARACTER. Returns number of bytes actually incremented 44 | int ptr_incr(const char **ptr, int count); 45 | 46 | 47 | const char *traverse_until(const char *ptr, char terminator); 48 | 49 | //treat the first character pointed to by 'ptr' as a quote character. Traverse the string until a matching character is 50 | //found, then return the character after that. This function ignores characters if they are quoted with a preceeding 51 | //'\' character. 52 | const char *traverse_quoted(const char *ptr); 53 | 54 | 55 | 56 | //Add item to a comma seperated list. If the new item is not the first Item in the list, then a comma will be 57 | //placed before it 58 | 59 | //e.g. CSV=CommaList(CSV, "this") 60 | // CSV=CommaList(CSV, "that") 61 | // printf("%s\n",CSV); //this,that 62 | char *CommaList(char *RetStr, const char *AddStr); 63 | 64 | 65 | #define SHELLSAFE_BLANK 1 66 | #define SHELLSAFE_REPORT 2 67 | #define SHELLSAFE_ABORT 4 68 | 69 | // quote or blank out characters that are used to run unintended shell commands. 70 | // if 'Flags' includes 'SHELLSAFE_BLANK' then such characters are replaced with ' ', otherwise they are quoted with '\' 71 | // if 'Flags' includes 'SHELLSAFE_REPORT' then a syslog message is sent if any unsafe chars are found in the string 72 | char *MakeShellSafeString(char *RetStr, const char *String, int Flags); 73 | 74 | //remap one fd to another. e.g. change stdin, stdout or stderr to point to a different fd 75 | int fd_remap(int fd, int newfd); 76 | 77 | //open a file, and remap it to fd ONLY if it opened successfully 78 | int fd_remap_path(int fd, const char *Path, int Flags); 79 | 80 | 81 | //given a key generate a hash value using the fnv method. Then mod this value by NoOfItems and return result. 82 | //This allows items to be mapped to values with a good spread, and is used internally by the 'Map' datastructure 83 | unsigned int fnv_hash(unsigned const char *key, int NoOfItems); 84 | 85 | #ifdef __cplusplus 86 | } 87 | #endif 88 | 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /HMAC.c: -------------------------------------------------------------------------------- 1 | #include "HMAC.h" 2 | 3 | int HMACBlockSize(const char *Type) 4 | { 5 | const char *ptr; 6 | 7 | if (StrValid(Type)) 8 | { 9 | if (strncasecmp(Type, "hmac-",5)==0) ptr=Type+5; 10 | else ptr=Type; 11 | 12 | if (strcasecmp(ptr, "md4")==0) return(64); 13 | if (strcasecmp(ptr, "md5")==0) return(64); 14 | if (strcasecmp(ptr, "sha")==0) return(64); 15 | if (strcasecmp(ptr, "sha1")==0) return(64); 16 | if (strcasecmp(ptr, "sha224")==0) return(64); 17 | if (strcasecmp(ptr, "sha256")==0) return(64); 18 | } 19 | 20 | return(128); 21 | } 22 | 23 | 24 | void HMACUpdate(HASH *HMAC, const char *Data, int Len) 25 | { 26 | HASH *Hash; 27 | 28 | Hash=(HASH *) HMAC->Ctx; 29 | Hash->Update(Hash,Data,Len); 30 | } 31 | 32 | 33 | 34 | int HMACFinish(HASH *HMAC, char **HashStr) 35 | { 36 | HASH *Hash; 37 | int len, result, BlockSize; 38 | 39 | 40 | BlockSize=HMACBlockSize(HMAC->Type); 41 | Hash=(HASH *) HMAC->Ctx; 42 | 43 | //We've done with this now, blank it and reuse for the inner result 44 | HMAC->Key1=CopyStr(HMAC->Key1,""); 45 | len=Hash->Finish(Hash,&HMAC->Key1); 46 | 47 | HMAC->Key2=SetStrLen(HMAC->Key2,BlockSize+len); 48 | memcpy(HMAC->Key2+BlockSize,HMAC->Key1,len); 49 | 50 | //Hash->Type 51 | result=HashBytes(HashStr, Hash->Type, HMAC->Key2, BlockSize+len, ENCODE_NONE); 52 | 53 | return(result); 54 | } 55 | 56 | 57 | void HMACPrepare(HASH *HMAC, const char *Data, int Len) 58 | { 59 | int i, BlockSize; 60 | char *Key=NULL, *Tempstr=NULL; 61 | 62 | //Whatever we've been given as a key, we have to turn it into a 63 | //key of 'HMAC_BLOCKSIZE', either by hashing it to make it shorter 64 | //or by padding with NULLS 65 | BlockSize=HMACBlockSize(HMAC->Type); 66 | Key=SetStrLen(Key, BlockSize); 67 | memset(Key,0, BlockSize); 68 | 69 | if (Len > BlockSize) 70 | { 71 | HMAC->Key1Len=HashBytes(&Tempstr,HMAC->Type,HMAC->Key1,HMAC->Key1Len,0); 72 | memcpy(Key,Tempstr,HMAC->Key1Len); 73 | } 74 | else 75 | { 76 | memcpy(Key,HMAC->Key1,HMAC->Key1Len); 77 | } 78 | 79 | HMAC->Key1=SetStrLen(HMAC->Key1,BlockSize); 80 | HMAC->Key2=SetStrLen(HMAC->Key2,BlockSize); 81 | HMAC->Key1Len=BlockSize; 82 | HMAC->Key2Len=BlockSize; 83 | 84 | for (i=0; i < BlockSize; i++) 85 | { 86 | //inner key 87 | HMAC->Key1[i]=Key[i] ^ 0x36; 88 | //outer key 89 | HMAC->Key2[i]=Key[i] ^ 0x5c; 90 | } 91 | 92 | 93 | //first thing to be hashed is the inner key, then data is 'concatted' onto it 94 | HMACUpdate(HMAC, HMAC->Key1, HMAC->Key1Len); 95 | HMACUpdate(HMAC, Data, Len); 96 | HMAC->Update=HMACUpdate; 97 | 98 | DestroyString(Tempstr); 99 | DestroyString(Key); 100 | } 101 | 102 | 103 | HASH *HMACInit(const char *Type) 104 | { 105 | HASH *Hash; 106 | const char *ptr; 107 | 108 | Hash=(HASH *) calloc(1, sizeof(HASH)); 109 | if (strncasecmp(Type, "hmac-", 5)==0) ptr=Type+5; 110 | else ptr=Type; 111 | Hash->Ctx=(void *) HashInit(ptr); 112 | Hash->Type=MCopyStr(Hash->Type, "hmac-", ptr, NULL); 113 | Hash->Update=HMACPrepare; 114 | Hash->Finish=HMACFinish; 115 | 116 | return(Hash); 117 | } 118 | 119 | 120 | void HMACSetKey(HASH *HMAC, const char *Key, int Len) 121 | { 122 | HMAC->Key1=SetStrLen(HMAC->Key1,Len); 123 | memcpy(HMAC->Key1,Key,Len); 124 | HMAC->Key1Len=Len; 125 | } 126 | 127 | void HMACDestroy(void *p_HMAC) 128 | { 129 | HASH *HMAC; 130 | 131 | HMAC=(HASH *) p_HMAC; 132 | HashDestroy(HMAC->Ctx); 133 | HMAC->Ctx=NULL; 134 | HashDestroy(HMAC); 135 | } 136 | 137 | 138 | int HMACBytes(char **RetStr, const char *Type, const char *Key, int KeyLen, const char *Data, int DataLen, int Encoding) 139 | { 140 | HASH *Hash; 141 | char *Tempstr=NULL; 142 | int result; 143 | 144 | Hash=HMACInit(Type); 145 | HMACSetKey(Hash, Key, KeyLen); 146 | HMACPrepare(Hash, Data, DataLen); 147 | 148 | if (Encoding > 0) 149 | { 150 | result=HMACFinish(Hash, &Tempstr); 151 | *RetStr=EncodeBytes(*RetStr, Tempstr, result, Encoding); 152 | } 153 | else result=HMACFinish(Hash, RetStr); 154 | HMACDestroy(Hash); 155 | 156 | return(result); 157 | } 158 | 159 | -------------------------------------------------------------------------------- /HMAC.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_HMAC_H 7 | #define LIBUSEFUL_HMAC_H 8 | 9 | #include "Hash.h" 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | void HMACUpdate(HASH *HMAC, const char *Data, int Len); 16 | int HMACFinish(HASH *HMAC, char **HashStr); 17 | void HMACPrepare(HASH *HMAC, const char *Data, int Len); 18 | HASH *HMACInit(const char *Type); 19 | void HMACSetKey(HASH *HMAC, const char *Key, int Len); 20 | void HMACDestroy(void *p_HMAC); 21 | int HMACBytes(char **RetStr, const char *Type, const char *Key, int KeyLen, const char *Data, int DataLen, int Encoding); 22 | 23 | 24 | #ifdef __cplusplus 25 | } 26 | #endif 27 | 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /Hash.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_HASH_H 7 | #define LIBUSEFUL_HASH_H 8 | 9 | /* Hashing functions. Mostly you'll use: 10 | 11 | len=HashBytes(&Hashed, "md5", "string to hash", 14, ENCODE_HEX); 12 | 13 | or 14 | 15 | len=HashFile(&Hashed, "sha1", "/tmp/filetohash.txt", ENCODE_BASE64); 16 | 17 | You can get a list of available hash types with HashAvailableTypes. This should be MD5, various SHA variants, whirlpool, and variants of the jh hash 18 | from Dr Hongjun Wu. More hash algorithms will likely be added in future. 19 | 20 | 21 | if you need more granulated control of hashing, then it's done like this 22 | 23 | Hash=HashInit("md5"); 24 | S=STREAMOpen("/tmp/testfile.txt","r"); 25 | result=STREAMReadBytes(S, Buffer BUFSIZ); 26 | while (result > 0) 27 | { 28 | HashUpdate(Hash, Buffer, result); 29 | result=STREAMReadBytes(S, Buffer BUFSIZ); 30 | } 31 | len=HashFinish(Hash, ENCODE_BASE64, HashStr); 32 | 33 | printf("Hash was: %s\n",HashStr); 34 | 35 | */ 36 | 37 | 38 | 39 | //if you load Hash.h you'll want Encodings.h too 40 | #include "Encodings.h" 41 | #include "Stream.h" 42 | #include "includes.h" 43 | 44 | #define HashUpdate(Hash, text, len) (Hash->Update(Hash, text, len)) 45 | 46 | 47 | #ifdef __cplusplus 48 | extern "C" { 49 | #endif 50 | 51 | typedef struct t_hash HASH; 52 | 53 | typedef int (*HASH_INIT_FUNC)(HASH *Hash, const char *Name, int Bits); 54 | typedef void (*HASH_UPDATE_FUNC)(HASH *Hash, const char *Data, int DataLen); 55 | typedef HASH *(*HASH_CLONE_FUNC)(HASH *Hash); 56 | typedef int (*HASH_FINISH_FUNC)(HASH *Hash, char **RetStr); 57 | 58 | struct t_hash 59 | { 60 | char *Type; 61 | //this is a placeholder used only by classlibraries for scripting langauges 62 | int Encoding; 63 | char *Key1; 64 | unsigned int Key1Len; 65 | char *Key2; 66 | unsigned int Key2Len; 67 | void *Ctx; 68 | HASH_INIT_FUNC Init; 69 | HASH_UPDATE_FUNC Update; 70 | HASH_FINISH_FUNC Finish; 71 | HASH_CLONE_FUNC Clone; 72 | }; 73 | 74 | 75 | //this function is used internally to register a hash type 76 | void HashRegister(const char *Name, int Len, HASH_INIT_FUNC Init); 77 | 78 | //for backwards compatiblity provide this function. It just calls'EncodingParse' 79 | int HashEncodingFromStr(const char *Str); 80 | 81 | //produce a comma separated list of available hash types. This can include hash-names from external sources like openssl. 82 | char *HashAvailableTypes(char *RetStr); 83 | 84 | 85 | HASH *HashInit(const char *Type); 86 | int HashFinish(HASH *Hash, int Encoding, char **Return); 87 | void HashDestroy(HASH *Hash); 88 | int HashBytes(char **Return, const char *Type, const char *text, int len, int Encoding); 89 | int HashBytes2(const char *Type, int Encoding, const char *text, int len, char **RetStr); 90 | 91 | //read from a stream (usually a file) and return the hash of it's contents 92 | int HashSTREAM(char **Return, const char *Type, STREAM *S, int Encoding); 93 | 94 | //hash a file at 'Path' 95 | int HashFile(char **Return, const char *Type, const char *Path, int Encoding); 96 | int PBK2DF2(char **Return, const char *Type, const char *Bytes, int Len, const char *Salt, int SaltLen, uint32_t Rounds, int Encoding); 97 | 98 | #ifdef __cplusplus 99 | } 100 | #endif 101 | 102 | 103 | 104 | #endif 105 | -------------------------------------------------------------------------------- /HashCRC32.c: -------------------------------------------------------------------------------- 1 | #include "HashCRC32.h" 2 | #include "crc32.h" 3 | 4 | void HashUpdateCRC(HASH *Hash, const char *Data, int Len) 5 | { 6 | #ifndef USE_LGPL 7 | crc32Update((unsigned long *) Hash->Ctx, (unsigned char *) Data, Len); 8 | #endif 9 | } 10 | 11 | 12 | HASH *HashCloneCRC(HASH *Hash) 13 | { 14 | HASH *NewHash=NULL; 15 | 16 | #ifndef USE_LGPL 17 | NewHash=(HASH *) calloc(1,sizeof(HASH)); 18 | NewHash->Type=CopyStr(NewHash->Type,Hash->Type); 19 | NewHash->Ctx=(void *) calloc(1,sizeof(unsigned long)); 20 | memcpy(NewHash->Ctx, Hash->Ctx, sizeof(unsigned long)); 21 | #endif 22 | 23 | return(NewHash); 24 | } 25 | 26 | 27 | int HashFinishCRC(HASH *Hash, char **HashStr) 28 | { 29 | int len=0; 30 | 31 | #ifndef USE_LGPL 32 | unsigned long crc; 33 | 34 | *HashStr=CopyStr(*HashStr, ""); 35 | len=sizeof(unsigned long); 36 | crc32Finish((unsigned long *) Hash->Ctx); 37 | crc=htonl(* (unsigned long *) Hash->Ctx); 38 | 39 | *HashStr=SetStrLen(*HashStr,len); 40 | memcpy(*HashStr,&crc,len); 41 | #endif 42 | 43 | return(len); 44 | } 45 | 46 | 47 | int HashInitCRC(HASH *Hash, const char *Name, int Len) 48 | { 49 | #ifndef USE_LGPL 50 | Hash->Ctx=(void *) calloc(1,sizeof(unsigned long)); 51 | if (Hash->Ctx) 52 | { 53 | crc32Init((unsigned long *) Hash->Ctx); 54 | Hash->Update=HashUpdateCRC; 55 | Hash->Finish=HashFinishCRC; 56 | Hash->Clone=HashCloneCRC; 57 | return(TRUE); 58 | } 59 | #endif 60 | 61 | return(FALSE); 62 | } 63 | 64 | void HashRegisterCRC32() 65 | { 66 | #ifndef USE_LGPL 67 | HashRegister("crc32", 32, HashInitCRC); 68 | #endif 69 | } 70 | -------------------------------------------------------------------------------- /HashCRC32.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_HASH_CRC32_H 7 | #define LIBUSEFUL_HASH_CRC32_H 8 | 9 | #include "Hash.h" 10 | 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | 17 | void HashRegisterCRC32(); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /HashJH.c: -------------------------------------------------------------------------------- 1 | #include "HashJH.h" 2 | 3 | #ifdef USE_JH 4 | 5 | #include "jh_ref.h" 6 | 7 | int HashFinishJH(HASH *Hash, char **HashStr) 8 | { 9 | int len; 10 | char *DigestBuff=NULL; 11 | 12 | DigestBuff=(char *) calloc(1,1024); 13 | 14 | len=JHFinal((hashState *) Hash->Ctx, (unsigned char *) DigestBuff); 15 | *HashStr=SetStrLen(*HashStr,len); 16 | memcpy(*HashStr,DigestBuff,len); 17 | 18 | DestroyString(DigestBuff); 19 | 20 | return(len); 21 | } 22 | 23 | 24 | 25 | void HashUpdateJH(HASH *Hash, const char *Data, int Len) 26 | { 27 | JHUpdate( (hashState *) Hash->Ctx, (unsigned char *) Data, Len); 28 | } 29 | 30 | 31 | HASH *HashCloneJH(HASH *Hash) 32 | { 33 | HASH *NewHash; 34 | 35 | NewHash=(HASH *) calloc(1,sizeof(HASH)); 36 | NewHash->Type=CopyStr(NewHash->Type,Hash->Type); 37 | NewHash->Ctx=(void *) calloc(1,sizeof(hashState *)); 38 | memcpy(NewHash->Ctx, Hash->Ctx, sizeof(hashState *)); 39 | 40 | return(NewHash); 41 | } 42 | 43 | #endif 44 | 45 | 46 | int HashInitJH(HASH *Hash, const char *Name, int Length) 47 | { 48 | #ifdef USE_JH 49 | switch (Length) 50 | { 51 | case 224: 52 | case 256: 53 | case 384: 54 | case 512: 55 | Hash->Ctx=(void *) calloc(1,sizeof(hashState)); 56 | JHInit((hashState *) Hash->Ctx, Length); 57 | Hash->Update=HashUpdateJH; 58 | Hash->Finish=HashFinishJH; 59 | Hash->Clone=HashCloneJH; 60 | return(TRUE); 61 | break; 62 | 63 | } 64 | #endif 65 | 66 | return(FALSE); 67 | } 68 | 69 | 70 | void HashRegisterJH() 71 | { 72 | #ifdef USE_JH 73 | HashRegister("jh224", 224, HashInitJH); 74 | HashRegister("jh256", 256, HashInitJH); 75 | HashRegister("jh384", 384, HashInitJH); 76 | HashRegister("jh512", 512, HashInitJH); 77 | HashRegister("jh-224", 224, HashInitJH); 78 | HashRegister("jh-256", 256, HashInitJH); 79 | HashRegister("jh-384", 384, HashInitJH); 80 | HashRegister("jh-512", 512, HashInitJH); 81 | #endif 82 | } 83 | -------------------------------------------------------------------------------- /HashJH.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_HASH_JH5_H 7 | #define LIBUSEFUL_HASH_JH5_H 8 | 9 | 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | 16 | #include "Hash.h" 17 | 18 | void HashRegisterJH(); 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | 24 | 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /HashMD5.c: -------------------------------------------------------------------------------- 1 | #include "HashMD5.h" 2 | 3 | #ifdef USE_MD5 4 | #include "md5.h" 5 | #define MD5LEN 16 6 | 7 | void HashUpdateMD5(HASH *Hash, const char *Data, int Len) 8 | { 9 | MD5Update((MD5_CTX *) Hash->Ctx, (const unsigned char *) Data, Len); 10 | } 11 | 12 | 13 | HASH *HashCloneMD5(HASH *Hash) 14 | { 15 | HASH *NewHash; 16 | 17 | NewHash=(HASH *) calloc(1,sizeof(HASH)); 18 | NewHash->Type=CopyStr(NewHash->Type,Hash->Type); 19 | NewHash->Ctx=(void *) calloc(1,sizeof(MD5_CTX)); 20 | memcpy(NewHash->Ctx, Hash->Ctx, sizeof(MD5_CTX)); 21 | NewHash->Update=Hash->Update; 22 | NewHash->Finish=Hash->Finish; 23 | NewHash->Clone=Hash->Clone; 24 | 25 | return(NewHash); 26 | } 27 | 28 | 29 | int HashFinishMD5(HASH *Hash, char **HashStr) 30 | { 31 | int len; 32 | char *DigestBuff=NULL; 33 | 34 | DigestBuff=(char *) calloc(1,MD5LEN+1); 35 | MD5Final((unsigned char *) DigestBuff, (MD5_CTX *) Hash->Ctx); 36 | 37 | len=MD5LEN; 38 | *HashStr=SetStrLen(*HashStr,len); 39 | memcpy(*HashStr,DigestBuff,len); 40 | 41 | DestroyString(DigestBuff); 42 | 43 | return(len); 44 | } 45 | #endif 46 | 47 | 48 | int HashInitMD5(HASH *Hash, const char *Name, int Len) 49 | { 50 | #ifdef USE_MD5 51 | Hash->Ctx=(void *) calloc(1,sizeof(MD5_CTX)); 52 | MD5Init((MD5_CTX *) Hash->Ctx); 53 | Hash->Update=HashUpdateMD5; 54 | Hash->Finish=HashFinishMD5; 55 | Hash->Clone=HashCloneMD5; 56 | 57 | return(TRUE); 58 | #else 59 | return(FALSE); 60 | #endif 61 | } 62 | 63 | 64 | void HashRegisterMD5() 65 | { 66 | #ifdef USE_MD5 67 | HashRegister("md5", 0, HashInitMD5); 68 | #endif 69 | } 70 | -------------------------------------------------------------------------------- /HashMD5.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_HASH_MD5_H 7 | #define LIBUSEFUL_HASH_MD5_H 8 | 9 | 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | 16 | #include "Hash.h" 17 | 18 | void HashRegisterMD5(); 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | 24 | 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /HashOpenSSL.c: -------------------------------------------------------------------------------- 1 | #include "HashOpenSSL.h" 2 | 3 | #ifdef HAVE_LIBSSL 4 | #include 5 | #include 6 | 7 | static void OpenSSLFreeHashCTX(HASH *Hash) 8 | { 9 | #ifdef HAVE_EVP_MD_CTX_FREE 10 | EVP_MD_CTX_free(Hash->Ctx); 11 | #else 12 | EVP_MD_CTX_destroy(Hash->Ctx); 13 | #endif 14 | 15 | Hash->Ctx=NULL; 16 | } 17 | 18 | 19 | static int OpenSSLFinishHash(HASH *Hash, char **Digest) 20 | { 21 | unsigned int Len; 22 | 23 | *Digest=SetStrLen(*Digest, EVP_MAX_MD_SIZE); 24 | EVP_DigestFinal((EVP_MD_CTX *) Hash->Ctx, (unsigned char *) *Digest, &Len); 25 | OpenSSLFreeHashCTX(Hash); 26 | 27 | return((int) Len); 28 | } 29 | 30 | 31 | static void OpenSSLUpdateHash(HASH *Hash, const char *Bytes, int Len) 32 | { 33 | EVP_DigestUpdate((EVP_MD_CTX *) Hash->Ctx, Bytes, Len); 34 | } 35 | 36 | static int OpenSSLInitHash(HASH *Hash, const char *Name, int Size) 37 | { 38 | const EVP_MD *MD; 39 | const char *p_Name; 40 | 41 | p_Name=Name; 42 | if (strncmp(p_Name, "openssl:", 8)==0) p_Name += 8; 43 | MD=EVP_get_digestbyname(p_Name); 44 | if (MD) 45 | { 46 | #ifdef HAVE_EVP_MD_CTX_NEW 47 | Hash->Ctx=(EVP_MD_CTX *) EVP_MD_CTX_new(); 48 | #else 49 | Hash->Ctx=(EVP_MD_CTX *) EVP_MD_CTX_create(); 50 | #endif 51 | 52 | if (! EVP_DigestInit(Hash->Ctx, MD)) 53 | { 54 | OpenSSLFreeHashCTX(Hash); 55 | return(FALSE); 56 | } 57 | 58 | Hash->Update=OpenSSLUpdateHash; 59 | Hash->Finish=OpenSSLFinishHash; 60 | 61 | return(TRUE); 62 | } 63 | return(FALSE); 64 | } 65 | 66 | //this function gets 'called back' by the call to 'OBJ_NAME_do_all' in HashRegisterOpenSSL 67 | //and is called for each algorithm name that openssl supports 68 | static void OpenSSLDigestCallback(const OBJ_NAME *obj, void *arg) 69 | { 70 | char *Tempstr=NULL; 71 | HASH *Hash; 72 | 73 | Hash=(HASH *) calloc(1, sizeof(HASH)); 74 | if (OpenSSLInitHash(Hash, obj->name, 0)) 75 | { 76 | HashRegister(obj->name, 0, OpenSSLInitHash); 77 | Tempstr=MCopyStr(Tempstr, "openssl:", obj->name, NULL); 78 | HashRegister(Tempstr, 0, OpenSSLInitHash); 79 | } 80 | OpenSSLFreeHashCTX(Hash); 81 | 82 | Destroy(Tempstr); 83 | } 84 | #endif 85 | 86 | void HashRegisterOpenSSL() 87 | { 88 | #ifdef HAVE_LIBSSL 89 | OpenSSL_add_all_digests(); //make sure they're loaded 90 | OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH, OpenSSLDigestCallback, NULL); 91 | #endif 92 | } 93 | -------------------------------------------------------------------------------- /HashOpenSSL.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_HASH_OPENSSL_H 7 | #define LIBUSEFUL_HASH_OPENSSL_H 8 | 9 | 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | 16 | #include "Hash.h" 17 | 18 | void HashRegisterOpenSSL(); 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | 24 | 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /HashSHA.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_HASH_SHA_H 7 | #define LIBUSEFUL_HASH_SHA_H 8 | 9 | 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | 16 | #include "Hash.h" 17 | 18 | void HashRegisterSHA(); 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | 24 | 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /HashWhirlpool.c: -------------------------------------------------------------------------------- 1 | #include "HashWhirlpool.h" 2 | 3 | #ifdef USE_WHIRL 4 | #include "whirlpool.h" 5 | 6 | int HashFinishWhirlpool(HASH *Hash, char **HashStr) 7 | { 8 | int len; 9 | char *DigestBuff=NULL; 10 | 11 | DigestBuff=(char *) calloc(1,WHIRLPOOL_DIGESTBYTES+1); 12 | WHIRLPOOLfinalize((WHIRLPOOLstruct *) Hash->Ctx, (unsigned char *) DigestBuff); 13 | 14 | len=WHIRLPOOL_DIGESTBYTES; 15 | *HashStr=SetStrLen(*HashStr,len); 16 | memcpy(*HashStr,DigestBuff,len); 17 | 18 | DestroyString(DigestBuff); 19 | 20 | return(len); 21 | } 22 | 23 | 24 | void HashUpdateWhirlpool(HASH *Hash, const char *Data, int Len) 25 | { 26 | WHIRLPOOLadd((unsigned char *) Data, Len * 8, (WHIRLPOOLstruct *) Hash->Ctx); 27 | } 28 | 29 | 30 | HASH *HashCloneWhirlpool(HASH *Hash) 31 | { 32 | HASH *NewHash; 33 | 34 | NewHash=(HASH *) calloc(1,sizeof(HASH)); 35 | NewHash->Type=CopyStr(NewHash->Type,Hash->Type); 36 | NewHash->Ctx=(void *) calloc(1,sizeof(WHIRLPOOLstruct *)); 37 | memcpy(NewHash->Ctx, Hash->Ctx, sizeof(WHIRLPOOLstruct *)); 38 | 39 | return(NewHash); 40 | } 41 | 42 | #endif 43 | 44 | int HashInitWhirlpool(HASH *Hash, const char *Name, int Len) 45 | { 46 | #ifdef USE_WHIRL 47 | Hash->Ctx=(void *) calloc(1,sizeof(WHIRLPOOLstruct)); 48 | WHIRLPOOLinit((WHIRLPOOLstruct *) Hash->Ctx); 49 | Hash->Update=HashUpdateWhirlpool; 50 | Hash->Finish=HashFinishWhirlpool; 51 | Hash->Clone=HashCloneWhirlpool; 52 | return(TRUE); 53 | #else 54 | return(FALSE); 55 | #endif 56 | } 57 | 58 | void HashRegisterWhirlpool() 59 | { 60 | #ifdef USE_WHIRL 61 | HashRegister("whirl", 0, HashInitWhirlpool); 62 | HashRegister("whirlpool", 0, HashInitWhirlpool); 63 | #endif 64 | } 65 | -------------------------------------------------------------------------------- /HashWhirlpool.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_HASH_WHIRL_H 7 | #define LIBUSEFUL_HASH_WHIRL_H 8 | 9 | 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | 16 | #include "Hash.h" 17 | 18 | void HashRegisterWhirlpool(); 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | 24 | 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /HttpChunkedTransfer.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | //These functions relate to adding a 'Data processor' to the stream that 7 | //will decode chunked HTTP transfers. This is an automatic component of 8 | //HTTP Streams, and thus the user normally doesn't need to use or know about 9 | //this module 10 | 11 | 12 | #ifndef LIBUSEFUL_HTTP_CHUNKED_H 13 | #define LIBUSEFUL_HTTP_CHUNKED_H 14 | 15 | #include "includes.h" 16 | #include "defines.h" 17 | #include "Stream.h" 18 | 19 | 20 | 21 | #ifdef __cplusplus 22 | extern "C" { 23 | #endif 24 | 25 | void HTTPAddChunkedProcessor(STREAM *S); 26 | 27 | 28 | #ifdef __cplusplus 29 | } 30 | #endif 31 | 32 | 33 | #endif 34 | 35 | -------------------------------------------------------------------------------- /HttpServer.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_HTTP_SERVER_H 7 | #define LIBUSEFUL_HTTP_SERVER_H 8 | 9 | #include "Stream.h" 10 | #include "Vars.h" 11 | 12 | /* 13 | Support for very basic in-app http servers. 14 | Usage is: 15 | 16 | Serv=STREAMServerNew("http:127.0.0.1:8080", ""); 17 | S=STREAMServerAccept(Serv); 18 | if (S) 19 | { 20 | if (strcmp(STREAMGetValue("HTTP:URL"), "/test")==0) 21 | { 22 | HTTPSendHeaders(S, 200, "OKAY", "X-Test-Header=test"); 23 | STREAMWriteLine("testing 123", S); 24 | STREAMClose(S); 25 | } 26 | } 27 | 28 | 29 | STREAMServerAccept handles the HTTP handshake and sets the following variables 30 | 31 | HTTP:Method HTTP Method used (GET, PUT, POST etc) 32 | HTTP:URL Requested url 33 | Cookie list of supplied cookies in format name=value;name=value 34 | Auth:Basic base64 encoded username:password details 35 | Auth:Bearer oauth 'access token' or other unique secret 36 | WEBSOCKET:KEY 'Key' Used in the weboscket protocol, the programmer does not normally need to know about this 37 | WEBSOCKET:PROTOCOL Requested websockets protocol, can be used to support multiple websocket subprotocols at the same url 38 | HTTP:Upgrade Will be set to 'websocket' if client asked to switch to websockets 39 | HTTP:
all other headers in request 40 | 41 | These can then be processed by the main program. HTTPSendHeaders is used to send back reply 42 | headers, and then other data can be written to the stream. 43 | 44 | Two convienience functions, HTTPSendDocument and HTTPSendFile allow the user to send headers and a document 45 | or the contents of a file at a given path. These functions wrap HTTPSendHeaders, so that doesn't need to 46 | be used with them. Both have an optional 'content-type' argument, but if this is blank or null then 47 | HTTPSendFile will try to guess the content-type of a file using the file extension. 48 | 49 | Authentication can be handled by one of the following methods 50 | 51 | ip:
- IP address of remote host matches one in the list 52 | cookie: - HTTP cookie is set to value 53 | 54 | Serv=STREAMServerNew("http://127.0.0.1:4040", "rw auth='password-file:/tmp/test.pw'"); 55 | Connections=ListCreate(); 56 | ListAddItem(Connections, Serv); 57 | 58 | while (1) 59 | { 60 | STREAMSelect(Connections, NULL); 61 | S=STREAMServerAccept(Serv); 62 | if (! STREAMIsAuth(S)) HTTPServerSendHeaders(S, 401, "Authentication Required", "WWW-Authenticate=Basic"); 63 | else 64 | { 65 | 66 | */ 67 | 68 | 69 | 70 | 71 | #ifdef __cplusplus 72 | extern "C" { 73 | #endif 74 | 75 | 76 | void HTTPServerParseClientCookies(ListNode *Vars, const char *Str); 77 | void HTTPServerParseAuthorization(ListNode *Vars, const char *Str); 78 | void HTTPServerParseClientHeaders(STREAM *S); 79 | void HTTPServerSendHeaders(STREAM *S, int ResponseCode, const char *ResponseText, const char *Headers); 80 | void HTTPServerAccept(STREAM *S); 81 | 82 | int HTTPServerSendResponse(STREAM *S, const char *ResponseCode, const char *ResponseReason, const char *Content, int Length, const char *ContentType, const char *Headers); 83 | int HTTPServerSendDocument(STREAM *S, const char *Content, int Length, const char *ContentType, const char *Headers); 84 | int HTTPServerSendStatus(STREAM *S, const char *ErrorCode, const char *ErrorReason); 85 | int HTTPServerSendDocument(STREAM *S, const char *Bytes, int Length, const char *ContentType, const char *Headers); 86 | int HTTPServerSendFile(STREAM *S, const char *Path, const char *ContentType, const char *Headers); 87 | 88 | #ifdef __cplusplus 89 | } 90 | #endif 91 | 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /HttpUtil.c: -------------------------------------------------------------------------------- 1 | #include "HttpUtil.h" 2 | #include "Encodings.h" 3 | 4 | 5 | void HTTPDecodeBasicAuth(const char *Auth, char **UserName, char **Password) 6 | { 7 | char *Tempstr=NULL; 8 | const char *ptr; 9 | 10 | Tempstr=DecodeToText(Tempstr, Auth, ENCODE_BASE64); 11 | ptr=GetToken(Tempstr, ":", UserName, 0); 12 | ptr=GetToken(ptr, ":", Password, 0); 13 | 14 | Destroy(Tempstr); 15 | } 16 | 17 | 18 | char *HTTPUnQuote(char *RetStr, const char *Str) 19 | { 20 | char *Token=NULL; 21 | const char *ptr; 22 | int olen=0, ilen; 23 | 24 | RetStr=CopyStr(RetStr,""); 25 | ilen=StrLen(Str); 26 | 27 | for (ptr=Str; ptr < (Str+ilen); ptr++) 28 | { 29 | switch (*ptr) 30 | { 31 | case '+': 32 | RetStr=AddCharToBuffer(RetStr,olen,' '); 33 | olen++; 34 | break; 35 | 36 | case '%': 37 | ptr++; 38 | Token=CopyStrLen(Token,ptr,2); 39 | ptr++; //not +=2, as we will increment again 40 | RetStr=AddCharToBuffer(RetStr,olen,strtol(Token,NULL,16) & 0xFF); 41 | olen++; 42 | break; 43 | 44 | default: 45 | RetStr=AddCharToBuffer(RetStr,olen,*ptr); 46 | olen++; 47 | break; 48 | } 49 | 50 | } 51 | 52 | StrLenCacheAdd(RetStr, olen); 53 | 54 | DestroyString(Token); 55 | return(RetStr); 56 | } 57 | 58 | 59 | char *HTTPQuoteChars(char *RetStr, const char *Str, const char *CharList) 60 | { 61 | char *Token=NULL; 62 | const char *ptr; 63 | int olen=0, ilen; 64 | 65 | RetStr=CopyStr(RetStr,""); 66 | ilen=StrLen(Str); 67 | 68 | for (ptr=Str; ptr < (Str+ilen); ptr++) 69 | { 70 | if (strchr(CharList,*ptr)) 71 | { 72 | // replacing ' ' with '+' should work, but some servers seem to no longer support it 73 | /* 74 | if (*ptr==' ') 75 | { 76 | RetStr=AddCharToBuffer(RetStr,olen,'+'); 77 | olen++; 78 | } 79 | else 80 | */ 81 | { 82 | Token=FormatStr(Token,"%%%02X",*ptr); 83 | StrLenCacheAdd(RetStr, olen); 84 | RetStr=CatStr(RetStr,Token); 85 | olen+=StrLen(Token); 86 | } 87 | } 88 | else 89 | { 90 | RetStr=AddCharToBuffer(RetStr,olen,*ptr); 91 | olen++; 92 | } 93 | } 94 | 95 | StrUnsafeTrunc(RetStr, olen); 96 | 97 | DestroyString(Token); 98 | return(RetStr); 99 | } 100 | 101 | 102 | 103 | char *HTTPQuote(char *RetBuff, const char *Str) 104 | { 105 | return(HTTPQuoteChars(RetBuff, Str, " \t\r\n\"#%()[]{}<>?&!,+':;/@")); 106 | } 107 | 108 | 109 | -------------------------------------------------------------------------------- /HttpUtil.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | //These functions are 'utility' functions related to HTTP, but which 7 | //might be used outside of http sometimes, such as quoting and unquoting 8 | //strings with the HTTP quoting system 9 | 10 | #ifndef LIBUSEFUL_HTTP_UTIL_H 11 | #define LIBUSEFUL_HTTP_UTIL_H 12 | 13 | #include "includes.h" 14 | 15 | 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | 21 | //apply http quoting (e.g. space is '%20') to a string, quoting any character in 'CharList' 22 | // e.g. Quoted=HTTPQuoteChars(Quoted, "http://user:pass@somewhere.com",":@"); 23 | char *HTTPQuoteChars(char *RetBuff, const char *Str, const char *CharList); 24 | 25 | //apply http quoting to a string, quoting standard problematic characters 26 | // e.g. Quoted=HTTPQuote(Quoted, "http://user:pass@somewhere.com"); 27 | char *HTTPQuote(char *RetBuff, const char *Str); 28 | 29 | //unquote a string that contains HTTP style quoting 30 | // e.g. Str=HTTPUnQuote(Str, Quoted); 31 | char *HTTPUnQuote(char *RetBuff, const char *Str); 32 | 33 | //decode a base64 string in the format : as used in 'Basic' http authentication 34 | //into individual user and password strings 35 | void HTTPDecodeBasicAuth(const char *Auth, char **UserName, char **Password); 36 | 37 | 38 | 39 | #ifdef __cplusplus 40 | } 41 | #endif 42 | 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /IPAddress.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | 7 | #ifndef LIBUSEFUL_IPADDR_H 8 | #define LIBUSEFUL_IPADDR_H 9 | 10 | #include "includes.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | //these functions return TRUE if a string appears to be an IP4 or IP6 address 17 | int IsIP4Address(const char *Str); 18 | int IsIP6Address(const char *Str); 19 | 20 | //returns TRUE for either IP6 or IP4 21 | int IsIPAddress(const char *Str); 22 | 23 | //lookup the primary IP address of a hostname 24 | const char *LookupHostIP(const char *Host); 25 | 26 | //lookup a list of addresses for a hostname 27 | ListNode *LookupHostIPList(const char *Host); 28 | 29 | //reverse lookup hostname for an IP 30 | const char *IPStrToHostName(const char *IP); 31 | 32 | //convert an integer representation of IP4 address to a string 33 | const char *IPtoStr(unsigned long IP); 34 | 35 | //convert a string representation of IP4 address to an integer representation 36 | unsigned long StrtoIP(const char *IPStr); 37 | 38 | //new functions that use inet_pton and inet_ntop 39 | void StrtoIP6(const char *Str, struct in6_addr *dest); 40 | 41 | char *IP4toStr(char *RetStr, unsigned long IP); 42 | 43 | char *IP6toStr(char *RetStr, struct in6_addr *IP); 44 | 45 | 46 | #ifdef __cplusplus 47 | } 48 | #endif 49 | 50 | 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /Inet.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_INET_H 7 | #define LIBUSEFUL_INET_H 8 | 9 | #include "includes.h" 10 | #include "defines.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | char *ExtractFromWebpage(char *RetStr, const char *URL, const char *ExtractStr, int MinLength); 17 | char *GetExternalIP(char *RetStr); 18 | int IPGeoLocate(const char *IP, ListNode *Vars); 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /LibSettings.c: -------------------------------------------------------------------------------- 1 | #include "defines.h" 2 | #include "includes.h" 3 | #include "Vars.h" 4 | #include "libUseful.h" 5 | #include 6 | 7 | /* These functions provide an interface for setting variables that */ 8 | /* are used by libUseful itself */ 9 | 10 | int LibUsefulFlags=0; 11 | static ListNode *LibUsefulSettings=NULL; 12 | 13 | ListNode *LibUsefulValuesGetHead() 14 | { 15 | return(LibUsefulSettings); 16 | } 17 | 18 | void LibUsefulInitSettings() 19 | { 20 | char *Tempstr=NULL; 21 | 22 | LibUsefulSettings=ListCreate(LIST_FLAG_CACHE); 23 | SetVar(LibUsefulSettings, "LibUseful:Version", __LIBUSEFUL_VERSION__); 24 | 25 | Tempstr=MCopyStr(Tempstr, __LIBUSEFUL_BUILD_DATE__, " ", __LIBUSEFUL_BUILD_TIME__, NULL); 26 | SetVar(LibUsefulSettings, "LibUseful:BuildTime", Tempstr); 27 | 28 | #ifdef USE_LGPL 29 | SetVar(LibUsefulSettings, "LibUseful:License", "LGPLv3"); 30 | #else 31 | SetVar(LibUsefulSettings, "LibUseful:License", "GPLv3"); 32 | #endif 33 | 34 | Tempstr=FormatStr(Tempstr, "%d", 4096 * 10000); 35 | SetVar(LibUsefulSettings, "MaxDocumentSize", Tempstr); 36 | 37 | Tempstr=FormatStr(Tempstr, "%d", 4096 * 10000); 38 | SetVar(LibUsefulSettings, "WEBSOCKET:MaxFrameSize", Tempstr); 39 | 40 | DestroyString(Tempstr); 41 | } 42 | 43 | void LibUsefulSetHTTPFlag(int Flag, const char *Value) 44 | { 45 | int Flags; 46 | 47 | if (strtobool(Value)) Flags=HTTPGetFlags() | Flag; 48 | else Flags=HTTPGetFlags() & ~Flag; 49 | HTTPSetFlags(Flags); 50 | } 51 | 52 | 53 | 54 | void LibUsefulSetValue(const char *Name, const char *Value) 55 | { 56 | if (! LibUsefulSettings) LibUsefulInitSettings(); 57 | if (strcasecmp(Name,"HTTP:Debug")==0) LibUsefulSetHTTPFlag(HTTP_DEBUG, Value); 58 | if (strcasecmp(Name,"HTTP:NoCookies")==0) LibUsefulSetHTTPFlag(HTTP_NOCOOKIES, Value); 59 | if (strcasecmp(Name,"HTTP:NoCompress")==0) LibUsefulSetHTTPFlag(HTTP_NOCOMPRESS, Value); 60 | if (strcasecmp(Name,"HTTP:NoCompression")==0) LibUsefulSetHTTPFlag(HTTP_NOCOMPRESS, Value); 61 | if (strcasecmp(Name,"HTTP:NoRedirect")==0) LibUsefulSetHTTPFlag(HTTP_NOREDIRECT, Value); 62 | if (strcasecmp(Name,"HTTP:NoCache")==0) LibUsefulSetHTTPFlag(HTTP_NOCACHE, Value); 63 | if (strcasecmp(Name,"StrLenCache")==0) 64 | { 65 | if (! strtobool(Value)) LibUsefulFlags |= LU_STRLEN_NOCACHE; 66 | else LibUsefulFlags &= ~LU_STRLEN_NOCACHE; 67 | } 68 | SetVar(LibUsefulSettings,Name,Value); 69 | } 70 | 71 | const char *LibUsefulGetValue(const char *Name) 72 | { 73 | if (! LibUsefulSettings) LibUsefulInitSettings(); 74 | 75 | if (!StrValid(Name)) return(""); 76 | return(GetVar(LibUsefulSettings,Name)); 77 | } 78 | 79 | int LibUsefulGetBool(const char *Name) 80 | { 81 | return(strtobool(LibUsefulGetValue(Name))); 82 | } 83 | 84 | 85 | int LibUsefulGetInteger(const char *Name) 86 | { 87 | const char *ptr; 88 | 89 | ptr=LibUsefulGetValue(Name); 90 | if (StrValid(ptr)) return(atoi(ptr)); 91 | return(0); 92 | } 93 | 94 | int LibUsefulDebugActive() 95 | { 96 | if (StrValid(getenv("LIBUSEFUL_DEBUG"))) return(TRUE); 97 | if (LibUsefulGetBool("libUseful:Debug")) return(TRUE); 98 | return(FALSE); 99 | } 100 | 101 | 102 | void LibUsefulAtExit() 103 | { 104 | #ifdef HAVE_MUNLOCKALL 105 | if (LibUsefulFlags & LU_MLOCKALL) munlockall(); 106 | #endif 107 | 108 | if (LibUsefulFlags & LU_CONTAINER) FileSystemUnMount("/","lazy"); 109 | ConnectionHopCloseAll(); 110 | CredsStoreDestroy(); 111 | } 112 | 113 | 114 | void LibUsefulSetupAtExit() 115 | { 116 | if (! (LibUsefulFlags & LU_ATEXIT_REGISTERED)) atexit(LibUsefulAtExit); 117 | LibUsefulFlags |= LU_ATEXIT_REGISTERED; 118 | } 119 | -------------------------------------------------------------------------------- /Markup.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | 7 | #ifndef LIBUSEFUL_MARKUP_H 8 | #define LIBUSEFUL_MARKUP_H 9 | 10 | #include "includes.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | // These functions act on XML and HTML style markup documents 17 | 18 | //read the next XML/HTML tag from memory. extract the namespace, tag type and Tag arguments and return a pointer to the 19 | //memory just after the tag. Namespace, TagType and TagData must be pointers to libUseful style strings 20 | const char *XMLGetTag(const char *Input, char **Namespace, char **TagType, char **TagData); 21 | 22 | //check both TagType and TagData for indications this is an end tag 23 | int XMLIsEndTag(const char *TagType, const char *TagData); 24 | 25 | //copy Str to RetBuff, applying HTML quoting as we go. RetBuff must be a libUseful style string 26 | char *HTMLQuote(char *RetBuff, const char *Str); 27 | 28 | //copy Str to RetBuff, expanding HTML quoting as we go. RetBuff must be a libUseful style string 29 | char *HTMLUnQuote(char *RetStr, const char *Str); 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | 35 | 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /OTP.c: -------------------------------------------------------------------------------- 1 | #include "includes.h" 2 | #include "Hash.h" 3 | #include "HMAC.h" 4 | #include "Encodings.h" 5 | #include "String.h" 6 | 7 | int TOTPAtTime(char **RetStr, const char *HashType, const char *EncodedSecret, int SecretEncoding, time_t When, int Digits, int Interval) 8 | { 9 | uint64_t totp=0; 10 | uint32_t code; 11 | char *Tempstr=NULL, *Secret=NULL; 12 | const char *ptr; 13 | int len, pos; 14 | 15 | len=DecodeBytes(&Secret, EncodedSecret, SecretEncoding); 16 | totp=(uint64_t) htonll((uint64_t) (When / Interval)); 17 | 18 | len=HMACBytes(&Tempstr, HashType, Secret, len, (char *) &totp, sizeof(uint64_t), ENCODE_NONE); 19 | 20 | ptr=Tempstr + len -1; 21 | pos=*ptr & 0xf; 22 | memcpy(&code, Tempstr + pos, 4); 23 | 24 | code=htonl(code); 25 | code &= 0x7fffffff; 26 | 27 | Tempstr=FormatStr(Tempstr, "%u", code); 28 | *RetStr=CopyStrLen(*RetStr, Tempstr + StrLen(Tempstr) - Digits, Digits); 29 | 30 | Destroy(Tempstr); 31 | Destroy(Secret); 32 | 33 | return(When % Interval); 34 | } 35 | 36 | 37 | 38 | int TOTPPrevCurrNext(char **Prev, char **Curr, char **Next, const char *HashType, const char *EncodedSecret, int SecretEncoding, int Digits, int Interval) 39 | { 40 | time_t When; 41 | When=time(NULL); 42 | 43 | TOTPAtTime(Prev, HashType, EncodedSecret, SecretEncoding, When - (Interval / 2 + 1), Digits, Interval); 44 | TOTPAtTime(Curr, HashType, EncodedSecret, SecretEncoding, When, Digits, Interval); 45 | TOTPAtTime(Next, HashType, EncodedSecret, SecretEncoding, When + (Interval / 2 + 1), Digits, Interval); 46 | return(When % Interval); 47 | } 48 | 49 | 50 | char *TOTP(char *RetStr, const char *HashType, const char *EncodedSecret, int SecretEncoding, int Digits, int Interval) 51 | { 52 | TOTPAtTime(&RetStr, HashType, EncodedSecret, SecretEncoding, time(NULL), Digits, Interval); 53 | return(RetStr); 54 | } 55 | 56 | 57 | char *GoogleTOTP(char *RetStr, const char *EncodedSecret) 58 | { 59 | return(TOTP(RetStr, "sha1", EncodedSecret, ENCODE_BASE32, 6, 30)); 60 | } 61 | -------------------------------------------------------------------------------- /OTP.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | 7 | #ifndef LIBUSEFUL_OTP_H 8 | #define LIBUSEFUL_OTP_H 9 | 10 | /* Generate a Time based One Time Password. 11 | For compatiblity with Google authenticator you should use: 12 | 13 | HashType=sha1 14 | Digits=6 15 | Interval=30 16 | SecretEncoding=ENCODE_BASE32 17 | 18 | 19 | This function does not parse totp urls, you will have to extract the secret from those yourself. 20 | */ 21 | 22 | 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | 29 | //Calculate TOTP at a given time, returns number of seconds the code is valid from that time 30 | int TOTPAtTime(char **RetStr, const char *HashType, const char *EncodedSecret, int SecretEncoding, time_t When, int Digits, int Interval); 31 | 32 | 33 | //Calculate TOTP at the current moment 34 | char *TOTP(char *RetStr, const char *HashType, const char *EncodedSecret, int SecretEncoding, int Digits, int Interval); 35 | 36 | 37 | //Calculate TOTP at Current time, at CurrTime - (Interval / 2 +5) and at CurrTime + (Interval / 2 +5) 38 | //returns number of seconds the 'Curr' code is valid from CurrTime 39 | int TOTPPrevCurrNext(char **Prev, char **Curr, char **Next, const char *HashType, const char *EncodedSecret, int SecretEncoding, int Digits, int Interval); 40 | 41 | 42 | //Calculate GoogleAutenticator code for the current moment 43 | char *GoogleTOTP(char *RetStr, const char *EncodedSecret); 44 | 45 | 46 | //Google authenticator compatible TOTP 47 | char *GoogleTOTP(char *RetStr, const char *EncodedSecret); 48 | 49 | 50 | #ifdef __cplusplus 51 | } 52 | #endif 53 | 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /PasswordFile.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | // These functions relate to a password file that stores passwords 7 | // in the form: 8 | // :::: 9 | // 10 | // if 'pass type' is blank or is 'plain' then the password is stored as-is in plaintext 11 | // otherwise 'pass type' will be a hash type, like md5, sha256 etc. 12 | // For hash types a 20 character salt is generated and prepended to the password, 13 | // and the resulting string is then hashed before being stored 14 | // 'extra' is populated with any extra data for/about this user 15 | 16 | 17 | #ifndef LIBUSEFUL_PASSWORD_FILE_H 18 | #define LIBUSEFUL_PASSWORD_FILE_H 19 | 20 | 21 | #include "includes.h" 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | 28 | // Add an entry to the password file, replacing any previous entries for that user. Because it has 29 | // to remove previous entries, this function builds an new password file, and then atomically moves 30 | // it into place to replace the existing one. It will not remove any duplicate entries for other 31 | // users. 32 | int PasswordFileAdd(const char *Path, const char *PassType, const char *User, const char *Password, const char *Extra); 33 | 34 | // Add an entry to the password file, not replacing previous entries, to previous passwords can still be 35 | // used. This does not require rebuilding the file, and thus may be more efficient than PasswordFileAdd 36 | int PasswordFileAppend(const char *Path, const char *PassType, const char *User, const char *Password, const char *Extra); 37 | 38 | //check a users password matches the one stored in password file at 'Path' 39 | int PasswordFileCheck(const char *Path, const char *User, const char *Password, char **ReturnedData); 40 | 41 | #ifdef __cplusplus 42 | } 43 | #endif 44 | 45 | 46 | 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /PatternMatch.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | 7 | #ifndef LIBUSEFUL_MATCHPATTERN 8 | #define LIBUSEFUL_MATCHPATTERN 9 | 10 | 11 | /* 12 | pmatch functions provide an enhanced form of the fnmatch shell/glob style pattern matching. 13 | This is because, personally, I hate POSIX regular expressions. 14 | 15 | SUPPORTED NATCHES ARE: 16 | 17 | ? any character 18 | * any list of characters 19 | ^ start-of-string marker 20 | $ end-of-string marker 21 | [..] list of characters 22 | 23 | \a alert (bell) 24 | \b backspace 25 | \d delete 26 | \e escape 27 | \n newline 28 | \r carriage-return 29 | \t tab 30 | \l any lowercase character 31 | \A any alphabetic character 32 | \B any alphanumeric character 33 | \C any printable character 34 | \D any digit 35 | \S any space 36 | \P any punctuation 37 | \U any uppercase character 38 | 39 | \+ turn match switch on 40 | \- turn match switch off 41 | 42 | MATCH SWITCHES: 43 | 44 | \+C \-C turn on/off case sensitive matching 45 | \+W \-W turn on/off wildcards 46 | \+X \-X turn on/off extraction. When 'off' matching chars will not be added to returned strings 47 | \+O \-O turn on/off overlapping matches. Overlapping matches are on by default. 48 | 49 | 50 | 51 | 52 | Please note that, without the PMATCH_SUBSTR flag being passed, the whole string must match (like glob). 53 | 54 | */ 55 | 56 | 57 | #define PMATCH_SUBSTR 1 58 | #define PMATCH_NOWILDCARDS 2 59 | #define PMATCH_NOCASE 4 60 | #define PMATCH_NOEXTRACT 8 61 | #define PMATCH_NEWLINEEND 16 62 | #define PMATCH_NOTSTART 32 63 | #define PMATCH_NOTEND 64 64 | #define PMATCH_NO_OVERLAP 128 65 | #define PMATCH_SHORT 256 66 | 67 | 68 | #include "includes.h" 69 | 70 | #ifdef __cplusplus 71 | extern "C" { 72 | #endif 73 | 74 | typedef struct 75 | { 76 | const char *Start; 77 | const char *End; 78 | } TPMatch; 79 | 80 | 81 | //find one match. Start and End can be NULL if you don't care where the match is 82 | int pmatch_one(const char *Pattern, const char *String, int len, const char **Start, const char **End, int Flags); 83 | 84 | 85 | //find many matches and return them in the list 86 | int pmatch(const char *Pattern, const char *String, int Len, ListNode *Matches, int Flags); 87 | 88 | 89 | #ifdef __cplusplus 90 | } 91 | #endif 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /Pty.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_PTY_H 7 | #define LIBUSEFUL_PTY_H 8 | 9 | #include "defines.h" 10 | 11 | //These are passed to TTYConfig 12 | #define TTYFLAG_PTY 1 13 | #define TTYFLAG_DATA 2 //we will be sending raw data on the tty, not lines of text. Effects flushing rules. 14 | #define TTYFLAG_CANON 4096 15 | #define TTYFLAG_HARDWARE_FLOW 8192 //enable hardware flow control 16 | #define TTYFLAG_SOFTWARE_FLOW 16324 //enable software flow control 17 | #define TTYFLAG_CRLF_KEEP 32768 18 | #define TTYFLAG_IGNSIG 65536 19 | #define TTYFLAG_ECHO 131072 //enable input echo 20 | #define TTYFLAG_IN_CRLF 262144 //change CarriageReturn to LineFeed on input 21 | #define TTYFLAG_IN_LFCR 524288 //change LineFeed to CarriageReturn on input 22 | #define TTYFLAG_OUT_CRLF 1048576 //change LineFeed to CarriageReturn-Linefeed on output 23 | #define TTYFLAG_NONBLOCK 2097152 24 | #define TTYFLAG_SAVE 4194304 //save attributes for later use with TTYReset 25 | #define COMMS_COMBINE_STDERR 8388608 //save attributes for later use with TTYReset 26 | 27 | #define STREAMConfigTTY(S,speed,flags) ((S && istty(S->in_fd)) ? TTYConfig(S->in_fd,speed,flags)) 28 | #define STREAMResetTTY(S) ((S && istty(S->in_fd)) ? TTYReset(S->in_fd)) 29 | #define STREAMHangUpTTY(S) ((S && istty(S->in_fd)) ? TTYHangUp(S->in_fd)) 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | //Reset a tty config to the values that were set before TTYOpen or TTYConfig were called 36 | int TTYReset(int tty); 37 | 38 | //shutdown TTY (hangup line if phone) 39 | int TTYHangUp(int tty); 40 | 41 | //in situations where the application is displaying a terminal, or in some other sense 42 | //knows the size of a window, tell the pty system what size that window is 43 | void PTYSetGeometry(int pty, int wid, int high); 44 | 45 | //open a tty device (like /dev/ttyS0). Flags are as 'TTYFLAG_' #defines above 46 | int TTYOpen(const char *devname, int LineSpeed, int Flags); 47 | 48 | 49 | 50 | //change config of an already opened tty device. Flags are as 'TTYFLAG_' #defines above 51 | void TTYConfig(int tty, int LineSpeed, int Flags); 52 | 53 | //get config flags of an already opened tty device 54 | int TTYGetConfig(int tty); 55 | 56 | //change config of an already opened tty device. Flags are as 'TTYFLAG_' #defines above 57 | #define TTYSetConfig(tty,speed,flags) (TTYConfig((tty,(speed),(flags))) 58 | 59 | 60 | 61 | //TTYOpen except accepting text config, not flags. Intended for bindings to languages like lua that don't handle 62 | //bit-flags well. possible config text options are: 63 | 64 | // 'pty' this is a noop in these functions, but is used in the Spawn functions 65 | // 'canon' turn on canonical processing 66 | // 'echo' turn on tty echo 67 | // 'xon' software flow control 68 | // 'sw' software flow control 69 | // 'hw' hardware flow control 70 | // 'nonblock' nonblocking 71 | // 'nb' nonblocking 72 | // 'ilfcr' input: change linefeed to carriage return 73 | // 'icrlf' input: change carriage return to linefeed 74 | // 'ocrlf' output: change linefeed to carriagereturn-linefeed 75 | // 'nosig' no signals 76 | // 'save' save current attributes (saved attributes can be restored by using TTYReset) 77 | // numeric values are taken as tty linespeeds 78 | 79 | int TTYConfigOpen(const char *Dev, const char *Config); 80 | 81 | //Parse 'text config' into flags and speed 82 | int TTYParseConfig(const char *Config, int *Speed); 83 | 84 | //master and slave are two ends of a PseudoTTY 'pipe'. This is a two-way pipe with all the properties (like line-speed, tty modes etc) of 85 | // a tty. I normally attach 'slave' to stdin and stdout of some process, and use 'master' as the end I read/write from/to 86 | int PseudoTTYGrab(int *master, int *slave, int Flags); 87 | 88 | //turn tty local echo on or off 89 | void TTYSetEcho(int tty, int OnOrOff); 90 | 91 | //switch canonical (line editing) mode on or off 92 | void TTYSetCanonical(int tty, int OnOrOff); 93 | 94 | #ifdef __cplusplus 95 | } 96 | #endif 97 | 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.com/ColumPaget/libUseful.svg?branch=master)](https://travis-ci.com/ColumPaget/libUseful) 2 | 3 | libUseful - a 'C' library of useful functions. 4 | ----------------------------------------------- 5 | 6 | libUseful provides a range of functions that simplify common programming tasks in 'C', particularly networking and communications. It hides the complexities of sockets, openssl, zlib, pseudoterminals, http, etc and provides commonly needed functionality like resizeable strings, linked lists and maps. 7 | 8 | libUseful has been compiled and used on various linux and freebsd systems. 9 | 10 | 11 | Author 12 | ------ 13 | libUseful is (C) 2009 Colum Paget. 14 | 15 | Email: colums.projects@gmail.com 16 | 17 | 18 | 19 | License 20 | ------- 21 | 22 | libUseful is licensed under either the Gnu Public License v3 or Lesser Gnu Public License v3. Some included code is GPL only, so to be under the Lesser Gnu Public License it must be built with the '--enable-lgpl' configure flag, which will leave those components out of the build. 23 | 24 | 25 | DISCLAIMER 26 | ---------- 27 | This is free software. It comes with no guarentees and I take no responsiblity if it makes your computer explode or opens a portal to the demon dimensions, or does anything. 28 | 29 | Install 30 | ------- 31 | 32 | should be as simple as: 33 | 34 | ./configure --prefix=/usr/local --enable-ssl --enable-ip6 35 | make 36 | make install 37 | 38 | .h files will be copied to /include/libUseful-4 39 | 40 | On linux a few linux-specific functions can be activated via configure: 41 | 42 | --enable-sendfile enable kernel-level 'fastcopy' within the STREAMSendFile function 43 | 44 | On intel systems some MMX/SSE/SSE2 features can be turned on by 45 | 46 | --enable-simd= where level is one of 'mmx', 'sse' or 'sse2' 47 | 48 | the major use of --enable-simd is SSE2 cache hinting in the list/map system, which can prevent large lists from poisoning the cache and so improve program performance. 49 | 50 | Compiler Flags 51 | -------------- 52 | 53 | If libUseful is compiled with openssl support then you need to pass the following library flags to gcc when you compile your programs 54 | 55 | gcc -o myProg myProg.c -lUseful -lssl -lcrypto -lz 56 | 57 | If openssl is not used (libUseful compiled with --disable-ssl), but zlib is used then the flags are 58 | 59 | gcc -o myProg myProg.c -lUseful -lssl -lcrypto -lz 60 | 61 | If neither zlib or openssl functionality is used in libUseful, then the flags are just 62 | 63 | gcc -o myProg myProg.c -lUseful 64 | 65 | 66 | IPv6 support 67 | ------------ 68 | 69 | Please note that, due to the author's lack of access to IPv6 networks the IPv6 functionality has not been extensively tested, though it has been seen to work. 70 | 71 | 72 | Documentation 73 | ------------- 74 | 75 | Please read Quickstart.md for an overview of core paradigms of using libUseful. Individual functions are documented in the .h header files. 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /RawData.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_BINARYBUFFER_H 7 | #define LIBUSEFUL_BINARYBUFFER_H 8 | 9 | #include "includes.h" 10 | 11 | /* 12 | These functions mostly exist for use in bindings to languages like lua that have no native 13 | support for binary data. They allow reading data into a buffer and then reading it out 14 | character by character or as Int16 or Int32 types 15 | */ 16 | 17 | 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | 24 | #define RAWDATARead(RD, S, len) (RAWDATAReadAt(RD, S, 0, len)) 25 | #define RAWDATASave(RD, S) (RAWDATAWriteAt(RD, S, 0, 0)) 26 | 27 | typedef struct 28 | { 29 | size_t BuffLen; 30 | size_t DataLen; 31 | char *Buffer; 32 | size_t pos; 33 | } RAWDATA; 34 | 35 | 36 | RAWDATA *RAWDATACreate(const char *Data, const char *Encoding, int MaxSize); 37 | RAWDATA *RAWDATACopy(RAWDATA *RD, size_t offset, size_t len); 38 | int RAWDATAAppend(RAWDATA *RD, const char *Data, const char *Encoding, int MaxBuffLen); 39 | void RAWDATADestroy(void *p_RD); 40 | 41 | int RAWDATAReadAt(RAWDATA *RD, STREAM *S, size_t offset, size_t size); 42 | int RAWDATAWrite(RAWDATA *RD, STREAM *S, size_t offset, size_t size); 43 | char RAWDATAGetChar(RAWDATA *RD, size_t pos); 44 | int RAWDATASetChar(RAWDATA *RD, size_t pos, char value); 45 | int16_t RAWDATAGetInt16(RAWDATA *RD, size_t pos); 46 | int RAWDATASetInt16(RAWDATA *RD, size_t pos, int16_t value); 47 | int32_t RAWDATAGetInt32(RAWDATA *RD, size_t pos); 48 | int RAWDATASetInt32(RAWDATA *RD, size_t pos, int32_t value); 49 | long RAWDATAFindChar(RAWDATA *RD, size_t offset, char Char); 50 | 51 | char *RAWDATACopyStr(char *RetStr, RAWDATA *RD); 52 | char *RAWDATACopyStrLen(char *RetStr, RAWDATA *RD, int len); 53 | void RAWDATAMove(RAWDATA *RD, size_t from, size_t to, size_t len); 54 | void RAWDATATrunc(RAWDATA *RD, size_t len); 55 | 56 | #ifdef __cplusplus 57 | } 58 | #endif 59 | 60 | 61 | 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /Seccomp.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2025 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_SECCOMP_H 7 | #define LIBUSEFUL_SECCOMP_H 8 | 9 | #include "includes.h" 10 | 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | int SeccompAddRules(const char *RuleList); 17 | 18 | #ifdef __cplusplus 19 | } 20 | #endif 21 | 22 | 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /SecureMem.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_SECUREMEM_H 7 | #define LIBUSEFUL_SECUREMEM_H 8 | 9 | #define SMEM_LOCK 1 10 | #define SMEM_NODUMP 2 11 | #define SMEM_NOFORK 4 12 | #define SMEM_RDONLY 8 13 | #define SMEM_WRONLY 16 14 | #define SMEM_NOACCESS 32 15 | #define SMEM_MADV_DONTFORK 4096 16 | #define SMEM_SECURE (SMEM_LOCK | SMEM_NOFORK | SMEM_NODUMP) 17 | #define SMEM_PARANOID (SMEM_SECURE | SMEM_NOACCESS) 18 | 19 | #define SecureStoreUnlock(SS) SecureLockMem(SS->Data, SS->Size, SMEM_RDONLY) 20 | #define SecureStoreLock(SS) SecureLockMem(SS->Data, SS->Size, SMEM_NOACCESS) 21 | 22 | #include 23 | 24 | typedef struct 25 | { 26 | int Flags; 27 | int Used; 28 | int Size; 29 | pid_t OwnerPid; 30 | unsigned char *Data; 31 | unsigned char *CurrLine; 32 | 33 | //Divisor is a single character that divides up fields in the data 34 | char Divisor; 35 | } SECURESTORE; 36 | 37 | 38 | #ifdef __cplusplus 39 | extern "C" { 40 | #endif 41 | 42 | void SecureClearMem(unsigned char *Mem, int Size); 43 | void SecureDestroy(unsigned char *Mem, int Size); 44 | int SecureRealloc(unsigned char **OldMem, int OldSize, int NewSize, int Flags); 45 | 46 | SECURESTORE *SecureStoreCreate(int Size); 47 | void SecureStoreDestroy(SECURESTORE *SS); 48 | SECURESTORE *SecureStoreLoad(const char *Path); 49 | 50 | int CredsStoreLoad(const char *Path); 51 | int CredsStoreAdd(const char *Realm, const char *User, const char *Cred); 52 | int CredsStoreLookup(const char *Realm, const char *User, const char **Pass); 53 | void CredsStoreDestroy(); 54 | void CredsStoreOnFork(); 55 | 56 | 57 | #ifdef __cplusplus 58 | } 59 | #endif 60 | 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /Smtp.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_SMTP_H 7 | #define LIBUSEFUL_SMTP_H 8 | 9 | #include "includes.h" 10 | #include "defines.h" 11 | 12 | #define SMTP_NOSSL 1 13 | #define SMTP_NOHEADER 2 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | int SMTPSendMail(const char *Sender, const char *Recipient, const char *Subject, const char *Body, int Flags); 20 | int SMTPSendMailFile(const char *Sender, const char *Recipient, const char *Path, int Flags); 21 | 22 | #ifdef __cplusplus 23 | } 24 | #endif 25 | 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /Ssh.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_SSH_H 7 | #define LIBUSEFUL_SSH_H 8 | 9 | #include "Stream.h" 10 | 11 | /* 12 | Connect to an ssh server and run a command. This requires the ssh command-line program to be available. 13 | 14 | You will normally not use these functions, instead using something like 'STREAMOpen("ssh://myhost.com:2222", "r bind=192.168.6.1");' 15 | 16 | The 'config' argument to SSHConnect and SSHOpen is the same as other STREAMOpen style commands, consisting of a set of fopen-style 'open flags' 17 | followed by name-value pairs for other settings 18 | 19 | Currently recognized 'open flags' are: 20 | 'r' -> SF_RDONLY (read a file from remote server) 21 | 'w' -> SF_WRONLY (write a file to remote server) 22 | 'w' -> SF_APPEND (append to a file to remote server) 23 | 'l' -> list files on remote server 24 | 'x' or anything else runs a command on the remote server 25 | 26 | Currently recognized name-value settings are: 27 | 28 | bind=
bind to a local address so that our connection seems to be coming from that address 29 | config= use ssh config file 30 | 31 | Note, such SSH connections CANNOT BE USED WITH CONNECTION CHAINS / PROXIES. They are always direct connections. 32 | 33 | if ssh's config system is being used to set up known connections (via ~/.ssh/config) then User, Pass and Port 34 | are not needed, and 'Host' is simply the connection-config name as configured in ~/.ssh/config. 35 | 36 | The returned stream can be used with the usual STREAM functions to read/write to and from the Command on the 37 | ssh host. see Stream.h for available functions. 38 | */ 39 | 40 | #ifdef __cplusplus 41 | extern "C" { 42 | #endif 43 | 44 | STREAM *SSHConnect(const char *Host, int Port, const char *User, const char *Pass, const char *Command, const char *Config); 45 | STREAM *SSHOpen(const char *Host, int Port, const char *User, const char *Pass, const char *Path, const char *Config); 46 | void SSHClose(STREAM *S); 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /StrLenCache.c: -------------------------------------------------------------------------------- 1 | #include "StrLenCache.h" 2 | 3 | #ifdef USE_STRLEN_CACHE 4 | typedef struct 5 | { 6 | const char *Str; 7 | size_t len; 8 | } TStrLenCacheEntry; 9 | 10 | static int StrLenCacheSize=0; 11 | static int StrLenCacheMinLen=100; 12 | static TStrLenCacheEntry *StrLenCache=NULL; 13 | 14 | 15 | 16 | 17 | static TStrLenCacheEntry *StrLenCacheFind(const char *Str) 18 | { 19 | TStrLenCacheEntry *Entry; 20 | 21 | for (Entry=StrLenCache; Entry < StrLenCache + StrLenCacheSize; Entry++) 22 | { 23 | //do not try to use builtin-prefetch here, as we are not interested 24 | //in the strings that are pointed to, we are just comparing addresses 25 | if (Entry->Str == Str) 26 | { 27 | return(Entry); 28 | } 29 | } 30 | 31 | return(NULL); 32 | } 33 | #endif 34 | 35 | 36 | int StrLenCacheInit(int Size, int MinStrLen) 37 | { 38 | #ifdef USE_STRLEN_CACHE 39 | StrLenCache=(TStrLenCacheEntry *) calloc(Size, sizeof(TStrLenCacheEntry)); 40 | if (StrLenCache == NULL) 41 | { 42 | errno=ENOMEM; 43 | return(FALSE); 44 | } 45 | StrLenCacheSize=Size; 46 | StrLenCacheMinLen=MinStrLen; 47 | return(TRUE); 48 | #endif 49 | 50 | errno=ENOTSUP; 51 | return(FALSE); 52 | } 53 | 54 | 55 | 56 | void StrLenCacheDel(const char *Str) 57 | { 58 | #ifdef USE_STRLEN_CACHE 59 | TStrLenCacheEntry *Entry; 60 | 61 | Entry=StrLenCacheFind(Str); 62 | if (Entry) Entry->Str=NULL; 63 | #endif 64 | } 65 | 66 | void StrLenCacheUpdate(const char *Str, int incr) 67 | { 68 | #ifdef USE_STRLEN_CACHE 69 | TStrLenCacheEntry *Entry; 70 | 71 | Entry=StrLenCacheFind(Str); 72 | if (Entry) Entry->len += incr; 73 | #endif 74 | } 75 | 76 | 77 | void StrLenCacheAdd(const char *Str, size_t len) 78 | { 79 | #ifdef USE_STRLEN_CACHE 80 | int i, emptyslot=-1; 81 | 82 | if (LibUsefulFlags & LU_STRLEN_NOCACHE) return; 83 | 84 | 85 | if (! StrLenCache) StrLenCacheInit(10, 100); 86 | 87 | //is string already in cache? We must check this even for short lengths! 88 | for (i=0; i < StrLenCacheSize; i++) 89 | { 90 | if (StrLenCache[i].Str == NULL) emptyslot=i; 91 | else if (StrLenCache[i].Str == Str) 92 | { 93 | //if the string has become short, then free its entry in the cache 94 | if (len < StrLenCacheMinLen) StrLenCache[i].Str=NULL; 95 | else StrLenCache[i].len=len; 96 | return; 97 | } 98 | } 99 | 100 | //don't pollute cache with short strings that don't take long to look up 101 | //strlen caching has been seen to give a benefit with very large strings, 102 | //but modern processors with built-in strlen functions are proabably faster 103 | //for short strings. The magic number seems to be about 100 chars. 104 | if (len > StrLenCacheMinLen) 105 | { 106 | //if we get here than string isn't in cache and we add it 107 | if (emptyslot == -1) emptyslot=rand() % StrLenCacheSize; 108 | 109 | StrLenCache[emptyslot].Str=Str; 110 | StrLenCache[emptyslot].len=len; 111 | } 112 | #endif 113 | } 114 | 115 | 116 | int StrLenFromCache(const char *Str) 117 | { 118 | if (! StrValid(Str)) return(0); 119 | 120 | #ifdef USE_STRLEN_CACHE 121 | TStrLenCacheEntry *Entry; 122 | 123 | if (! (LibUsefulFlags & LU_STRLEN_NOCACHE)) 124 | { 125 | Entry=StrLenCacheFind(Str); 126 | if (Entry) return(Entry->len); 127 | } 128 | #endif 129 | 130 | //okay, nothing worked, fall back to good old strlen 131 | return(strlen(Str)); 132 | } 133 | 134 | -------------------------------------------------------------------------------- /StrLenCache.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_STRLEN_CACHE_H 7 | #define LIBUSEFUL_STRLEN_CACHE_H 8 | 9 | #include "includes.h" 10 | 11 | /* 12 | Libuseful has an internal caching system for strlen results, as functions like CopyStr use 13 | strlen a lot. For large strings (basically manipulating entire documents in memory) this can 14 | result in very dramatic speedups on old systems without AVX strlen processor instructions. 15 | However, for short strings it can be slightly slower than libc strlen. The magic number seems 16 | to come at about 100 characters long. 17 | 18 | Hence 'StrLen' (defined in String.h) does not use this cache. StrLenFromCache is the version 19 | of StrLen that does use the cache. Furthermore short strings are not added to the cache, as 20 | the benefit of caching them is too small to warrant evicting longer strings from the cache. 21 | 22 | All this means that libUseful string functions like CopyStr trade off being slightly slower 23 | than strlen for short strings, against being much better than strlen for large strings. In 24 | normal use these differences aren't noticable, but become so when dealing with large strings. 25 | 26 | There is a danger to this when using functions that directly manipulate strings. If one directly 27 | sets a character in a string to be '\0' (the null char or zero byte) then the string would 28 | usually be considered 'truncated' at that point. However StrLenFromCache will still report 29 | the cached length of the string. This can result in 'CatStr' appending data *after* the 30 | null/zero byte, which means such data will effectively be lost. This is why functions like: 31 | 32 | StrTrunc(char *Str, int Len) 33 | StrTruncChar(char *Str, char Term); 34 | StrRTruncChar(char *Str, char Term); 35 | 36 | are provided to allow string truncation that works with caching. 37 | 38 | 39 | 40 | The caching system can be switched on and off using: 41 | 42 | LibUsefulSetValue("StrLenCache", "Y"); // turn caching on 43 | LibUsefulSetValue("StrLenCache", "N"); // turn caching off 44 | 45 | it can also be compiled out using the `./configure --disable-strlen-cache` option 46 | 47 | */ 48 | 49 | 50 | 51 | #ifdef __cplusplus 52 | extern "C" { 53 | #endif 54 | 55 | 56 | //this function allows you to set the number of rows in the string-len cache, and the minimum 57 | //length of a string to be included in the cache. The defaults are '10' rows in the cache and 58 | //'100' characters minimum in a string to be included. 59 | 60 | //If all is well, function returns TRUE 61 | //If StrLenCaching is disabled at libUseful compile time function returns FALSE and errno is set to ENOTSUP 62 | //if memory for the cache cannot be allocated then the function returns FALSE and errno is set to ENOMEM 63 | //Note: if caching is turned off with LibUsefulSetValue then this function still returns true, as you 64 | //can change the settings for the cache even when you're not currently using the feature 65 | int StrLenCacheInit(int Size, int MinStrLen); 66 | 67 | 68 | //thse are used internally, you'll not normally use any of these functions 69 | int StrLenFromCache(const char *Str); 70 | void StrLenCacheDel(const char *Str); 71 | void StrLenCacheUpdate(const char *Str, int incr); 72 | void StrLenCacheAdd(const char *Str, size_t len); 73 | 74 | #ifdef __cplusplus 75 | } 76 | #endif 77 | 78 | 79 | 80 | #endif 81 | 82 | -------------------------------------------------------------------------------- /StreamAuth.c: -------------------------------------------------------------------------------- 1 | #include "StreamAuth.h" 2 | #include "OpenSSL.h" 3 | #include "PasswordFile.h" 4 | #include "HttpUtil.h" 5 | #include "Encodings.h" 6 | #include "StringList.h" 7 | 8 | 9 | static int STREAMAuthValueFile(const char *Path, const char *Value) 10 | { 11 | 12 | return(FALSE); 13 | } 14 | 15 | //did the client provide an SSL certificate as authentication? 16 | static int STREAMAuthProcessCertificate(STREAM *S, const char *CertName, const char *CommonName) 17 | { 18 | char *Require=NULL; 19 | int AuthResult=FALSE; 20 | 21 | #ifdef HAVE_LIBSSL 22 | //does the certificate name/subject match out expectation? 23 | Require=OpenSSLCertDetailsGetCommonName(Require, STREAMGetValue(S, CommonName)); 24 | if (CompareStr(CertName, Require)==0) 25 | { 26 | //is certificate valid 27 | if (CompareStr(STREAMGetValue(S, "SSL:CertificateVerify"), "OK")==0) AuthResult=TRUE; 28 | } 29 | #endif 30 | 31 | Destroy(Require); 32 | return(AuthResult); 33 | } 34 | 35 | 36 | 37 | 38 | static int STREAMBasicAuthPasswordFile(const char *Path, STREAM *S) 39 | { 40 | char *User=NULL, *Password=NULL; 41 | const char *ptr; 42 | int AuthResult=FALSE; 43 | 44 | if (StrValid(Path)) 45 | { 46 | User=CopyStr(User, STREAMGetValue(S, "AUTH:User")); 47 | Password=CopyStr(Password, STREAMGetValue(S, "AUTH:Password")); 48 | AuthResult=PasswordFileCheck(Path, User, Password, NULL); 49 | } 50 | 51 | Destroy(User); 52 | Destroy(Password); 53 | 54 | return(AuthResult); 55 | } 56 | 57 | 58 | 59 | static int STREAMAuthProcess(STREAM *S, const char *AuthTypes) 60 | { 61 | char *Key=NULL, *Value=NULL, *Tempstr=NULL; 62 | const char *ptr; 63 | int AuthResult=FALSE; 64 | 65 | //we are passed a list of authentication methods as name-value pairs, 66 | //where the name is the authentication method type, and the value is 67 | //data related to that type (sometimes a password or ip, sometimes a path 68 | //to a file containing the actual passwords etc) 69 | ptr=GetNameValuePair(AuthTypes, ";", ":",&Key, &Value); 70 | while (ptr) 71 | { 72 | if (CompareStrNoCase(Key, "basic")==0) 73 | { 74 | Tempstr=EncodeBytes(Tempstr, Value, StrLen(Value), ENCODE_BASE64); 75 | if (CompareStr(Tempstr, STREAMGetValue(S, "Auth:Basic"))==0) AuthResult=TRUE; 76 | } 77 | else if ( 78 | (CompareStrNoCase(Key, "certificate")==0) || 79 | (CompareStrNoCase(Key, "cert")==0) 80 | ) AuthResult=STREAMAuthProcessCertificate(S, Value, "SSL:CertificateSubject"); 81 | else if (CompareStrNoCase(Key, "issuer")==0) AuthResult=STREAMAuthProcessCertificate(S, Value, "SSL:CertificateIssuer"); 82 | else if (CompareStrNoCase(Key, "cookie")==0) 83 | { 84 | if (InStringList(STREAMGetValue(S, Key), Value, ",")) AuthResult=TRUE; 85 | } 86 | else if (CompareStrNoCase(Key, "ip")==0) 87 | { 88 | if (InStringList(GetRemoteIP(S->in_fd), Value, ",")) AuthResult=TRUE; 89 | } 90 | else if (CompareStrNoCase(Key, "password-file")==0) AuthResult=STREAMBasicAuthPasswordFile(Value, S); 91 | 92 | ptr=GetNameValuePair(ptr, ";", ":",&Key, &Value); 93 | } 94 | 95 | if (AuthResult==TRUE) STREAMSetValue(S, "STREAM:Authenticated", "Y"); 96 | 97 | 98 | Destroy(Key); 99 | Destroy(Value); 100 | Destroy(Tempstr); 101 | 102 | return(AuthResult); 103 | } 104 | 105 | 106 | 107 | int STREAMAuth(STREAM *S) 108 | { 109 | const char *ptr; 110 | 111 | ptr=STREAMGetValue(S, "AUTH:Types"); 112 | if (! StrValid(ptr)) return(TRUE); 113 | 114 | if (STREAMAuthProcess(S, ptr)) 115 | { 116 | S->Flags |= LU_SS_AUTH; 117 | return(TRUE); 118 | } 119 | 120 | return(FALSE); 121 | } 122 | -------------------------------------------------------------------------------- /StreamAuth.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_STREAM_AUTH_H 7 | #define LIBUSEFUL_STREAM_AUTH_H 8 | 9 | #include "Stream.h" 10 | 11 | /* Functions supporting some types of authentication against streams. 12 | 13 | For http streams password-file authentication is supported. For other network streams 14 | IP address based and ssl certificate based authenticaiton is supported. 15 | 16 | The only function you'd normally use here is the 'STREAMIsAuth(STREAM *S)' macro, to check 17 | if a stream has been authenticated using any of these methods. 'STREAMAuth' is usually called 18 | automatically from within STREAMServerAccept, and doesn't need to be re-called. 19 | 20 | Both STREAMIsAuth and STREAMAuth return TRUE or FALSE to indicate whether the stream has been authenticated 21 | 22 | Example usage: 23 | 24 | Serv=STREAMServerNew("http:192.168.0.1", "auth='password-file:/etc/myserver.pw;ip:192.168.0.2,192.168.0.3'"); 25 | S=STREAMServerAccept(Serv); 26 | if (StreamIsAuth(S)) 27 | { 28 | ... 29 | } 30 | 31 | This sets up authentication using either a password file (see PasswordFile.h) or by IP address. If the connection is coming from one of the specified IP addresses, or theres a user/password match in the password file, then the connection is authenticated (obviously password-file is only usable because HTTP has a password authentication scheme). 32 | 33 | Note usage of semi-colon to seperate authentication types. comma is used to seperate multiple options within an authentication type 34 | 35 | Available authentication schemes are: 36 | 37 | ip:
- authenticate by matching source IP with one of the IPs in a comma-seperated list 38 | password-file: - authenticate by using a username/password found in password file at 39 | cert: - authenticate with a client-certificate that verifies and has the specified subject (usually username) 40 | certificate: - authenticate with a client-certificate that verifies and has the specified subject (usually username) 41 | issuer: - authenticate with a client-certificate that verifies and is issued by the specified issuer 42 | basic: - authenticate using a username and password combo expressed as an HTTP style base64 encoded string 43 | cookie: - authenticate using an HTTP cookie that matches 44 | 45 | For the 'certificate' and 'issuer' authentication types, the verifiying certificates (CA certificates) can be defined using the 'SSL:VerifyFile' and 'SSL:VerifyDir' options to STREAMServerNew (without these libUseful will default to using the openssl default file, usually stored somewhere like '/etc/ssl/cacert.pem', and which provides CA certificates for well-known certificate authorities. 46 | 47 | Example SSL setup: 48 | 49 | Serv=STREAMServerNew("tls:192.168.0.1", "auth='cert:bill.blogs;issuer:myCA' ssl:CertFile=/etc/ssl/myhost.crt ssl:KeyFile=/etc/ssl/myhost.key ssl:VerifyFile=/etc/ssl/myCA.ca"); 50 | S=STREAMServerAccept(Serv); 51 | if (StreamIsAuth(S)) 52 | { 53 | ... 54 | } 55 | 56 | In this setup we can authenticate using a certificate for 'bill.blogs' that is verified by any CA certificate (in this case that would have to be one in /etc/ssl/myCA.ca) or with any certificate issued by 'myCA' (which again, must be verified against a certificate in /etc/ssl/myCA.ca) 57 | 58 | 59 | */ 60 | 61 | 62 | 63 | 64 | #ifdef __cplusplus 65 | extern "C" { 66 | #endif 67 | 68 | #define STREAMIsAuth(S) ((S)->Flags & LU_SS_AUTH) 69 | int STREAMAuth(STREAM *S); 70 | 71 | #ifdef __cplusplus 72 | } 73 | #endif 74 | 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /StringList.c: -------------------------------------------------------------------------------- 1 | #include "StringList.h" 2 | #include "Tokenizer.h" 3 | #include "includes.h" 4 | 5 | int InStringList(const char *Item, const char *List, const char *Sep) 6 | { 7 | const char *ptr; 8 | char *Token=NULL; 9 | int RetVal=FALSE; 10 | 11 | ptr=GetToken(List, Sep, &Token, 0); 12 | while (ptr) 13 | { 14 | if (strcmp(Item, Token)==0) 15 | { 16 | RetVal=TRUE; 17 | break; 18 | } 19 | ptr=GetToken(ptr, Sep, &Token, 0); 20 | } 21 | 22 | Destroy(Token); 23 | 24 | return(RetVal); 25 | } 26 | 27 | 28 | char *StringListGet(char *RetStr, const char *List, const char *Sep, int Pos) 29 | { 30 | const char *ptr; 31 | char *Token=NULL; 32 | int count=0; 33 | 34 | RetStr=CopyStr(RetStr, ""); 35 | ptr=GetToken(List, Sep, &Token, 0); 36 | while (ptr) 37 | { 38 | if (count==Pos) RetStr=CopyStr(RetStr, Token); 39 | count++; 40 | ptr=GetToken(ptr, Sep, &Token, 0); 41 | } 42 | 43 | Destroy(Token); 44 | return(RetStr); 45 | } 46 | 47 | 48 | char *StringListAdd(char *RetStr, const char *Item, const char *Sep) 49 | { 50 | if (StrValid(RetStr)) RetStr=MCatStr(RetStr, Sep, Item, NULL); 51 | else RetStr=CopyStr(RetStr, Item); 52 | 53 | return(RetStr); 54 | } 55 | 56 | char *StringListAddUnique(char *RetStr, const char *Item, const char *Sep) 57 | { 58 | char *Token=NULL; 59 | const char *ptr; 60 | 61 | ptr=GetToken(RetStr, Sep, &Token, 0); 62 | while (ptr) 63 | { 64 | if (CompareStr(Token, Item) ==0) 65 | { 66 | Destroy(Token); 67 | return(RetStr); 68 | } 69 | ptr=GetToken(ptr, Sep, &Token, 0); 70 | } 71 | 72 | return(StringListAdd(RetStr, Item, Sep)); 73 | } 74 | 75 | 76 | char *StringListToUnique(char *RetStr, const char *Input, const char *Sep) 77 | { 78 | char *Token=NULL; 79 | const char *ptr; 80 | 81 | ptr=GetToken(Input, Sep, &Token, 0); 82 | while (ptr) 83 | { 84 | RetStr=StringListAddUnique(RetStr, Token, Sep); 85 | ptr=GetToken(ptr, Sep, &Token, 0); 86 | } 87 | 88 | return(RetStr); 89 | } 90 | -------------------------------------------------------------------------------- /StringList.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Copyright (c) 2015 Colum Paget 4 | * SPDX-License-Identifier: LGPL-3.0-or-later 5 | */ 6 | 7 | #ifndef LIBUSEFUL_STRINGLIST_H 8 | #define LIBUSEFUL_STRINGLIST_H 9 | 10 | /* 11 | Utility functions to hand a string of strings, separated by a separator string or character 12 | */ 13 | 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | //check if Item is in string 'List' where 'List' is separated into strings by 'Sep' 20 | //e.g. InStringList("that", "this,that,theother", ","); 21 | 22 | 23 | //is an Item in a List of strings separated by Sep? 24 | int InStringList(const char *Item, const char *List, const char *Sep); 25 | 26 | //get an item at Pos in a List of strings seperated by Sep 27 | char *StringListGet(char *RetStr, const char *List, const char *Sep, int Pos); 28 | 29 | //add Item to the end of a list of strings (here RetStr as it's also what's returned) separated by Sep 30 | char *StringListAdd(char *RetStr, const char *Item, const char *Sep); 31 | 32 | //add Item to the end of a list of strings (here RetStr as it's also what's returned) separated by Sep, but only do that if it's not already in the string 33 | char *StringListAddUnique(char *RetStr, const char *Item, const char *Sep); 34 | 35 | //take a list of strings (Input) separated by Sep, and return a copy of Input except each string only occurs once 36 | char *StringListToUnique(char *RetStr, const char *Input, const char *Sep); 37 | 38 | 39 | #ifdef __cplusplus 40 | } 41 | #endif 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /SysInfo.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_SYSINFO_H 7 | #define LIBUSEFUL_SYSINFO_H 8 | 9 | 10 | #include "defines.h" 11 | #include "includes.h" 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | 18 | typedef enum {OSINFO_TYPE, OSINFO_ARCH, OSINFO_RELEASE, OSINFO_HOSTNAME, OSINFO_UPTIME, OSINFO_TOTALMEM, OSINFO_FREEMEM, OSINFO_BUFFERMEM, OSINFO_TOTALSWAP, OSINFO_FREESWAP, OSINFO_LOAD1MIN, OSINFO_LOAD5MIN, OSINFO_LOAD15MIN, OSINFO_HOMEDIR, OSINFO_TMPDIR, OSINFO_PROCS, OSINFO_USERINFO, OSINFO_DOMAINNAME, OSINFO_INTERFACES, OSINFO_LOCALE, OSINFO_LANG, OSINFO_COUNTRY, OSINFO_CURRENCY, OSINFO_CURRENCY_SYM, OSINFO_PAGESIZE, OSINFO_OPENMAX, OSINFO_CLOCKTICK} EOSInfo; 19 | 20 | 21 | // pass in one of the OSINFO_ defines above to get out a string answer 22 | //OSINFO_TYPE system type, e.g. 'linux' 23 | //OSINFO_ARCH system architecture, e.g. 'arm' 'i386' 24 | //OSINFO_RELEASE system kernel version 25 | //OSINFO_HOSTNAME system hostname 26 | //OSINFO_DOMAINNAME system domainname 27 | //OSINFO_INTERFACES list of network interfaces 28 | //OSINFO_HOMEDIR user home directory 29 | //OSINFO_TMPDIR user temporary directory 30 | //OSINFO_LOCALE user locale (en_US, en_GB, fr_FR, jp_JP etc) 31 | //OSINFO_LANG user locale lang (en, fr, jp etc) 32 | //OSINFO_COUNTRY user locale country (US, GB, FR, JP, ZH) 33 | //OSINFO_CURRENCY user locale currency code (USD, GBP, EU, etc) 34 | //OSINFO_CURRENCY_SYM user locale currency sym ($ etc) 35 | 36 | const char *OSSysInfoString(int Info); 37 | 38 | 39 | 40 | // pass in one of the OSINFO_ defines to get a numeric answer 41 | // OSINFO_UPTIME seconds since boot 42 | // OSINFO_TOTALMEM visible system memory 43 | // OSINFO_FREEMEM available system memory 44 | // OSINFO_BUFFERMEM memory used in buffers 45 | // OSINFO_TOTALSWAP total swap space 46 | // OSINFO_FREESWAP free swap space 47 | // OSINFO_LOAD1MIN system load in last minute 48 | // OSINFO_LOAD5MIN system load in last five minutes 49 | // OSINFO_LOAD15MIN system load in last fifteen minutes 50 | // OSINFO_PROCS number of processes running 51 | // OSINFO_PAGESIZE pagesize of system 52 | // OSINFO_OPENMAX max number of files open by a process 53 | // OSINFO_CLOCKTICK clockticks per second (accurate value 54 | 55 | size_t OSSysInfoLong(int Info); 56 | 57 | #ifdef __cplusplus 58 | } 59 | #endif 60 | 61 | 62 | #endif 63 | 64 | -------------------------------------------------------------------------------- /TerminalBar.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_TERMINAL_BAR_H 7 | #define LIBUSEFUL_TERMINAL_BAR_H 8 | 9 | #include "includes.h" 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | /* THIS FEATURE IS STILL BEING DEVELOPED 16 | * 17 | * ultimately the plan is to be able to add 'bars' to the top and bottom of the screen that can hold 18 | * information, menus or text input, with the scrolling region of the terminal being between them 19 | */ 20 | 21 | 22 | //this will eventually be replaced with 23 | //the 'TerminalWidget' base struct 24 | typedef struct 25 | { 26 | int Flags; 27 | int x, y; 28 | int ForeColor; 29 | int BackColor; 30 | int TextLen; 31 | char *Text; 32 | char *MenuPadLeft; 33 | char *MenuPadRight; 34 | char *CursorLeft; 35 | char *CursorRight; 36 | ListNode *MenuItems; 37 | STREAM *Term; 38 | } TERMBAR; 39 | 40 | 41 | // These functions create a terminal bar at the bottom of the screen. 42 | TERMBAR *TerminalBarCreate(STREAM *Term, const char *Config, const char *Text); 43 | void TerminalBarDestroy(TERMBAR *TB); 44 | 45 | // Change config of a terminal bar. Options key=value strings. Recognized keys are: 46 | // MenuPadLeft //string that menu options should be left padded with 47 | // MenuPadRight //string that menu options should be right padded with 48 | // CursorLeft //string that SELECTED menu options should be left padded with 49 | // CursorRight //string that SELECTED menu options should be right padded with 50 | // forecolor, backcolor, bold, inverse, underline, blink //attributes 51 | // e.g. forecolor=red backcolor=yellow 'MenuPadLeft= ' 'MenuPadRight= ' 'CursorLeft= >' 'CursorRight=< ' 52 | void TerminalBarSetConfig(TERMBAR *TB, const char *Config); 53 | 54 | 55 | //display a terminal bar with 'Text' 56 | void TerminalBarUpdate(TERMBAR *TB, const char *Text); 57 | 58 | //display a prompt in a terminal bar and let the user type in text. Flags are as for 'TerminalReadText' 59 | char *TerminalBarReadText(char *RetStr, TERMBAR *TB, int Flags, const char *Prompt); 60 | 61 | //display a menu of optoons in a terminal bar. Options are supplied as a comma-separated 62 | //list in 'ItemStr'. The selected option is copied into 'RetStr' and returned 63 | char *TerminalBarMenu(char *RetStr, TERMBAR *TB, const char *ItemStr); 64 | 65 | 66 | void TerminalBarsInit(STREAM *S); 67 | 68 | 69 | #ifdef __cplusplus 70 | } 71 | #endif 72 | 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /TerminalChoice.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | /* This implements a simple one-line menu that looks like: 7 | * 8 | * proceed Y/n? no 9 | * 10 | * If you just want to ask a question without other processing going on you can do: 11 | * 12 | * STREAM *Term; 13 | * char *Choice=NULL; 14 | * 15 | * Term=STREAMFromDualFD(0,1); 16 | * Term=TerminalInit(TERM_RAWKEYS|TERM_SAVEATTRIBS); 17 | * Choice=TerminalChoice(Choice, Term, "prompt='make your choice' options='yes,no,maybe'"); 18 | * printf("User Chose: %s\n", Choice); 19 | * 20 | * If the user presses escape (they may have to do this twice) then NULL is returned (and the string, in this case 'Choice' is freed if it has memory allocated). Otherwise one of the strings given in the comma-separated list 'options' is returned. 21 | * 22 | * The 'Config' parameter of TerminalChoice takes the following entries: 23 | * 24 | * prompt= A text or prompt that preceeds the menu 25 | * options= A comma-separated list of menu options 26 | * choices= Equivalent to 'options=' 27 | * x= Position the menu at terminal column 'x'. Without x and/or y the menu will be on the current line 28 | * y= Position the menu at terminal row 'y'. Without x and/or y the menu will be on the current line 29 | * select-left= Text to the left of a currently selected item. Defaults to '<' 30 | * select-right= Text to the right of a currently selected item. Defaults to '>' 31 | * pad-left= Text to the left of an unselected item. Defaults to ' ' 32 | * pad-right= Text to the right of an unselected item. Defaults to ' ' 33 | * 34 | * 35 | * The 'select' and 'pad' entries can take libUseful tilde-style formatting. If, for instance, you wanted the selected item to be bold-text you'd call: 36 | * 37 | * Choice=TerminalChoice(Choice, Term, "select-left='~e ' select-right=' ~0' pad-left=' ' pad-right=' ' options='yes,no,maybe'"); 38 | * 39 | * In programs where blocking while the user makes a choice is not desired, the following approach can be used: 40 | * 41 | 42 | TERMCHOICE *Chooser; 43 | int inchar; 44 | 45 | Chooser=TerminalChoiceCreate(Term, Config); 46 | TerminalChoiceDraw(Chooser); 47 | inchar=TerminalReadChar(Term); 48 | while (TRUE) 49 | { 50 | RetStr=TerminalChoiceOnKey(RetStr, Chooser, inchar); 51 | if ((! RetStr) || StrValid(RetStr)) break; 52 | 53 | // do other things 54 | 55 | inchar=TerminalReadChar(Term); 56 | } 57 | RetStr=TerminalChoiceProcess(RetStr, Chooser); 58 | TerminalChoiceDestroy(Chooser); 59 | 60 | 61 | Normally this would probably be broken up into a part called at program startup that set up the TERMCHOICE object 62 | then a select/poll loop that did various things, and handed the 'TerminalReadChar' and called 'TerminalChoiceOnKey' 63 | and finally TerminalChoiceDestroy being called on program exit or whenever 64 | 65 | * 66 | */ 67 | 68 | 69 | #ifndef LIBUSEFUL_TERMINAL_CHOICE_H 70 | #define LIBUSEFUL_TERMINAL_CHOICE_H 71 | 72 | #include "includes.h" 73 | #include "Unicode.h" 74 | #include "KeyCodes.h" 75 | 76 | #include "Terminal.h" 77 | #include "TerminalMenu.h" 78 | 79 | #define TERMCHOICE TERMMENU 80 | 81 | #ifdef __cplusplus 82 | extern "C" { 83 | #endif 84 | 85 | #define TerminalChoiceDestroy TerminalWidgetDestroy 86 | #define TerminalChoiceSetOptions TerminalWidgetSetOptions 87 | 88 | TERMCHOICE *TerminalChoiceCreate(STREAM *Term, const char *Config); 89 | void TerminalChoiceDraw(TERMCHOICE *Chooser); 90 | char *TerminalChoiceOnKey(char *RetStr, TERMCHOICE *Chooser, int key); 91 | char *TerminalChoiceProcess(char *RetStr, TERMCHOICE *Chooser); 92 | char *TerminalChoice(char *RetStr, STREAM *Term, const char *Config); 93 | 94 | 95 | #ifdef __cplusplus 96 | } 97 | #endif 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /TerminalKeys.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | 7 | #ifndef LIBUSEFUL_TERMINAL_KEYS_H 8 | #define LIBUSEFUL_TERMINAL_KEYS_H 9 | 10 | #include "includes.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | const char *TerminalTranslateKeyCode(int key); 17 | int TerminalTranslateKeyStrWithMod(const char *str, int *mod); 18 | int TerminalTranslateKeyStr(const char *str); 19 | int TerminalReadCSISeq(STREAM *S); 20 | int TerminalReadOSCSeq(STREAM *S); 21 | int TerminalReadSSCSeq(STREAM *S); 22 | 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | 27 | 28 | 29 | #endif 30 | 31 | 32 | -------------------------------------------------------------------------------- /TerminalMenu.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_TERMINAL_MENU_H 7 | #define LIBUSEFUL_TERMINAL_MENU_H 8 | 9 | #include "includes.h" 10 | #include "TerminalWidget.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | 17 | //Terminal menu functions give you a selectable 'box' menu of options that's operated by 'up', 'down' 18 | //'enter' to select and 'escape' to back out of it. The menu has an internal list called 'options' to 19 | //which you add named items. The names are the menu options that will be displayed. You can pass NULL 20 | //for the list item, or an object you want associated with the menu option. When an option is selected 21 | //the list node is returned, so you have both the option name, as Node->Tag, and any associated item 22 | //as Node->Item 23 | 24 | // Supported keys are arrows and ctrl-WASD: 25 | 26 | //UP: up-arrow, ctrl-w 27 | //DOWN: down-arrow, ctrl-s 28 | //SELECT: enter, ctrl-d 29 | //EXIT MENU: escape, ctrl-a 30 | 31 | 32 | #define TERMMENU_POSITIONED 1 33 | #define TERMMENU_SELECTED LIST_FLAG_USER1 34 | 35 | #define TERMMENU TERMWIDGET 36 | #define TerminalMenuDestroy TerminalWidgetDestroy 37 | 38 | TERMMENU *TerminalMenuCreate(STREAM *Term, int x, int y, int wid, int high); 39 | 40 | //draw the menu in it's current state. 41 | void TerminalMenuDraw(TERMMENU *Menu); 42 | 43 | //process key and draw menu in its state after the keypress. Return a choice if 44 | //one is selected, else return NULL. This can be used if you want to handle some 45 | //keypresses outside of the menu, only passing relevant keys to the menu 46 | ListNode *TerminalMenuOnKey(TERMMENU *Menu, int key); 47 | 48 | //run a menu after it's been setup. This keeps reading keypresses until an option is 49 | //selected. Returns the selected option, or returns NULL if escape is pressed 50 | ListNode *TerminalMenuProcess(TERMMENU *Menu); 51 | 52 | //set menu cursor to top 53 | ListNode *TerminalMenuTop(TERMMENU *Menu); 54 | 55 | //move menu cursor up one line 56 | ListNode *TerminalMenuUp(TERMMENU *Menu); 57 | 58 | //move menu cursor down one line 59 | ListNode *TerminalMenuDown(TERMMENU *Menu); 60 | 61 | 62 | //create a menu from a list of options, and run it. 63 | //This keeps reading keypresses until an option is selected. 64 | //Returns the selected option, or returns NULL if escape is pressed. 65 | //if TERMMENU_SELECTED is set on the head of Options, then the menu will allow setting 66 | //'selected' against multiple values 67 | ListNode *TerminalMenu(STREAM *Term, ListNode *Options, int x, int y, int wid, int high); 68 | 69 | //create a menu from a line of text, and run it. 70 | //Options in the text a seperated by '|' so "This|That|The Other". 71 | //This keeps reading keypresses until an option is selected. 72 | //Returns the selected option as string copied into 'RetStr', or returns NULL if escape is pressed. 73 | //if TERMMENU_SELECTED is set on the head of Options, then the menu will allow setting 74 | //'selected' against multiple values 75 | char *TerminalMenuFromText(char *RetStr, STREAM *Term, const char *Options, int x, int y, int wid, int high); 76 | 77 | 78 | #ifdef __cplusplus 79 | } 80 | #endif 81 | 82 | 83 | 84 | #endif 85 | 86 | -------------------------------------------------------------------------------- /TerminalProgress.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | /* This implements a simple terminal progress bar 7 | * 8 | * Example Usage: 9 | 10 | STREAM *Term; 11 | char *Tempstr=NULL; 12 | TERMPROGRESS *TP; 13 | int i; 14 | 15 | Term=STREAMFromDualFD(0,1); 16 | TerminalInit(Term, TERM_RAWKEYS | TERM_SAVEATTRIBS); 17 | TerminalClear(Term); 18 | 19 | TP=TerminalProgressCreate(Term, "prompt='progress: ' left-contain=' -=' right-contain='=- ' progress=| width=20"); 20 | for (i=0; i <= 20; i++) 21 | { 22 | Tempstr=FormatStr(Tempstr, "NOW AT: %d", i); 23 | TerminalProgressUpdate(TP, i, 20, Tempstr); 24 | sleep(1); 25 | } 26 | 27 | TerminalReset(Term); 28 | } 29 | 30 | * 31 | * The 'Config' parameter of TerminalProgressCreate takes the following entries: 32 | * 33 | * prompt= A text or prompt that preceeds the progress bar 34 | * x= Position the progress-bar at terminal column 'x'. Without x and/or y the progress-bar will be on the current line 35 | * y= Position the progress-bar at terminal row 'y'. Without x and/or y the progress-bar will be on the current line 36 | * width= Width in characters of progress-bar NOT INCLUDING prompt, left container, right container etc 37 | * progress= A character to use for the progress part of the bar, defaults to '*' 38 | * remain= A character to use for the remaining part of the bar, defaults to ' ' 39 | * remainder= A character to use for the remaining part of the bar, defaults to ' ' 40 | * remaining= A character to use for the remaining part of the bar, defaults to ' ' 41 | * attrib= Set attributes of REMAINDER part of the bar 42 | * progress-attrib= Set attributes of PROGRESS part of the bar 43 | * left-contain= A string to be the left 'container' of the bar, defaults to ' [' 44 | * right-contain= A string to be the right 'container' of the bar, defaults to '] ' 45 | * innertext= Text displayed in (or 'over') the progress bar, can contain $(percent) to be updated with percentage done 46 | * 47 | * attrib and progress-attrib can be used to create bars based only around colored blocks, like so 48 | 49 | TP=TerminalProgressCreate(Term, "prompt='progress: ' progress=' ' attribs=~B progress-attribs=~W left-contain='' right-contain=' ' width=20"); 50 | * 51 | */ 52 | 53 | 54 | #ifndef LIBUSEFUL_TERMINAL_PROGRESS_H 55 | #define LIBUSEFUL_TERMINAL_PROGRESS_H 56 | 57 | #include "includes.h" 58 | #include "Unicode.h" 59 | #include "KeyCodes.h" 60 | 61 | #ifdef __cplusplus 62 | extern "C" { 63 | #endif 64 | 65 | #include "Terminal.h" 66 | #include "TerminalMenu.h" 67 | 68 | #define TERMPROGRESS TERMWIDGET 69 | 70 | #define TerminalProgressDestroy TerminalWidgetDestroy 71 | #define TerminalProgressSetOptions TerminalWidgetSetOptions 72 | 73 | TERMPROGRESS *TerminalProgressCreate(STREAM *Term, const char *Config); 74 | void TerminalProgressDraw(TERMPROGRESS *TP, float Perc, const char *Info); 75 | char *TerminalProgressProcess(char *RetStr, TERMPROGRESS *TP); 76 | float TerminalProgressUpdate(TERMPROGRESS *TP, int Value, int Max, const char *Info); 77 | 78 | 79 | #ifdef __cplusplus 80 | } 81 | #endif 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /TerminalTheme.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_TERMINAL_THEME_H 7 | #define LIBUSEFUL_TERMINAL_THEME_H 8 | 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | 15 | #include "includes.h" 16 | #include "List.h" 17 | #include "TerminalWidget.h" 18 | 19 | ListNode *TerminalThemeInit(); 20 | const char *TerminalThemeGet(const char *Scope, const char *AttributeName); 21 | void TerminalThemeSet(const char *Name, const char *Value); 22 | void TerminalThemeApply(TERMWIDGET *TW, const char *Type); 23 | 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif 28 | 29 | 30 | 31 | #endif 32 | 33 | 34 | -------------------------------------------------------------------------------- /TerminalWidget.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | /* 7 | * 8 | * You probably have no interest in this module, it provides shared functionality used by TerminalMenu, TerminalChoice and TerminalProgress 9 | */ 10 | 11 | 12 | #ifndef LIBUSEFUL_TERMINAL_WIDGET_H 13 | #define LIBUSEFUL_TERMINAL_WIDGET_H 14 | 15 | #include "includes.h" 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | #define TERMWIDGET_POSITIONED 1 22 | 23 | typedef struct 24 | { 25 | int x; 26 | int y; 27 | int wid; 28 | int high; 29 | STREAM *Term; 30 | ListNode *Options; 31 | char *Attribs; 32 | char *CursorAttribs; 33 | char *SelectedAttribs; 34 | char *CursorLeft; 35 | char *CursorRight; 36 | int Flags; 37 | char *Text; 38 | } TERMWIDGET; 39 | 40 | TERMWIDGET *TerminalWidgetNew(STREAM *Term, int x, int y, int width, int high, const char *Options); 41 | TERMWIDGET *TerminalWidgetCreate(STREAM *Term, const char *Options); 42 | void TerminalWidgetParseConfig(TERMWIDGET *TW, const char *Config); 43 | void TerminalWidgetDestroy(void *p_Widget); 44 | 45 | int TerminalWidgetPutLine(TERMWIDGET *TW, int line, const char *Text); 46 | int TerminalWidgetStartLine(TERMWIDGET *TW, int line); 47 | 48 | 49 | #ifdef __cplusplus 50 | } 51 | #endif 52 | 53 | 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /Time.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_TIME_H 7 | #define LIBUSEFUL_TIME_H 8 | 9 | #include "includes.h" 10 | #include "Process.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | #define HOURSECS 3600 17 | #define DAYSECS (24 * 3600) 18 | #define LU_STD_DATE_FMT "%Y/%m/%d %H:%M:%S" 19 | 20 | //Flags passed to get time 21 | #define TIME_MILLISECS 1 //return number of milliseconds 22 | #define TIME_CENTISECS 2 //return number of centiseconds 23 | #define TIME_CACHED 1024 //used cached time 24 | 25 | // Get current time. By default returns seconds since 1970. Passing the above flags can change that to milliseconds or centiseconds. 26 | // Passing TIME_CACHED causes it to return a cached value for the time (you'd use this in time-critical applications where you're 27 | // looking the time up a lot 28 | uint64_t GetTime(int Flags); 29 | 30 | //return a string describing the current date/time, in a format described by 'DateFormat'. 'DateFormat' is an strftime/strptime style format string. 31 | char *GetDateStr(const char *DateFormat, const char *TimeZone); 32 | 33 | //in the next two functions 'epoch' is usually Jan 1 1970, but might be some other date on different systems. 34 | //It's the date that all time is measured from in the operating system or hardware. 35 | 36 | //as GetDateStr except the 'Secs' argument (which is number of seconds since epoch, as returned by time(NULL)) specifies the time to format 37 | char *GetDateStrFromSecs(const char *DateFormat, time_t Secs, const char *TimeZone); 38 | 39 | //Convert a date/time string 'Str' to number of seconds since epoch 40 | time_t DateStrToSecs(const char *DateFormat, const char *Str, const char *TimeZone); 41 | 42 | //Convert a string describing a duration to seconds. String in the form "1d 5h 30m" where m=minutes h=hours d=days w=weeks y=year Y=year (year always 365 days) 43 | time_t ParseDuration(const char *Dur); 44 | 45 | //format a string using the substitutions %w %d %h %m %s for weeks, days, hours, minutes and seconds 46 | //if any of the substututions are missing, then their value is carried over to the next highest substitution 47 | //so if there's no '%d', then the 'days' part will be counted in '%h' (hours) 48 | //or if that is missing in '%m' (mins) or '%s' (seconds) 49 | const char *FormatDuration(const char *Fmt, time_t Duration); 50 | 51 | //convert Time from timezone 'SrcZone' to 'DstZone' 52 | //time must be inf ormat "%Y/%m/%d %H:%M:%S" 53 | char *TimeZoneConvert(char *RetStr, const char *Time, const char *SrcZone, const char *DstZone); 54 | 55 | //this sets a SIGALRM timer, causing a signal to be sent to our process after 'timeout' seconds. 56 | //You can either pass a signal handler function, or pass NULL to use the default libUseful internal 57 | //signal handler (SIGNAL_HANDLER_FUNC is of the form 'void MyHandler(int sig)' ) 58 | void SetTimeout(int timeout, SIGNAL_HANDLER_FUNC); 59 | 60 | //return the offset in seconds of "TimeZone" 61 | long TimezoneOffset(const char *TimeZone); 62 | 63 | //convert a milliseconds value to a timeval 64 | void MillisecsToTV(int millisecs, struct timeval *tv); 65 | 66 | 67 | //given day, month and year, is it the current day? return TRUE if so, FALSE otherwise 68 | int IsToday(int Day, int Month, int Year); 69 | 70 | 71 | //return TRUE (1) if year is a leap year, FALSE (0) otherwise 72 | int IsLeapYear(unsigned int year); 73 | 74 | //return number of days in month (month range 1-12, months < 1 are in previous years and >12 are in subsequent years) 75 | int GetDaysInMonth(int Month, int Year); 76 | 77 | //produce a csv of days in month. each line is a week. Any dates starting 78 | //with '-' are in the previous month to the one requested, and any 79 | //started with '+' are in the next month 80 | char *CalendarFormatCSV(char *RetStr, unsigned int Month, unsigned int Year); 81 | 82 | 83 | #ifdef __cplusplus 84 | } 85 | #endif 86 | 87 | 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /URL.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_URL_H 7 | #define LIBUSEFUL_URL_H 8 | 9 | #include "includes.h" 10 | 11 | /* 12 | These functions break a URL of the form ://:@:/? into its component parts 13 | 14 | In general any of the destination arguments can be NULL. So, if you don't want user and password, just set the return args 15 | for those to NULL 16 | */ 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif 21 | 22 | 23 | //Parse a full URL with all parts. DO NOT TRY TO GUESS PORT if no port in the URL itself 24 | void UnpackURL(const char *URL, char **Proto, char **Host, char **Port, char **User, char **Password, char **Path, char **Args); 25 | 26 | 27 | //Parse a full URL with all parts. Guess port for well known protocols (so https://myhost/ returns a port of 80) 28 | void ParseURL(const char *URL, char **Proto, char **Host, char **Port, char **User, char **Password, char **Path, char **Args); 29 | 30 | //Parse a URL type that lacks a protocol or Args part, something like "myhost.com:22" 31 | const char *ParseHostDetails(const char *Data,char **Host,char **Port,char **User, char **Password); 32 | 33 | //Parse URL, but allow two arguments after the url '-password' and '-keyfile'. 34 | // e.g. ssh:user@host -keyfile ./id_rsa 35 | //These are really intended for ssh urls 36 | void ParseConnectDetails(const char *Str, char **Proto, char **Host, char **Port, char **User, char **Pass, char **InitDir); 37 | 38 | //for webpage-style partial urls, that can be relative to a parent url, resolve the url relative to it's parent 39 | //in order to produce a full url 40 | char *ResolveURL(char *RetStr, const char *Parent, const char *SubItem); 41 | 42 | #ifdef __cplusplus 43 | } 44 | #endif 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /Unicode.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_UNICODE_H 7 | #define LIBUSEFUL_UNICODE_H 8 | 9 | #include "includes.h" 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | // set the GLOBAL unicode level. 16 | // this is a global value that represents the unicode abilities of an OS or device. 17 | // Functions like 'UnicodeStr' and 'StrAddUnicodeChar' use this information in all their operations. 18 | 19 | // There are 3 values 20 | // level 0: no unicode support, unicode chars will be replaced with '?' 21 | // level 1: unicode support up to 0x800, chars above this will be replaced with '?' 22 | // level 2: unicode support up to 0x10000, chars above this will be replaced with '?' 23 | // level 3: unicode support up to 0x1FFFF, chars above this will be replaced with '?' 24 | void UnicodeSetUTF8(int level); 25 | 26 | //decode a single UTF-8 sequence pointed to by ptr and return it as an unsigned int, incrementing ptr to 27 | //point beyond the just decoded sequence 28 | unsigned int UnicodeDecode(const char **ptr); 29 | 30 | //encode a single unicode value ('Code') to a UTF-8 string using the supplied UnicodeLevel 31 | //rather than the global unicode level set by UnicodeSetUTF9 32 | char *UnicodeEncodeChar(char *RetStr, int UnicodeLevel, int Code); 33 | 34 | //encode a single unicode value ('Code') to a unicode string honoring the global unicode level 35 | char *UnicodeStr(char *RetStr, int Code); 36 | 37 | char *BufferAddUnicodeChar(char *RetStr, unsigned int len, unsigned int uchar); 38 | 39 | //encode a single unicode value ('Code') to a unicode string honoring the global unicode level, and append that string to a character string 40 | char *StrAddUnicodeChar(char *RetStr, int uchar); 41 | 42 | //lookup a unicode string by name at the specified Unicode support level 43 | char *UnicodeStrFromNameAtLevel(char *RetStr, int UnicodeLevel, const char *Name); 44 | 45 | //lookup a unicode string by name, honoring the global unicode level 46 | char *UnicodeStrFromName(char *RetStr, const char *Name); 47 | 48 | 49 | #ifdef __cplusplus 50 | } 51 | #endif 52 | 53 | #endif 54 | 55 | -------------------------------------------------------------------------------- /UnitsOfMeasure.c: -------------------------------------------------------------------------------- 1 | #include "UnitsOfMeasure.h" 2 | 3 | double ToPower(double val, double power) 4 | { 5 | double result=0; 6 | int i; 7 | 8 | result=val; 9 | for (i=1; i < power; i++) 10 | { 11 | result=result * val; 12 | } 13 | 14 | return(result); 15 | } 16 | 17 | 18 | double FromSIUnit(const char *Data, int Base) 19 | { 20 | double val; 21 | char *ptr=NULL; 22 | 23 | val=strtod(Data,&ptr); 24 | while (isspace(*ptr)) ptr++; 25 | switch (*ptr) 26 | { 27 | case 'k': 28 | val=val * Base; 29 | break; 30 | case 'M': 31 | val=val * ToPower(Base,2); 32 | break; 33 | case 'G': 34 | val=val * ToPower(Base,3); 35 | break; 36 | case 'T': 37 | val=val * ToPower(Base,4); 38 | break; 39 | case 'P': 40 | val=val * ToPower(Base,5); 41 | break; 42 | case 'E': 43 | val=val * ToPower(Base,6); 44 | break; 45 | case 'Z': 46 | val=val * ToPower(Base,7); 47 | break; 48 | case 'Y': 49 | val=val * ToPower(Base,8); 50 | break; 51 | } 52 | 53 | return(val); 54 | } 55 | 56 | 57 | 58 | const char *ToSIUnit(double Value, int Base, int Precision) 59 | { 60 | static char *Str=NULL; 61 | char *Fmt=NULL; 62 | double next; 63 | //Set to 0 to keep valgrind happy 64 | int i=0; 65 | char suffix=' ', *sufflist=" kMGTPEZY"; 66 | 67 | 68 | for (i=0; sufflist[i] !='\0'; i++) 69 | { 70 | next=ToPower(Base, i+1); 71 | if (next > Value) break; 72 | } 73 | 74 | if ((i > 0) && (sufflist[i] !='\0')) 75 | { 76 | Value=Value / ToPower(Base, i); 77 | suffix=sufflist[i]; 78 | Fmt=FormatStr(Fmt, "%%0.%df%%c", Precision); 79 | Str=FormatStr(Str,Fmt,(float) Value,suffix); 80 | } 81 | else 82 | { 83 | //here 'next' is the remainder, by casting 'Value' to a long we remove the 84 | //decimal component, then subtract from Value. This leaves us with *only* 85 | //the decimal places 86 | next=Value - (long) Value; 87 | if (Precision==0) Str=FormatStr(Str,"%ld",(long) Value); 88 | else 89 | { 90 | Fmt=FormatStr(Fmt, "%%0.%df", Precision); 91 | Str=FormatStr(Str,Fmt,(float) Value); 92 | } 93 | } 94 | 95 | 96 | DestroyString(Fmt); 97 | return(Str); 98 | } 99 | 100 | -------------------------------------------------------------------------------- /UnitsOfMeasure.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_MEASURE_H 7 | #define LIBUSEFUL_MEASURE_H 8 | 9 | #include "defines.h" 10 | #include "includes.h" 11 | 12 | /* 13 | Functions relating to convertion between SI Units/ Metric and and IEC units. So, is kilo 1024, or 1000? 14 | */ 15 | 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | 21 | //a simple power function included to allow libUseful to build without needing libmath/libm 22 | double ToPower(double val, double power); 23 | 24 | const char *ToSIUnit(double Value, int Base, int Precision); 25 | #define ToIEC(Value, Precision) (ToSIUnit((Value), 1024, Precision)) 26 | #define ToMetric(Value, Precision) (ToSIUnit((Value), 1000, Precision)) 27 | 28 | //Convert to and from metric 29 | double FromSIUnit(const char *Data, int Base); 30 | #define FromIEC(Value, Precision) (FromSIUnit((Value), 1024)) 31 | #define FromMetric(Value, Precision) (FromSIUnit((Value), 1000)) 32 | 33 | 34 | 35 | #ifdef __cplusplus 36 | } 37 | #endif 38 | 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /UnixSocket.c: -------------------------------------------------------------------------------- 1 | #include "UnixSocket.h" 2 | #include 3 | #include 4 | #include 5 | #include "Errors.h" 6 | 7 | // crazyshit function because different implementations treat 8 | // sun_path differently, so we have to derive a safe length for it! 9 | void sun_set_path(struct sockaddr_un *sa, const char *Path) 10 | { 11 | int len, val; 12 | char *ptr1, *ptr2; 13 | 14 | memset(sa,0,sizeof(struct sockaddr_un)); 15 | sa->sun_family=AF_UNIX; 16 | ptr1=sa->sun_path; 17 | ptr2=(char *) sa; //sa is already a pointer, so we don't need & 18 | 19 | len=sizeof(struct sockaddr_un) - (ptr1-ptr2); 20 | 21 | if (len > 0) 22 | { 23 | len--; //force room for terminating \0 24 | 25 | //all hail strlcpy, makes life easier 26 | #ifdef strlcpy 27 | strlcpy(sa->sun_path,Path,len); 28 | 29 | //else grrrr 30 | #else 31 | val=StrLen(Path); 32 | if (val < len) len=val; 33 | strncpy(sa->sun_path,Path,len); 34 | sa->sun_path[len]='\0'; 35 | #endif 36 | 37 | } 38 | 39 | } 40 | 41 | 42 | int OpenUnixSocket(const char *Path, int Type) 43 | { 44 | int sock; 45 | struct sockaddr_un sa; 46 | int val; 47 | 48 | if (Type==0) Type=SOCK_STREAM; 49 | 50 | sock=socket(PF_UNIX, Type, FALSE); 51 | if (sock==-1) return(-1); 52 | 53 | sun_set_path(&sa, Path); 54 | val=sizeof(sa); 55 | if (connect(sock,(struct sockaddr *) &sa,val)==0) return(sock); 56 | 57 | close(sock); 58 | return(-1); 59 | } 60 | 61 | 62 | 63 | int STREAMConnectUnixSocket(STREAM *S, const char *Path, int ConType) 64 | { 65 | 66 | S->in_fd=OpenUnixSocket(Path, ConType); 67 | if (S->in_fd==-1) return(FALSE); 68 | S->out_fd=S->in_fd; 69 | S->Type=ConType; 70 | 71 | return(TRUE); 72 | } 73 | 74 | 75 | int UnixSocketBindPath(int sock, const char *Path) 76 | { 77 | struct sockaddr_un sa; 78 | socklen_t salen; 79 | 80 | unlink(Path); 81 | sun_set_path(&sa, Path); 82 | salen=sizeof(struct sockaddr_un); 83 | if (bind(sock,(struct sockaddr *) &sa, salen)==0) return(TRUE); 84 | 85 | return(FALSE); 86 | } 87 | 88 | 89 | int UnixServerInit(int Type, const char *Path) 90 | { 91 | int sock; 92 | int result; 93 | 94 | //if (Type==0) Type=SOCK_STREAM; 95 | sock=socket(PF_UNIX, Type, 0); 96 | 97 | if (sock < 0) 98 | { 99 | RaiseError(ERRFLAG_ERRNO, "UnixServerInit","failed to create a unix socket."); 100 | return(-1); 101 | } 102 | 103 | //No reason to pass server/listen sockets across an exec 104 | fcntl(sock, F_SETFD, FD_CLOEXEC); 105 | 106 | if (UnixSocketBindPath(sock, Path)) 107 | { 108 | if (Type==SOCK_STREAM) 109 | { 110 | result=listen(sock, 10); 111 | if (result==0) return(sock); 112 | RaiseError(ERRFLAG_ERRNO, "UnixServerInit","failed to 'listen' on unix sock %s.",Path); 113 | } 114 | else return(sock); 115 | } 116 | else RaiseError(ERRFLAG_ERRNO, "UnixServerInit","failed to bind unix sock to %s.",Path); 117 | 118 | 119 | close(sock); 120 | return(-1); 121 | } 122 | 123 | 124 | 125 | int UnixServerAccept(int ServerSock) 126 | { 127 | struct sockaddr_un sa; 128 | socklen_t salen; 129 | int sock; 130 | 131 | salen=sizeof(sa); 132 | sock=accept(ServerSock,(struct sockaddr *) &sa,&salen); 133 | return(sock); 134 | } 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /UnixSocket.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_UNIXSOCK_H 7 | #define LIBUSEFUL_UNIXSOCK_H 8 | 9 | #include "Stream.h" 10 | #include "defines.h" 11 | #include "includes.h" 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | 18 | 19 | int UnixSocketBindPath(int sock, const char *Path); 20 | 21 | //create a unix (filesystem not network) socket. 'Type' can be 'SOCK_STREAM' or 'SOCK_DGRAM'. 22 | //return value is file descriptor of socket, or -1 on error 23 | int UnixServerInit(int Type, const char *Path); 24 | 25 | //accept a new connection on a unix server sock. return value is file descriptor for connection 26 | //or -1 on error 27 | int UnixServerAccept(int ServerSock); 28 | 29 | /*you shouldn't normally need to use these functions, the same thing can be achieved by 30 | 31 | S=STREAMOpen("unix:/tmp/mysock", ""); 32 | 33 | or 34 | 35 | S=STREAMOpen("unixdgram:/tmp/mysock", ""); 36 | */ 37 | 38 | int OpenUnixSocket(const char *Path, int SockType); 39 | int STREAMConnectUnixSocket(STREAM *S, const char *Path, int SockType); 40 | 41 | 42 | #ifdef __cplusplus 43 | } 44 | #endif 45 | 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /Users.c: -------------------------------------------------------------------------------- 1 | #include "Users.h" 2 | 3 | int LookupUID(const char *User) 4 | { 5 | struct passwd *pwent; 6 | 7 | if (! StrValid(User)) return(-1); 8 | pwent=getpwnam(User); 9 | if (! pwent) return(-1); 10 | return(pwent->pw_uid); 11 | } 12 | 13 | 14 | int LookupGID(const char *Group) 15 | { 16 | struct group *grent; 17 | 18 | if (! StrValid(Group)) return(-1); 19 | grent=getgrnam(Group); 20 | if (! grent) return(-1); 21 | return(grent->gr_gid); 22 | } 23 | 24 | 25 | const char *LookupUserName(uid_t uid) 26 | { 27 | struct passwd *pwent; 28 | 29 | pwent=getpwuid(uid); 30 | if (! pwent) return(""); 31 | return(pwent->pw_name); 32 | } 33 | 34 | 35 | const char *LookupGroupName(gid_t gid) 36 | { 37 | struct group *grent; 38 | 39 | grent=getgrgid(gid); 40 | if (! grent) return(""); 41 | return(grent->gr_name); 42 | } 43 | 44 | 45 | int SwitchUID(int uid) 46 | { 47 | struct passwd *pw; 48 | 49 | pw=getpwuid(uid); 50 | 51 | //must initgroups before switch user, as the user we switch too 52 | //may not have permission to do so 53 | #ifdef HAVE_INITGROUPS 54 | if (pw) initgroups(pw->pw_name, 0); 55 | #endif 56 | 57 | #ifdef HAVE_SETRESUID 58 | if ((uid==-1) || (setresuid(uid,uid,uid) !=0)) 59 | #else 60 | if ((uid==-1) || (setreuid(uid,uid) !=0)) 61 | #endif 62 | { 63 | RaiseError(ERRFLAG_ERRNO, "SwitchUID", "Switch user failed. uid=%d",uid); 64 | if (LibUsefulGetBool("SwitchUserAllowFail")) return(FALSE); 65 | exit(1); 66 | } 67 | 68 | if (pw) 69 | { 70 | setenv("HOME",pw->pw_dir,TRUE); 71 | setenv("USER",pw->pw_name,TRUE); 72 | 73 | } 74 | return(TRUE); 75 | } 76 | 77 | 78 | int SwitchUser(const char *NewUser) 79 | { 80 | int uid; 81 | 82 | uid=LookupUID(NewUser); 83 | if (uid==-1) return(FALSE); 84 | return(SwitchUID(uid)); 85 | } 86 | 87 | 88 | int SwitchGID(int gid) 89 | { 90 | if ((gid==-1) || (setgid(gid) !=0)) 91 | { 92 | RaiseError(ERRFLAG_ERRNO, "SwitchGID", "Switch group failed. gid=%d",gid); 93 | if (LibUsefulGetBool("SwitchGroupAllowFail")) return(FALSE); 94 | exit(1); 95 | } 96 | return(TRUE); 97 | } 98 | 99 | int SwitchGroup(const char *NewGroup) 100 | { 101 | int gid; 102 | 103 | gid=LookupGID(NewGroup); 104 | if (gid==-1) return(FALSE); 105 | return(SwitchGID(gid)); 106 | } 107 | 108 | 109 | 110 | 111 | const char *GetUserHomeDir(const char *User) 112 | { 113 | struct passwd *pwent; 114 | 115 | if (! StrValid(User)) return(NULL); 116 | pwent=getpwnam(User); 117 | if (! pwent) 118 | { 119 | RaiseError(ERRFLAG_ERRNO, "getpwuid","Failed to get info for user [%s]", User); 120 | return(NULL); 121 | } 122 | return(pwent->pw_dir); 123 | } 124 | 125 | 126 | 127 | const char *GetCurrUserHomeDir() 128 | { 129 | struct passwd *pwent; 130 | 131 | pwent=getpwuid(getuid()); 132 | if (! pwent) 133 | { 134 | RaiseError(ERRFLAG_ERRNO, "getpwuid","Failed to get info for current user"); 135 | return(NULL); 136 | } 137 | return(pwent->pw_dir); 138 | } 139 | 140 | -------------------------------------------------------------------------------- /Users.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_USERS_H 7 | #define LIBUSEFUL_USERS_H 8 | 9 | #include "defines.h" 10 | #include "includes.h" 11 | 12 | /* 13 | A number of general functions that don't fit anywhere else 14 | */ 15 | 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | 21 | 22 | //lookup uid for User 23 | int LookupUID(const char *User); 24 | 25 | //lookup gid for Group 26 | int LookupGID(const char *Group); 27 | 28 | //lookup username from uid 29 | const char *LookupUserName(uid_t uid); 30 | 31 | //lookup groupname from gid 32 | const char *LookupGroupName(gid_t gid); 33 | 34 | 35 | //switch user or group by id (call SwitchGID first, or you may not have permissions to switch user) 36 | int SwitchUID(int uid); 37 | int SwitchGID(int gid); 38 | 39 | //switch user or group by name (call SwitchGgroup first, or you may not have permissions to switch user) 40 | int SwitchUser(const char *User); 41 | int SwitchGroup(const char *Group); 42 | 43 | //returns a string pointing to a users home directory. DO NOT FREE THIS STRING. Take a copy of it, as it's 44 | //an internal buffer and will change on the next call to this function 45 | const char *GetUserHomeDir(const char *User); 46 | 47 | 48 | //returns a string pointing to the CURRENT USER'S home directory. 49 | // DO NOT FREE THIS STRING. Take a copy of it, as it's 50 | //an internal buffer and will change on the next call to this function 51 | const char *GetCurrUserHomeDir(); 52 | 53 | 54 | #ifdef __cplusplus 55 | } 56 | #endif 57 | 58 | 59 | #endif 60 | 61 | 62 | -------------------------------------------------------------------------------- /WebSocket.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_WEBSOCKET_H 7 | #define LIBUSEFUL_WEBSOCKET_H 8 | 9 | #include "Stream.h" 10 | 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | 17 | int WebSocketSendBytes(STREAM *S, const char *Data, int Len); 18 | int WebSocketReadBytes(STREAM *S, char *Data, int Len); 19 | STREAM *WebSocketOpen(const char *URL, const char *Config); 20 | int WebSocketAccept(STREAM *S); 21 | 22 | 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /base64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * base64.c -- base-64 conversion routines. 3 | * 4 | * This base64 code is adapted from code from the fetchmail program. 5 | * It is GPL v2 or later as covered in fetchmail's 'COPYING' file. 6 | * It is believed to be written written by Eric S Raymond. 7 | * 8 | * This base 64 encoding is defined in RFC2045 section 6.8, 9 | * "Base64 Content-Transfer-Encoding", but lines must not be broken in the 10 | * scheme used here. 11 | */ 12 | #include 13 | #include "Encodings.h" 14 | 15 | 16 | #define BAD -1 17 | #define DECODE64(base64val, c) (isascii(c) ? base64val[c] : BAD) 18 | 19 | 20 | 21 | void Radix64frombits(unsigned char *out, const unsigned char *in, int inlen, const char *base64digits, char pad) 22 | /* raw bytes in quasi-big-endian order to base 64 string (NUL-terminated) */ 23 | { 24 | for (; inlen >= 3; inlen -= 3) 25 | { 26 | *out++ = base64digits[in[0] >> 2]; 27 | *out++ = base64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)]; 28 | *out++ = base64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)]; 29 | *out++ = base64digits[in[2] & 0x3f]; 30 | in += 3; 31 | } 32 | 33 | if (inlen > 0) 34 | { 35 | unsigned char fragment; 36 | 37 | *out++ = base64digits[in[0] >> 2]; 38 | fragment = (in[0] << 4) & 0x30; 39 | if (inlen > 1) 40 | fragment |= in[1] >> 4; 41 | *out++ = base64digits[fragment]; 42 | *out++ = (inlen < 2) ? pad : base64digits[(in[1] << 2) & 0x3c]; 43 | *out++ = pad; 44 | } 45 | *out = '\0'; 46 | } 47 | 48 | 49 | 50 | void to64frombits(char *out, const char *in, int inlen) 51 | { 52 | Radix64frombits((unsigned char *) out, (const unsigned char *) in, inlen, BASE64_CHARS,'='); 53 | } 54 | 55 | 56 | 57 | 58 | int Radix64tobits(char *out, const char *in, const char *base64digits, char pad) 59 | /* base 64 to raw bytes in quasi-big-endian order, returning count of bytes */ 60 | { 61 | int len = 0, i=0; 62 | char base64vals[255]; 63 | register unsigned char digit1, digit2, digit3, digit4; 64 | const unsigned char *ptr, *end; 65 | 66 | for (ptr=(const unsigned char *) base64digits; *ptr !='\0'; ptr++) 67 | { 68 | base64vals[*ptr]=i; 69 | i++; 70 | } 71 | 72 | ptr=in; 73 | end=in+StrLen(in); 74 | if (ptr[0] == '+' && ptr[1] == ' ') ptr += 2; 75 | if (*ptr == '\r') return(0); 76 | 77 | 78 | 79 | do 80 | { 81 | digit1 = ptr[0]; 82 | if (DECODE64(base64vals, digit1) == BAD) return(-1); 83 | digit2 = ptr[1]; 84 | if (DECODE64(base64vals, digit2) == BAD) return(-1); 85 | digit3 = ptr[2]; 86 | if ((digit3 != pad) && (DECODE64(base64vals, digit3) == BAD)) return(-1); 87 | digit4 = ptr[3]; 88 | if ((digit4 != pad) && (DECODE64(base64vals, digit4) == BAD)) return(-1); 89 | ptr += 4; 90 | *out++ = (DECODE64(base64vals, digit1) << 2) | (DECODE64(base64vals, digit2) >> 4); 91 | ++len; 92 | if (digit3 != pad) 93 | { 94 | *out++ = ((DECODE64(base64vals, digit2) << 4) & 0xf0) | (DECODE64(base64vals, digit3) >> 2); 95 | ++len; 96 | if (digit4 != pad) 97 | { 98 | *out++ = ((DECODE64(base64vals, digit3) << 6) & 0xc0) | DECODE64(base64vals, digit4); 99 | ++len; 100 | } 101 | } 102 | } 103 | while (*ptr && (*ptr != '\r') && (ptr < end) && (digit4 != pad)); 104 | 105 | return (len); 106 | } 107 | 108 | 109 | 110 | int from64tobits(char *out, const char *in) 111 | { 112 | return(Radix64tobits(out, in, BASE64_CHARS,'=')); 113 | } 114 | 115 | /* base64.c ends here */ 116 | -------------------------------------------------------------------------------- /base64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: GPL-2.0 3 | * 4 | * This base64 code is adapted from code from the fetchmail program. 5 | * It is GPL v2 or later and believed written by Eric S Raymond. 6 | * 7 | */ 8 | 9 | 10 | #ifndef BASE_64_H 11 | #define BASE_64_H 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | void Radix64frombits(unsigned char *out, const unsigned char *in, int inlen, const char *base64digits, char pad); 18 | int Radix64tobits(char *out, const char *in, const char *base64digits, char pad); 19 | 20 | void to64frombits(unsigned char *out, const unsigned char *in, int inlen); 21 | int from64tobits(char *out, const char *in); 22 | 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /baseXX.c: -------------------------------------------------------------------------------- 1 | #include "baseXX.h" 2 | 3 | 4 | 5 | /* This is surely not the fastest baseXX decoder, it is written for understanding/legiblity, not speed. 6 | * first we convert baseXX into binary, as a string of '1' and '0' characters 7 | * Then we work through this string converting it into eight-bit values. 8 | * The reason it's done this way is that it's tough to handle 'overlapping bits' when dealing with characters 9 | * that represent 5-bit or 6-bit chunks of a string of 8-bit values, and the resulting code of trying to do it all 10 | * with bit-shifting is rather unreadable 11 | */ 12 | 13 | //MaxChunk is the highest bit of a chunk, 16 for base32 and 32 for base64 14 | char *baseXXtobinary(char *RetStr, const char *In, const char *Encoder, int MaxChunk) 15 | { 16 | const char *ptr, *found; 17 | uint32_t val=0, bit; 18 | 19 | for (ptr=In; (*ptr != '\0') ; ptr++) 20 | { 21 | //find the position in the base32 characterset. That position is the 'value' of the character 22 | found=strchr(Encoder, *ptr); 23 | if (found) val=(found - Encoder); 24 | else break; 25 | 26 | bit=MaxChunk; 27 | 28 | //unpack the value into a string of 1's and 0's. As we add 1's and 0's from later characters 29 | //we will get a contiguous stream of 1's and 0's that we can then break up into 8-bit chunks 30 | while (bit > 0) 31 | { 32 | if (val & bit) RetStr=CatStr(RetStr, "1"); 33 | else RetStr=CatStr(RetStr, "0"); 34 | bit=bit >> 1; 35 | } 36 | } 37 | 38 | return(RetStr); 39 | } 40 | 41 | 42 | int baseXXdecode(unsigned char *Out, const char *In, const char *Encoder, int MaxChunk) 43 | { 44 | char *Tempstr=NULL; 45 | unsigned char *p_Out; 46 | const char *ptr, *end; 47 | uint32_t val; 48 | 49 | Tempstr=baseXXtobinary(Tempstr, In, Encoder, MaxChunk); 50 | 51 | val=StrLen(Tempstr); 52 | val -= val % 8; 53 | StrUnsafeTrunc(Tempstr, val); 54 | end=Tempstr+val; 55 | 56 | p_Out=Out; 57 | 58 | for (ptr=Tempstr; ptr < end; ptr+=8) 59 | { 60 | val=parse_bcd_byte(ptr); 61 | *p_Out=val & 0xFF; 62 | p_Out++; 63 | } 64 | *p_Out='\0'; 65 | 66 | val=p_Out - Out; 67 | 68 | Destroy(Tempstr); 69 | 70 | return(val); 71 | } 72 | 73 | 74 | 75 | 76 | char *baseXXencode(char *RetStr, const char *Input, int Len, int ChunkSize, const char *Encoder, char Pad) 77 | { 78 | char *Tempstr=NULL, *BCD=NULL; 79 | const char *ptr, *end; 80 | int val, len=0; 81 | 82 | 83 | RetStr=CopyStr(RetStr, ""); 84 | BCD=encode_bcd_bytes(BCD, (unsigned const char *) Input, Len); 85 | end=BCD+StrLen(BCD); 86 | 87 | for (ptr=BCD; ptr < end; ptr+=ChunkSize) 88 | { 89 | Tempstr=CopyStrLen(Tempstr, ptr, ChunkSize); 90 | Tempstr=PadStrTo(Tempstr, '0', ChunkSize); 91 | val=(int) parse_bcd_byte(Tempstr); 92 | RetStr=AddCharToBuffer(RetStr, len, Encoder[val]); 93 | len++; 94 | } 95 | 96 | val=StrLen(RetStr) % 8; 97 | if (val > 0) 98 | { 99 | for (; val < 8; val++) RetStr=AddCharToStr(RetStr, Pad); 100 | } 101 | 102 | Destroy(Tempstr); 103 | Destroy(BCD); 104 | return(RetStr); 105 | } 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /baseXX.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2025 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | 7 | #ifndef LIBUSEFUL_BASEXX_H 8 | #define LIBUSEFUL_BASEXX_H 9 | 10 | #include "includes.h" 11 | 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | 18 | //the mysterious '5' in baseXXencode is the number of bits that can be encoded in one character of base32 19 | #define base32encode(Out, In, Len, Encoder, Pad) (baseXXencode((Out), (In), (Len), 5, (Encoder), (Pad))) 20 | //the mysterious '16' in baseXXdecode is the highest bit that can be encoded in base32 21 | #define base32decode(Out, In, Encoder) (baseXXdecode((Out), (In), (Encoder), 16)) 22 | 23 | //the mysterious '6' in baseXXencode is the number of bits that can be encoded in one character of base64 24 | #define base64encode(Out, In, Len, Encoder, Pad) (baseXXencode((Out), (In), (Len), 6, (Encoder), (Pad))) 25 | //the mysterious '32' in baseXXdecode is the highest bit that can be encoded in base64 26 | #define base64decode(Out, In, Encoder) (baseXXdecode((Out), (In), (Encoder) , 32)) 27 | 28 | int baseXXdecode(unsigned char *Out, const char *In, const char *Encoder, int MaxChunk); 29 | char *baseXXencode(char *Out, const char *Input, int Len, int ChunkSize, const char *Encoder, char Pad); 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /crc32.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003, Dominik Reichl , Germany. 3 | * SPDX-License-Identifier: GPL-2.0 4 | */ 5 | 6 | /* 7 | --------------------------------------------------------------------------- 8 | Copyright (c) 2003, Dominik Reichl , Germany. 9 | All rights reserved. 10 | 11 | Distributed under the terms of the GNU General Public License v2. 12 | 13 | This software is provided 'as is' with no explicit or implied warranties 14 | in respect of its properties, including, but not limited to, correctness 15 | and/or fitness for purpose. 16 | --------------------------------------------------------------------------- 17 | */ 18 | 19 | #ifndef ___CRC32_H___ 20 | #define ___CRC32_H___ 21 | 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | void crc32Init(unsigned long *pCrc32); 28 | void crc32Update(unsigned long *pCrc32, unsigned char *pData, unsigned long uSize); 29 | void crc32Finish(unsigned long *pCrc32); 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | 35 | #endif /* ___CRC32_H___ */ 36 | -------------------------------------------------------------------------------- /defines.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_DEFINES_H 7 | #define LIBUSEFUL_DEFINES_H 8 | 9 | //this file is for general, globally defined values like 'TRUE' and 'FALSE' 10 | 11 | #ifndef __cplusplus 12 | 13 | 14 | //this mostly exists for libUseful-lua, so that swig can recognize functions that return boolean values 15 | //we don't want to define this if we're using libUseful under c++ though, as c++ already has a boolean 16 | //datatype, and if libUseful is the first thing included before the c++ standard includes, then it will 17 | //go ahead and define it's own bool type 18 | #define bool int 19 | #endif 20 | 21 | #define FALSE 0 22 | #define TRUE 1 23 | 24 | #define FTIMEOUT -2 25 | 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | //this is a basic call-back function type that gets used in a number of places 32 | typedef int (*BASIC_FUNC)(void *Data, int Flags); 33 | 34 | 35 | #ifdef __cplusplus 36 | } 37 | #endif 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /examples/CMON.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | main() 4 | { 5 | PARSER *DB; 6 | STREAM *S; 7 | char *Tempstr=NULL; 8 | 9 | S=STREAMOpen("/tmp/wallpaper_mgr.db", "r"); 10 | Tempstr=STREAMReadLine(Tempstr, S); 11 | STREAMClose(S); 12 | 13 | DB=ParserParseDocument("cmon", Tempstr); 14 | 15 | Destroy(Tempstr); 16 | } 17 | -------------------------------------------------------------------------------- /examples/Config.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | main() 4 | { 5 | STREAM *S; 6 | char *Tempstr=NULL; 7 | PARSER *P; 8 | 9 | S=STREAMOpen("asciiblast.conf", "r"); 10 | Tempstr=STREAMReadDocument(Tempstr, S); 11 | STREAMClose(S); 12 | 13 | P=ParserParseDocument("config", Tempstr); 14 | 15 | if (P) 16 | { 17 | Tempstr=CopyStr(Tempstr, ""); 18 | Tempstr=ParserExport(Tempstr, "yaml", P); 19 | printf("%s\n", Tempstr); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /examples/Errors.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | //this program demostrates some aspects of the libUseful error system 4 | 5 | 6 | //this function should generate two errors 7 | int TestFunction() 8 | { 9 | STREAM *S; 10 | 11 | // by default failed network connections raise errors. However, if you uncomment 'LibUsefulSetValue("Error:IgnoreIP","true");' 12 | // in main, then network errors will be ignored, and we will have to pass 'E' in the second argument to STREAMOpen here 13 | S=STREAMOpen("tcp://nonexistenthost.fdafelfhgexy.com",""); 14 | STREAMClose(S); 15 | 16 | // note use of 'E' flag to cause an error to be raised if this file files to open 17 | S=STREAMOpen("/tmp/nonexistentfile","rE"); 18 | STREAMClose(S); 19 | 20 | return(FALSE); 21 | } 22 | 23 | 24 | void HandleErrors() 25 | { 26 | ListNode *Errors, *Curr; 27 | TError *Err; 28 | 29 | Errors=ErrorsGet(); 30 | Curr=ListGetNext(Errors); 31 | while (Curr) 32 | { 33 | Err=(TError *) Curr->Item; 34 | printf("Error during %s at line %d in file '%s': '%s'. errno was %d '%s' \n",Err->where, Err->line, Err->file, Err->msg, Err->errval, strerror(Err->errval)); 35 | Curr=ListGetNext(Curr); 36 | } 37 | 38 | fflush(NULL); 39 | exit(1); 40 | } 41 | 42 | main() 43 | { 44 | 45 | //Suppress libUseful's own error print out, we are going to handle and print ouf the errors ourselves 46 | LibUsefulSetValue("Error:Silent","true"); 47 | 48 | //Setting this causes network errors to be ignored 49 | //LibUsefulSetValue("Error:IgnoreIP","true"); 50 | 51 | if (! TestFunction()) HandleErrors(); 52 | 53 | 54 | } 55 | -------------------------------------------------------------------------------- /examples/FileCopy.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | main(int argc, char *argv[]) 4 | { 5 | STREAM *In, *Out; 6 | 7 | printf("a1=%s a2=%s\n",argv[1], argv[2]); 8 | In=STREAMOpen(argv[1], "r"); 9 | STREAMCopy(In, argv[2]); 10 | STREAMClose(In); 11 | STREAMClose(Out); 12 | } 13 | -------------------------------------------------------------------------------- /examples/HMAC.c: -------------------------------------------------------------------------------- 1 | #include "../Hash.h" 2 | 3 | 4 | void HMACTest(const char *Type, const char *Text) 5 | { 6 | char *Tempstr=NULL, *Output=NULL; 7 | int len; 8 | 9 | len=HMACBytes(&Output, Type, "key", 3, Text, StrLen(Text), ENCODE_HEX); 10 | printf("%s: %s\n", Type, Output); 11 | 12 | Destroy(Tempstr); 13 | Destroy(Output); 14 | } 15 | 16 | main() 17 | { 18 | HMACTest("md5", "The quick brown fox jumps over the lazy dog"); 19 | HMACTest("sha1", "The quick brown fox jumps over the lazy dog"); 20 | HMACTest("sha256", "The quick brown fox jumps over the lazy dog"); 21 | HMACTest("sha512", "The quick brown fox jumps over the lazy dog"); 22 | } 23 | -------------------------------------------------------------------------------- /examples/Hash.c: -------------------------------------------------------------------------------- 1 | #include "../Hash.h" 2 | 3 | 4 | main() 5 | { 6 | char *Tempstr=NULL, *Types=NULL, *Type=NULL; 7 | const char *ptr; 8 | 9 | Types=HashAvailableTypes(Types); 10 | printf("HashTypes: %s\n\n", Types); 11 | 12 | ptr=GetToken(Types, ",", &Type, 0); 13 | while (ptr) 14 | { 15 | HashBytes(&Tempstr, Type, "testing123", 10, ENCODE_HEX); 16 | printf("%s: %s\n", Type, Tempstr); fflush(NULL); 17 | ptr=GetToken(ptr, ",", &Type, 0); 18 | } 19 | 20 | Destroy(Tempstr); 21 | } 22 | -------------------------------------------------------------------------------- /examples/HttpServer.c: -------------------------------------------------------------------------------- 1 | #include "libUseful-5/libUseful.h" 2 | 3 | main() 4 | { 5 | STREAM *Serv, *S; 6 | ListNode *Connections; 7 | char *Doc=NULL; 8 | 9 | //Serv=STREAMServerNew("http://127.0.0.1:4040", "rw auth='password-file:/tmp/test.pw'"); 10 | Serv=STREAMServerNew("http://127.0.0.1:4040", "rw auth='ip:192.168.2.1,127.0.0.1'"); 11 | Connections=ListCreate(); 12 | ListAddItem(Connections, Serv); 13 | 14 | while (1) 15 | { 16 | STREAMSelect(Connections, NULL); 17 | S=STREAMServerAccept(Serv); 18 | if (! STREAMAuth(S)) HTTPServerSendHeaders(S, 401, "Authentication Required", "WWW-Authenticate=Basic"); 19 | else 20 | { 21 | printf("GOT: %d %s %s\n", STREAMAuth(S), STREAMGetValue(S, "HTTP:Method"), STREAMGetValue(S, "HTTP:URL")); 22 | 23 | Doc=CopyStr(Doc, "

Testing testing 1234.

This is a test, using html

"); 24 | HTTPServerSendDocument(S, Doc, StrLen(Doc), "text/html", ""); 25 | //HTTPServerSendFile(S, "/home/colum/C444CBC4.mp4", "", ""); 26 | } 27 | STREAMClose(S); 28 | } 29 | 30 | Destroy(Doc); 31 | } 32 | -------------------------------------------------------------------------------- /examples/JSON.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | main() 4 | { 5 | PARSER *P; 6 | char *Tempstr=NULL; 7 | 8 | P=ParserParseDocument("json", "{'this': 'this is some text','that': 'that is some text','the other': 1234, 'subitem': {'stuff in a subitem': 'whatever', 'contents': 'with contents'}}"); 9 | Tempstr=ParserExport(Tempstr, "json", P); 10 | Tempstr=ParserExport(Tempstr, "xml", P); 11 | printf("%s\n", Tempstr); 12 | 13 | Destroy(Tempstr); 14 | } 15 | -------------------------------------------------------------------------------- /examples/LineEdit.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | main() 4 | { 5 | TLineEdit *LE; 6 | STREAM *Term; 7 | char *Tempstr=NULL; 8 | int inchar, pos; 9 | 10 | 11 | Term=STREAMFromDualFD(0,1); 12 | TerminalInit(Term, TERM_RAWKEYS | TERM_SAVEATTRIBS); 13 | 14 | LE=LineEditCreate(LINE_EDIT_HISTORY); 15 | LineEditSetMaxHistory(LE, 3); 16 | while (1) 17 | { 18 | inchar=TerminalReadChar(Term); 19 | pos=LineEditHandleChar(LE, inchar); 20 | if (pos == LINE_EDIT_ENTER) 21 | { 22 | Tempstr=LineEditDone(Tempstr, LE); 23 | printf("\rYou Typed: %s\n", Tempstr); 24 | } 25 | else 26 | { 27 | printf("\r%s ", LE->Line); 28 | Tempstr=CopyStrLen(Tempstr, LE->Line, LE->Cursor); 29 | printf("\r%s", Tempstr); 30 | } 31 | fflush(NULL); 32 | } 33 | 34 | Destroy(Tempstr); 35 | } 36 | -------------------------------------------------------------------------------- /examples/ListLimits.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | 4 | void Destroyer(void *Item) 5 | { 6 | printf("DESTROY: %s\n", (const char *) Item); 7 | Destroy(Item); 8 | } 9 | 10 | 11 | main() 12 | { 13 | ListNode *Map; 14 | char *Tempstr=NULL; 15 | int i; 16 | 17 | Map=MapCreate(128, 0); 18 | ListSetMaxItems(Map, 3, Destroyer); 19 | 20 | for (i=0; i < 100000; i++) 21 | { 22 | Tempstr=FormatStr(Tempstr, "%d", i); 23 | ListAddNamedItem(Map, Tempstr, CopyStr(NULL,Tempstr)); 24 | } 25 | 26 | MapDumpSizes(Map); 27 | 28 | Destroy(Tempstr); 29 | } 30 | -------------------------------------------------------------------------------- /examples/Makefile: -------------------------------------------------------------------------------- 1 | LIBS=../libUseful.a -lssl -lcrypto -lz #-lcap 2 | 3 | all: 4 | gcc -oJSON.exe JSON.c $(LIBS) 5 | gcc -oCMON.exe CMON.c $(LIBS) 6 | gcc -oYAML.exe YAML.c $(LIBS) 7 | gcc -oHash.exe Hash.c $(LIBS) 8 | gcc -oHMAC.exe HMAC.c $(LIBS) 9 | gcc -oTerminal.exe Terminal.c $(LIBS) 10 | gcc -oTermBar.exe TermBar.c $(LIBS) 11 | gcc -oTermMenu.exe TermMenu.c $(LIBS) 12 | gcc -oTermChoice.exe TermChoice.c $(LIBS) 13 | gcc -oTermProgress.exe TermProgress.c $(LIBS) 14 | gcc -oTermCalendar.exe TermCalendar.c $(LIBS) 15 | gcc -oVars.exe Vars.c $(LIBS) 16 | gcc -oParseRSS.exe ParseRSS.c $(LIBS) 17 | gcc -oFileCopy.exe FileCopy.c $(LIBS) 18 | gcc -oTokenize.exe Tokenize.c $(LIBS) 19 | gcc -oSpawnContainer.exe SpawnContainer.c $(LIBS) 20 | gcc -oMaps.exe Maps.c $(LIBS) 21 | gcc -oTTYTest.exe TTYTest.c $(LIBS) 22 | gcc -oErrors.exe Errors.c $(LIBS) 23 | gcc -ossh-time.exe ssh-time.c $(LIBS) 24 | gcc -ossh-tunnel.exe ssh-tunnel.c $(LIBS) 25 | gcc -ossh-listfiles.exe ssh-listfiles.c $(LIBS) 26 | gcc -oConfig.exe Config.c $(LIBS) 27 | gcc -oStrLen.exe StrLen.c $(LIBS) 28 | gcc -oSSLClient.exe SSLClient.c $(LIBS) 29 | gcc -oSysInfo.exe SysInfo.c $(LIBS) 30 | gcc -oWebsocket.exe Websocket.c $(LIBS) 31 | gcc -oHttpServer.exe HttpServer.c $(LIBS) 32 | gcc -oPasswordFile.exe PasswordFile.c $(LIBS) 33 | gcc -obase32.exe base32.c $(LIBS) 34 | gcc -obase64.exe base64.c $(LIBS) 35 | gcc -ouudecode.exe uudecode.c $(LIBS) 36 | gcc -ononewprivs.exe nonewprivs.c $(LIBS) 37 | gcc -ochroot.exe chroot.c $(LIBS) 38 | gcc -omovetest.exe movetest.c $(LIBS) 39 | gcc -oencrypt.exe encrypt.c $(LIBS) 40 | gcc -odecrypt.exe decrypt.c $(LIBS) 41 | gcc -opbkdf2.exe pbkdf2.c $(LIBS) 42 | gcc -ofmtduration.exe fmtduration.c $(LIBS) 43 | gcc -ocalendar.exe calendar.c $(LIBS) 44 | gcc -oLineEdit.exe LineEdit.c $(LIBS) 45 | gcc -ocontainer.exe container.c $(LIBS) 46 | gcc -oListLimits.exe ListLimits.c $(LIBS) 47 | 48 | seccomp.exe: seccomp.c 49 | gcc -oseccomp.exe seccomp.c $(LIBS) 50 | 51 | clean: 52 | rm -f *.exe 53 | -------------------------------------------------------------------------------- /examples/Maps.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | 4 | //This will download a testfile which is a list of the top million websites, load it into a map or list, and then do lookups 5 | //in it to demonstrate the speed or otherwise of these 6 | 7 | 8 | 9 | void Lookup(ListNode *Map, const char *Name) 10 | { 11 | ListNode *Node; 12 | 13 | Node=ListFindNamedItem(Map, Name); 14 | //if (Node) printf("%s %s %s\n",Node->Tag,Node->Item,Node->Prev->Item); 15 | } 16 | 17 | 18 | void DownloadTestFile() 19 | { 20 | STREAM *In, *Out; 21 | 22 | In=STREAMOpen("http://downloads.majestic.com/majestic_million.csv","r"); 23 | if (In) 24 | { 25 | Out=STREAMOpen("majestic_million.csv","w"); 26 | STREAMSendFile(In, Out, 0, SENDFILE_LOOP); 27 | STREAMClose(Out); 28 | STREAMClose(In); 29 | } 30 | 31 | } 32 | 33 | 34 | 35 | void LoadCSV(ListNode *List) 36 | { 37 | char *Tempstr=NULL, *Rank=NULL, *Site=NULL; 38 | const char *ptr; 39 | STREAM *S; 40 | 41 | S=STREAMOpen("majestic_million.csv","r"); 42 | Tempstr=STREAMReadLine(Tempstr, S); 43 | while (Tempstr) 44 | { 45 | ptr=GetToken(Tempstr,",",&Rank,0); 46 | ptr=GetToken(ptr,",",&Site,0); 47 | ptr=GetToken(ptr,",",&Site,0); 48 | 49 | ListAddNamedItem(List,Site,CopyStr(NULL,Rank)); 50 | Tempstr=STREAMReadLine(Tempstr, S); 51 | } 52 | 53 | STREAMClose(S); 54 | } 55 | 56 | 57 | void Test(ListNode *List, const char *Type) 58 | { 59 | long start, end, i, lookups=10000; 60 | 61 | start=GetTime(TIME_CENTISECS); 62 | LoadCSV(List); 63 | end=GetTime(TIME_CENTISECS); 64 | printf("Time to load a million records into a %s: %f secs\n", Type, (float) (end-start) /100.0); 65 | 66 | start=GetTime(TIME_CENTISECS); 67 | for (i=0; i < lookups; i++) Lookup(List, "zyber.co.nz"); 68 | end=GetTime(TIME_CENTISECS); 69 | printf("Time to do %d lookups in a million record %s %f secs\n", lookups, Type, (float) (end-start) /100.0); 70 | } 71 | 72 | 73 | main() 74 | { 75 | ListNode *List; 76 | 77 | if (access("majestic_million.csv",F_OK) !=0) DownloadTestFile(); 78 | 79 | List=ListCreate(); 80 | //Test(List, "LIST"); 81 | ListDestroy(List, Destroy); 82 | 83 | List=MapCreate(1000, 0); 84 | Test(List, "MAP"); 85 | ListDestroy(List, Destroy); 86 | } 87 | -------------------------------------------------------------------------------- /examples/ParseRSS.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | 4 | //demonstrates parsing an RSS feed 5 | 6 | void main() 7 | { 8 | STREAM *S; 9 | ListNode *P, *SubItem, *Curr; 10 | char *Tempstr=NULL; 11 | const char *ptr; 12 | 13 | S=STREAMOpen("http://feeds.feedburner.com/dancarlin/commonsense?format=xml", "r"); 14 | if (S) 15 | { 16 | Tempstr=STREAMReadDocument(Tempstr, S); 17 | P=ParserParseDocument("rss",Tempstr); 18 | Curr=ListGetNext(P); 19 | while (Curr) 20 | { 21 | if (Curr->ItemType==ITEM_STRING) printf("%s: %s\n",Curr->Tag, (char *) Curr->Item); 22 | else 23 | { 24 | SubItem=ParserOpenItem(P, Curr->Tag); 25 | ptr=ParserGetValue(SubItem, "title"); 26 | if (StrValid(ptr)) 27 | { 28 | printf("\n%s\n", ptr); 29 | ptr=ParserGetValue(SubItem, "description"); 30 | if (StrValid(ptr)) printf("%s\n", ptr); 31 | ptr=ParserGetValue(SubItem, "enclosure_url"); 32 | if (StrValid(ptr)) printf("%s\n", ptr); 33 | } 34 | } 35 | Curr=ListGetNext(Curr); 36 | } 37 | } 38 | 39 | DestroyString(Tempstr); 40 | ParserItemsDestroy(P); 41 | } 42 | -------------------------------------------------------------------------------- /examples/PasswordFile.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | void main() 4 | { 5 | PasswordFileAdd("/tmp/test.pw", "sha1", "test user", "testing 123", NULL); 6 | PasswordFileAppend("/tmp/test.pw", "sha1", "another", "another password", NULL); 7 | //PasswordFileAdd("/tmp/test.pw", "sha1", "test user", "testing 456", NULL); 8 | 9 | printf("CHECK1: %d\n", PasswordFileCheck("/tmp/test.pw", "test user", "testing 123", NULL)); 10 | printf("CHECK2: %d\n", PasswordFileCheck("/tmp/test.pw", "test user", "testing 456", NULL)); 11 | printf("CHECK2: %d\n", PasswordFileCheck("/tmp/test.pw", "another", "another password", NULL)); 12 | } 13 | -------------------------------------------------------------------------------- /examples/README: -------------------------------------------------------------------------------- 1 | These examples all contain the line: 2 | 3 | #include "../libUseful.h" 4 | 5 | This is because they're intended to be compiled in place, within the libUseful source directory. In normal use the libUseful header files would be installed in your include path, and this line would become something like: 6 | 7 | #include "libUseful-3/libUseful.h" 8 | 9 | Furthermore these examples are linked against the static library of libUseful, like so: 10 | 11 | gcc -oVars.exe Vars.c ../libUseful-3.a 12 | 13 | This is why the .exe files are so big! In normal usage you'd install libUseful-2.8.so somewhere in your library path, and link with 14 | 15 | gcc -oVars.exe Vars.c -lUseful-3 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/SSLClient.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | /* 4 | Pass this program a URL of a host to connect to e.g. 5 | 6 | ssl://www.google.com:443 7 | ssl://imap.myhost.com:993 8 | https://www.google.com 9 | 10 | if the host supports SSL connections on that port, then this program 11 | will print out certificate and encryption details 12 | 13 | */ 14 | 15 | main(int argc, char *argv[]) 16 | { 17 | STREAM *S; 18 | char *URL=NULL, *Config=NULL, *Tempstr=NULL; 19 | const char *ptr; 20 | 21 | URL=CopyStr(URL, argv[1]); 22 | S=STREAMOpen(URL, Config); 23 | if (S) 24 | { 25 | ptr=STREAMGetValue(S,"SSL:Cipher"); 26 | if (StrValid(ptr)) 27 | { 28 | printf("Encrypted Connection: %s bit %s\n",STREAMGetValue(S, "SSL:CipherBits"), ptr); 29 | printf("Certificate Verified: %s\n",STREAMGetValue(S, "SSL:CertificateVerify")); 30 | printf("Certificate Issuer : %s\n",STREAMGetValue(S, "SSL:CertificateIssuer")); 31 | printf("Certificate Subject : %s\n",STREAMGetValue(S, "SSL:CertificateSubject")); 32 | printf("Certificate NotBefor: %s\n",STREAMGetValue(S, "SSL:CertificateNotBefore")); 33 | printf("Certificate NotAfter: %s\n",STREAMGetValue(S, "SSL:CertificateNotAfter")); 34 | } 35 | } 36 | else printf("Connection not encrypted\n"); 37 | 38 | STREAMClose(S); 39 | } 40 | 41 | -------------------------------------------------------------------------------- /examples/Smtp.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | 4 | main() 5 | { 6 | STREAM *S; 7 | char *Line=NULL, *Tempstr=NULL; 8 | 9 | S=STREAMOpen("tcp:mail.gmail.com:25", ""); 10 | if (S) 11 | { 12 | Tempstr=SetStrLen(Tempstr, 255); 13 | gethostname(Tempstr, 255); 14 | 15 | Line=MCopyStr(Line, "HELO ", Tempstr, "\r\n",NULL); 16 | STREAMWriteLine(Line, S); 17 | 18 | Line=STREAMReadLine(Line, S); 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /examples/SpawnContainer.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | main(int argc, char *argv[]) 4 | { 5 | char *Tempstr=NULL; 6 | 7 | Tempstr=MCopyStr(Tempstr, "ns=",argv[1],NULL); 8 | 9 | if (xfork(Tempstr)==0) 10 | { 11 | Tempstr=SetStrLen(Tempstr, 255); 12 | gethostname(Tempstr, 255); 13 | printf("hostname: %s\n",Tempstr); 14 | sleep (20); 15 | } 16 | 17 | DestroyString(Tempstr); 18 | } 19 | -------------------------------------------------------------------------------- /examples/StrLen.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | 4 | int StrLenTest(const char *Str, unsigned int iter) 5 | { 6 | uint64_t start, end; 7 | int i, len; 8 | 9 | start=GetTime(0); 10 | //printf("DOC: %s\n", Tempstr); 11 | for (i=0; i < iter; i++) 12 | { 13 | len=StrLenFromCache(Str); 14 | } 15 | end=GetTime(0); 16 | 17 | printf("CACHE: iter=%u len=%d time=%d\n", iter, len, (int) (end-start)); 18 | 19 | start=GetTime(0); 20 | //printf("DOC: %s\n", Tempstr); 21 | for (i=0; i < iter; i++) 22 | { 23 | len=strlen(Str); 24 | } 25 | end=GetTime(0); 26 | 27 | printf("NO CACHE: iter=%u len=%d time=%d\n", iter, len, (int) (end-start)); 28 | } 29 | 30 | 31 | main() 32 | { 33 | STREAM *S; 34 | char *Tempstr=NULL; 35 | 36 | StrLenCacheInit(10, 100); 37 | 38 | /* 39 | S=STREAMOpen("http://freshcode.club/", "r"); 40 | Tempstr=STREAMReadDocument(Tempstr, S); 41 | STREAMClose(S); 42 | */ 43 | Tempstr=CopyStr(Tempstr, "this is a test. Twas brillig and the slivey tooves dist gyre and gimble in the wable. All mimsy were the borogroves and all the meme wraths outgrabe."); 44 | 45 | StrLenTest(Tempstr, UINT_MAX); 46 | } 47 | -------------------------------------------------------------------------------- /examples/SysInfo.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | #include 3 | 4 | main() 5 | { 6 | printf("%s\n", OSSysInfoString(OSINFO_LOCALE)); 7 | printf("%s\n", OSSysInfoString(OSINFO_LANG)); 8 | printf("%s\n", OSSysInfoString(OSINFO_COUNTRY)); 9 | printf("%s\n", OSSysInfoString(OSINFO_CURRENCY)); 10 | printf("%s\n", OSSysInfoString(OSINFO_CURRENCY_SYM)); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /examples/TTYTest.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | 4 | //crude demo of tty functions 5 | 6 | void ReadReply(STREAM *S) 7 | { 8 | char *Tempstr=NULL; 9 | Tempstr=STREAMReadLine(Tempstr, S); 10 | while (StrLen(Tempstr)) 11 | { 12 | StripTrailingWhitespace(Tempstr); 13 | printf("%s\n",Tempstr); 14 | if (strcmp(Tempstr,"OK")==0) break; 15 | Tempstr=STREAMReadLine(Tempstr, S); 16 | } 17 | DestroyString(Tempstr); 18 | } 19 | 20 | main(int argc, char *argv[]) 21 | { 22 | int fd; 23 | STREAM *S; 24 | char *Tempstr=NULL; 25 | 26 | 27 | //this was tested with a GSM modem. These do not implement a full serial device, so options like 28 | //'echo/TTYFLAG_ECHO' don't work properly. So all we do here is set the baudrate 29 | 30 | //This is one method using TTYOpen 31 | /* 32 | Tempstr=CopyStr(Tempstr,"/dev/ttyS0"); 33 | if (argc > 0) Tempstr=CopyStr(Tempstr,argv[1]); 34 | 35 | fd=TTYOpen(Tempstr, 38400, 0); 36 | S=STREAMFromFD(fd); 37 | */ 38 | 39 | 40 | //this is another method using STREAMOpen 41 | Tempstr=CopyStr(Tempstr,"tty:/dev/ttyS0"); 42 | if (argc > 0) Tempstr=MCopyStr(Tempstr,"tty:",argv[1],NULL); 43 | 44 | S=STREAMOpen(Tempstr, "38400"); 45 | // end 46 | 47 | STREAMWriteLine("ATI\r\n",S); 48 | ReadReply(S); 49 | 50 | STREAMWriteLine("AT+CSQ\r\n",S); 51 | ReadReply(S); 52 | 53 | STREAMWriteLine("AT^SYSINFO\r\n",S); 54 | ReadReply(S); 55 | 56 | STREAMWriteLine("AT+COPS=?\r\n",S); 57 | ReadReply(S); 58 | 59 | STREAMWriteLine("AT+COPS=23415\r\n",S); 60 | ReadReply(S); 61 | 62 | 63 | 64 | STREAMWriteLine("AT+CMGF=1\r\n",S); 65 | ReadReply(S); 66 | STREAMWriteLine("AT+CMGS=+447749722575\r\nThis is the text message.\x1a",S); 67 | ReadReply(S); 68 | 69 | 70 | STREAMClose(S); 71 | DestroyString(Tempstr); 72 | } 73 | -------------------------------------------------------------------------------- /examples/TermBar.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | //demonstrates terminal bars 4 | 5 | TERMBAR *UpperTB, *LowerTB; 6 | 7 | int KeyCallback(STREAM *S, int key) 8 | { 9 | char *Tempstr=NULL; 10 | 11 | if (key==TKEY_F4) TerminalBarUpdate(UpperTB, "you pressed F4"); 12 | if (key==TKEY_F5) TerminalBarUpdate(UpperTB, "you pressed F5"); 13 | if (key==TKEY_F7) TerminalBarUpdate(UpperTB, "you pressed F7"); 14 | if (key==TKEY_MENU) TerminalBarUpdate(UpperTB, "you pressed Menu"); 15 | if (key==TKEY_WIN) TerminalBarUpdate(UpperTB, "you pressed win"); 16 | if (key==TKEY_CTRL_WIN) TerminalBarUpdate(UpperTB, "you pressed crtrl win"); 17 | 18 | 19 | if (key==TKEY_HOME) 20 | { 21 | UpperTB->ForeColor=ANSI_RED; 22 | UpperTB->BackColor=ANSI_YELLOW; 23 | UpperTB->Flags=ANSI_INVERSE; 24 | UpperTB->CursorLeft=CopyStr(UpperTB->CursorLeft," {"); 25 | UpperTB->CursorRight=CopyStr(UpperTB->CursorRight,"} "); 26 | Tempstr=TerminalBarMenu(Tempstr, UpperTB, "this,that,the other"); 27 | printf("%s\r\n",Tempstr); 28 | } 29 | 30 | DestroyString(Tempstr); 31 | } 32 | 33 | main(int argc, char *argv[]) 34 | { 35 | STREAM *Term; 36 | char *Tempstr=NULL; 37 | int i; 38 | 39 | Term=STREAMFromDualFD(0,1); 40 | TerminalInit(Term, TERM_RAWKEYS); 41 | TerminalSetKeyCallback(Term, KeyCallback); 42 | TerminalClear(Term); 43 | 44 | UpperTB=TerminalBarCreate(Term, "top", "This is an upper terminal bar"); 45 | LowerTB=TerminalBarCreate(Term, "lower forecolor=cyan backcolor=blue", "this is a lower terminal bar"); 46 | 47 | /* 48 | for (i=0; i < 100; i++) 49 | { 50 | printf("CSCROLL %d\r\n", i); 51 | sleep(1); 52 | } 53 | */ 54 | 55 | Tempstr=TerminalBarReadText(Tempstr, LowerTB, 0, ">>"); 56 | while (Tempstr) 57 | { 58 | //void TerminalBarUpdate(TERMBAR *TB, const char *Text); 59 | Tempstr=CatStr(Tempstr,"\r\n"); 60 | TerminalPutStr(Tempstr, Term); 61 | Tempstr=TerminalBarReadText(Tempstr, LowerTB, 0, ">>"); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /examples/TermCalendar.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | //demonstrates terminal calendar widget 4 | 5 | main(int argc, char *argv[]) 6 | { 7 | STREAM *Term; 8 | char *Tempstr=NULL; 9 | TERMCALENDAR *TC; 10 | int i; 11 | 12 | Term=STREAMFromDualFD(0,1); 13 | TerminalInit(Term, TERM_RAWKEYS | TERM_SAVEATTRIBS); 14 | TerminalClear(Term); 15 | 16 | //Tempstr=TerminalCalendar(Tempstr, Term, 10, 5, ""); 17 | //Tempstr=TerminalCalendar(Tempstr, Term, 10, 5, "month=4 year=2005 left_cursor=~y<~0 right_cursor=~y>~0 TitleYearAttribs=~r InsideMonthAttribs=~w OutsideMonthAttribs=~c y=2 TodayAttribs=~e"); 18 | Tempstr=TerminalCalendar(Tempstr, Term, 10, 5, "left_cursor=~y<~0 right_cursor=~y>~0 TitleYearAttribs=~r InsideMonthAttribs=~c OutsideMonthAttribs=~b y=2 TodayAttribs=~e datestate:2025-03-11=busy stateattribs:busy=~R~w "); 19 | 20 | printf("\n%s\n", Tempstr); 21 | 22 | TerminalReset(Term); 23 | } 24 | -------------------------------------------------------------------------------- /examples/TermChoice.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | main() 4 | { 5 | STREAM *Term; 6 | ListNode *Options; 7 | char *Tempstr=NULL; 8 | 9 | Term=STREAMFromDualFD(0,1); 10 | TerminalInit(Term, TERM_SAVE_ATTRIBS | TERM_RAWKEYS); 11 | 12 | TerminalClear(Term); 13 | TerminalCursorMove(Term, 0, 0); 14 | Tempstr=TerminalChoice(Tempstr, Term, "prompt=choose: width=40 left_cursor='~e<' right_cursor='>~0' options='this,that,the other,even more, option this, do anything, but whatever' "); 15 | 16 | TerminalReset(Term); 17 | 18 | Destroy(Tempstr); 19 | } 20 | -------------------------------------------------------------------------------- /examples/TermMenu.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | main() 4 | { 5 | STREAM *Term; 6 | ListNode *Options; 7 | 8 | Options=ListCreate(); 9 | SetVar(Options, "this", NULL); 10 | SetVar(Options, "that", NULL); 11 | SetVar(Options, "the other", NULL); 12 | 13 | Term=STREAMFromDualFD(0,1); 14 | TerminalInit(Term, TERM_SAVE_ATTRIBS | TERM_RAWKEYS); 15 | 16 | TerminalClear(Term); 17 | TerminalCursorMove(Term, 0, 0); 18 | TerminalMenu(Term, Options, 2, 2, -4, 6); 19 | 20 | TerminalReset(Term); 21 | } 22 | -------------------------------------------------------------------------------- /examples/TermProgress.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | //demonstrates terminal progress bars 4 | 5 | main(int argc, char *argv[]) 6 | { 7 | STREAM *Term; 8 | char *Tempstr=NULL; 9 | TERMPROGRESS *TP; 10 | int i; 11 | 12 | Term=STREAMFromDualFD(0,1); 13 | TerminalInit(Term, TERM_RAWKEYS | TERM_SAVEATTRIBS); 14 | TerminalClear(Term); 15 | 16 | //TP=TerminalProgressCreate(Term, "prompt='progress: ' left-contain=' -=' right-contain='=- ' progress=| width=20"); 17 | //TP=TerminalProgressCreate(Term, "prompt='progress: ' progress=' ' progress-attribs=~i width=20"); 18 | //TP=TerminalProgressCreate(Term, "prompt='progress: ' width=20"); 19 | TP=TerminalProgressCreate(Term, "prompt='progress: ' progress=' ' attribs=~B~w progress-attribs=~W~b left-contain='[' right-contain=']' innertext='$(percent)%' width=20"); 20 | for (i=0; i <= 20; i++) 21 | { 22 | Tempstr=FormatStr(Tempstr, " NOW AT: %d", i); 23 | TerminalProgressUpdate(TP, i, 20, Tempstr); 24 | sleep(1); 25 | } 26 | 27 | TerminalReset(Term); 28 | } 29 | -------------------------------------------------------------------------------- /examples/Terminal.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | //demonstrates a few functions related to terminal control 4 | 5 | void Interact(STREAM *Term, const char *Prompt, int Flags) 6 | { 7 | char *Input=NULL, *Tempstr=NULL; 8 | 9 | TerminalPutStr(Prompt, Term); 10 | 11 | Input=TerminalReadText(Input, Flags, Term); 12 | 13 | TerminalPutStr("\r\n", Term); 14 | Tempstr=MCopyStr(Tempstr, "~eYou typed:~0 ", Input, "\r\n", NULL); 15 | TerminalPutStr(Tempstr, Term); 16 | 17 | 18 | DestroyString(Tempstr); 19 | DestroyString(Input); 20 | } 21 | 22 | 23 | 24 | main(int argc, char *argv[]) 25 | { 26 | STREAM *Term; 27 | char *Tempstr=NULL, *Input=NULL; 28 | TERMBAR *TB; 29 | 30 | Term=STREAMFromDualFD(0,1); 31 | TerminalInit(Term, TERM_RAWKEYS); 32 | TerminalClear(Term); 33 | 34 | Interact(Term, "~y~RHello. Type something and I'll ~eecho it~>~0\r\n", 0); 35 | Interact(Term, "~r~WNow type something and I'll ~ehide it~>~0\r\n", TERM_HIDETEXT); 36 | Interact(Term, "~c~BNow type something and I'll ~estar it out like a password~>~0\r\n", TERM_SHOWSTARS); 37 | Interact(Term, "~w~GNow type something and I'll ~estar but show the last letter~>~0\r\n", TERM_SHOWTEXTSTARS); 38 | TerminalPutStr("~iOkay, that's all folks. exiting..~>~0\r\n", Term); 39 | 40 | sleep(3); 41 | TerminalReset(Term); 42 | 43 | DestroyString(Tempstr); 44 | DestroyString(Input); 45 | } 46 | -------------------------------------------------------------------------------- /examples/Tokenize.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | //demonstrates libUseful functions to break a string up into tokens 4 | 5 | #define STR "one two three four \"five six seven\" eight nine" 6 | 7 | void OutputTokens(const char *Title, const char *In, int Flags) 8 | { 9 | char *Token=NULL; 10 | const char *ptr; 11 | 12 | printf("\n%s\n",Title); 13 | ptr=GetToken(In, " ", &Token, Flags); 14 | while (ptr) 15 | { 16 | printf("%s\n",Token); 17 | ptr=GetToken(ptr, " ", &Token, Flags); 18 | } 19 | 20 | DestroyString(Token); 21 | } 22 | 23 | main() 24 | { 25 | printf("Results of GetToken called with different flags on the string : %s\n",STR); 26 | OutputTokens("GetToken - no flags", STR, 0); 27 | OutputTokens("GetToken - GETTOKEN_HONOR_QUOTES", STR, GETTOKEN_HONOR_QUOTES); 28 | OutputTokens("GetToken - GETTOKEN_QUOTES", STR, GETTOKEN_QUOTES); 29 | } 30 | -------------------------------------------------------------------------------- /examples/Vars.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | //simple program to demostrate how Vars work in libUseful 4 | 5 | main() 6 | { 7 | ListNode *Vars; 8 | char *Tempstr=NULL; 9 | 10 | Vars=ListCreate(); 11 | SetVar(Vars, "arg1", "abcdefg"); 12 | SetVar(Vars, "arg2", "12345"); 13 | 14 | Tempstr=SubstituteVarsInString(Tempstr,"arg1=$(arg1) arg2=$(arg2)", Vars,0); 15 | printf("%s\n",Tempstr); 16 | 17 | DestroyString(Tempstr); 18 | } 19 | -------------------------------------------------------------------------------- /examples/Websocket.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | 4 | //Test websockets by connecting to a nostr server and printing out messages 5 | 6 | 7 | void ParseMessage(const char *msg) 8 | { 9 | char *Token=NULL; 10 | const char *ptr; 11 | ListNode *P; 12 | int val; 13 | 14 | printf("MSG: %s\n", msg); 15 | ptr=GetToken(msg, ",", &Token, 0); 16 | ptr=GetToken(ptr, ",", &Token, 0); 17 | ptr=GetToken(ptr, "]", &Token, 0); 18 | 19 | P=ParserParseDocument("json", Token); 20 | ptr=ParserGetValue(P, "kind"); 21 | if (ptr) 22 | { 23 | val=atoi(ptr); 24 | 25 | switch (val) 26 | { 27 | case 1: printf("%s\n", ParserGetValue(P, "content")); break; 28 | case 3: printf("TAGS: %s\n", ParserGetValue(P, "content")); 29 | } 30 | } 31 | 32 | ParserItemsDestroy(P); 33 | 34 | Destroy(Token); 35 | } 36 | 37 | 38 | main() 39 | { 40 | STREAM *S; 41 | char *Tempstr=NULL; 42 | int result; 43 | 44 | S=STREAMOpen("wss://nos.lol", ""); 45 | 46 | Tempstr=FormatStr(Tempstr, "[\"REQ\", \"test\", {\"since\": %lu,\"limit\":5}]", time(NULL) - (2 * 3600)); 47 | STREAMWriteLine(Tempstr, S); 48 | 49 | /* 50 | Tempstr=SetStrLen(Tempstr, 4096); 51 | while (1) 52 | { 53 | result=STREAMReadBytes(S, Tempstr, 4096); 54 | printf("RESULT: %d\n", result); 55 | if (result < 0) break; 56 | if (result > 0) 57 | { 58 | StrTrunc(Tempstr, result); 59 | printf("%s\n", Tempstr); 60 | } 61 | } 62 | */ 63 | 64 | Tempstr=STREAMReadLine(Tempstr, S); 65 | while (Tempstr) 66 | { 67 | ParseMessage(Tempstr); 68 | Tempstr=STREAMReadLine(Tempstr, S); 69 | } 70 | 71 | Destroy(Tempstr); 72 | STREAMClose(S); 73 | } 74 | -------------------------------------------------------------------------------- /examples/WebsocketServer.c: -------------------------------------------------------------------------------- 1 | #include "libUseful-5/libUseful.h" 2 | 3 | main() 4 | { 5 | STREAM *Serv, *S; 6 | 7 | 8 | } 9 | -------------------------------------------------------------------------------- /examples/YAML.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | main() 4 | { 5 | PARSER *P; 6 | char *Tempstr=NULL; 7 | 8 | P=ParserParseDocument("yaml", "this: this is some text\nthat: that is some text\n'the other': 1234\nsubitem:\n stuff in a subitem: whatever\n contents: with contents\n block: |\n this is some\n block text\n final: final item\n"); 9 | Tempstr=ParserExport(Tempstr, "json", P); 10 | Tempstr=ParserExport(Tempstr, "xml", P); 11 | Tempstr=ParserExport(Tempstr, "yaml", P); 12 | Tempstr=ParserExport(Tempstr, "cmon", P); 13 | printf("%s\n", Tempstr); 14 | 15 | Destroy(Tempstr); 16 | } 17 | -------------------------------------------------------------------------------- /examples/asciiblast.conf: -------------------------------------------------------------------------------- 1 | 2 | #event {turns=100; minelayer {x=rand; y=3;}} 3 | level0 4 | { 5 | hunter {direction=leftpatrol; x=30; y=10} 6 | bomber {direction=leftpatrol; x=50; y=10} 7 | drone {direction=leftpatrol; x=80; y=10} 8 | #complete { type=time ; value=100} 9 | event {turns=10; bunkerbuster {x=rand; y=3;}} 10 | event {turns=5; seeker {x=rand; y=3;}} 11 | event {turns=2; mine {x=rand; y=3;}} 12 | } 13 | 14 | 15 | #level3 16 | #{ 17 | #event {turns=200; bomber {direction=either; y=5; armor=2; firerate=30}} 18 | #block {type=marcher; direction=leftdown; x=right; y=-20; width=12; height=5; xgap=6; ygap=0; firerate=40;} 19 | #} 20 | 21 | 22 | 23 | level1 24 | { 25 | event {turns=250; bomber {direction=either; y=3; armor=2; firerate=30}} 26 | event {turns=200; bomber {direction=either; y=4; armor=2; firerate=30}} 27 | 28 | block {type=diver; direction=rightpatrol; x=left; y=8; width=8; height=4; xgap=0; ygap=0} 29 | block {type=diver; direction=leftpatrol; x=right; y=8; width=8; height=4; xgap=0; ygap=0} 30 | } 31 | 32 | 33 | -------------------------------------------------------------------------------- /examples/base32.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | #define HELLO "JBSWY3DPEE======" 4 | 5 | main(int argc, char *argv[]) 6 | { 7 | char *Chars=NULL, *Bytes=NULL; 8 | int len; 9 | 10 | if (argc < 2) 11 | { 12 | printf("ERROR: no test string, please supply one on the command-line\n"); 13 | exit(1); 14 | } 15 | 16 | Chars=EncodeBytes(Chars, argv[1], StrLen(argv[1]), ENCODE_BASE32); 17 | printf("%s\n", Chars); 18 | Chars=EncodeBytes(Chars, argv[1], StrLen(argv[1]), ENCODE_CBASE32); 19 | printf("%s\n", Chars); 20 | Chars=EncodeBytes(Chars, argv[1], StrLen(argv[1]), ENCODE_WBASE32); 21 | printf("%s\n", Chars); 22 | Chars=EncodeBytes(Chars, argv[1], StrLen(argv[1]), ENCODE_HBASE32); 23 | printf("%s\n", Chars); 24 | Chars=EncodeBytes(Chars, argv[1], StrLen(argv[1]), ENCODE_ZBASE32); 25 | printf("%s\n", Chars); 26 | 27 | 28 | len=DecodeBytes(&Bytes, "7e7e9c42a91bfef19fa929e5fda1b72e0ebc1a4c1141673e2794234d86addf4e", ENCODE_HEX); 29 | Chars=EncodeBytes(Chars, Bytes, len, ENCODE_BECH32); 30 | printf("%s\n", Chars); 31 | 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /examples/base64.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | #define HELLO "JBSWY3DPEE======" 4 | 5 | main(int argc, char *argv[]) 6 | { 7 | char *Chars=NULL, *Bytes=NULL; 8 | int len; 9 | 10 | if (argc < 2) 11 | { 12 | printf("ERROR: no test string, please supply one on the command-line\n"); 13 | exit(1); 14 | } 15 | 16 | Chars=EncodeBytes(Chars, argv[1], StrLen(argv[1]), ENCODE_BASE64); 17 | printf("%s\n", Chars); 18 | DecodeBytes(&Bytes, Chars, ENCODE_BASE64); 19 | printf("Decoded: %s\n", Bytes); 20 | 21 | Chars=EncodeBytes(Chars, argv[1], StrLen(argv[1]), ENCODE_IBASE64); 22 | printf("%s\n", Chars); 23 | DecodeBytes(&Bytes, Chars, ENCODE_IBASE64); 24 | printf("Decoded: %s\n", Bytes); 25 | 26 | 27 | 28 | Chars=EncodeBytes(Chars, argv[1], StrLen(argv[1]), ENCODE_PBASE64); 29 | printf("%s\n", Chars); 30 | 31 | /* 32 | len=DecodeBytes(&Bytes, "7e7e9c42a91bfef19fa929e5fda1b72e0ebc1a4c1141673e2794234d86addf4e", ENCODE_HEX); 33 | Chars=EncodeBytes(Chars, Bytes, len, ENCODE_BECH32); 34 | printf("%s\n", Chars); 35 | */ 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /examples/calendar.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | main() 4 | { 5 | char *Tempstr=NULL; 6 | 7 | Tempstr=CalendarFormatCSV(Tempstr, 1, 2025); 8 | printf("%s\n", Tempstr); 9 | 10 | Destroy(Tempstr); 11 | } 12 | -------------------------------------------------------------------------------- /examples/chroot.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | main() 4 | { 5 | 6 | ProcessApplyConfig("chroot=/tmp/xxx strict"); 7 | printf("I'm still here\n"); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /examples/container.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | 4 | main() 5 | { 6 | ProcessApplyConfig("container nonet +mnt=/etc,/dev,/lib,/usr/lib,/bin,/usr/bin"); 7 | system("/bin/sh"); 8 | } 9 | -------------------------------------------------------------------------------- /examples/decrypt.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | main(int argc, const char *argv[]) 4 | { 5 | STREAM *S, *Out; 6 | char *Tempstr=NULL; 7 | int result=0; 8 | 9 | Out=STREAMFromDualFD(0,1); 10 | S=STREAMOpen(argv[1], "re encrypt=whatever"); 11 | if (S) 12 | { 13 | Tempstr=SetStrLen(Tempstr, 4096); 14 | result=STREAMReadBytes(S, Tempstr, 4096); 15 | while (result > 0) 16 | { 17 | STREAMWriteBytes(Out, Tempstr, result); 18 | result=STREAMReadBytes(S, Tempstr, 4096); 19 | } 20 | STREAMClose(S); 21 | } 22 | 23 | Destroy(Tempstr); 24 | } 25 | -------------------------------------------------------------------------------- /examples/encrypt.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | main() 4 | { 5 | STREAM *S; 6 | char *Tempstr=NULL; 7 | int result=0; 8 | 9 | S=STREAMOpen("file.enc", "we"); 10 | printf("should fail: %d\n",S); 11 | 12 | S=STREAMOpen("file.enc", "we encrypt=whatever"); 13 | STREAMWriteLine("Twas Brillig and the slivey tooves didst gyre and gimble in the wabe\n", S); 14 | STREAMClose(S); 15 | 16 | S=STREAMOpen("file.enc", "re encrypt=whatever"); 17 | if (S) 18 | { 19 | Tempstr=STREAMReadLine(Tempstr, S); 20 | //Tempstr=SetStrLen(Tempstr, 4096); 21 | //result=STREAMReadBytes(S, Tempstr, 4096); 22 | //StrTrunc(Tempstr, result); 23 | printf("%s\n", Tempstr); 24 | STREAMClose(S); 25 | } 26 | 27 | Destroy(Tempstr); 28 | } 29 | -------------------------------------------------------------------------------- /examples/fmtduration.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | main() 4 | { 5 | printf("%s\n", FormatDuration("uptime: %dd %hh %mm %ss", OSSysInfoLong(OSINFO_UPTIME))); 6 | printf("%s\n", FormatDuration("uptime: %dd %hh %mm %ss %% %%% %x %", OSSysInfoLong(OSINFO_UPTIME))); 7 | printf("%s\n", FormatDuration("uptime: %hh %mm %ss", OSSysInfoLong(OSINFO_UPTIME))); 8 | printf("%s\n", FormatDuration("uptime: %dd %mm %ss", OSSysInfoLong(OSINFO_UPTIME))); 9 | } 10 | -------------------------------------------------------------------------------- /examples/invoke.conf: -------------------------------------------------------------------------------- 1 | cryptmount 2 | { 3 | user wwwrun 4 | #program invoke 5 | run "/usr/sbin/cryptsetup open /dev/md1 crypted.partition" pty expect=Convo 6 | run "/bin/mount /dev/mapper/crypted.partition /home/" 7 | 8 | Convo 9 | { 10 | expect "Enter passphrase for " "$(PASSPHRASE)" 11 | fail "No key available with this passphrase." 12 | } 13 | } 14 | 15 | dmi-model 16 | { 17 | user axiom 18 | run "cat /sys/class/dmi/id/product_name" 19 | } 20 | 21 | dmi-assettag 22 | { 23 | user axiom 24 | run "cat /sys/class/dmi/id/product_serial" 25 | } 26 | 27 | 28 | 29 | serverbackup 30 | { 31 | user axiom 32 | require directory /home/Software 33 | run "/bin/tar --exclude=.git -zcO $(args)" 34 | } 35 | 36 | 37 | RestartFirewall 38 | { 39 | user wwwrun 40 | run "/bin/mv -f /tmp/trusted.ethers /etc; /etc/firewall.sh" 41 | } 42 | 43 | -------------------------------------------------------------------------------- /examples/movetest.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | main() 4 | { 5 | FileMoveToDir("/etc/hosts", "/tmp/"); 6 | } 7 | -------------------------------------------------------------------------------- /examples/nonewprivs.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | main() 4 | { 5 | ProcessApplyConfig("nosu"); 6 | printf("You should now be running in a shell that cannot su/sudo\n"); 7 | printf("Type 'exit' to leave it\n"); 8 | setenv("PS1", "restricted: ", TRUE); 9 | SwitchProgram("/bin/bash", ""); 10 | } 11 | -------------------------------------------------------------------------------- /examples/pattest.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | #define Str "made glorious summer by this son of york" 4 | 5 | void Check(const char *Pattern) 6 | { 7 | ListNode *Matches; 8 | int result; 9 | 10 | Matches=ListCreate(); 11 | 12 | result=pmatch(Pattern, Str, StrLen(Str), Matches, 0); 13 | printf("[%s] %d %d matches\n",Pattern, result, ListSize(Matches)); 14 | 15 | } 16 | 17 | main() 18 | { 19 | 20 | //Pattern=CopyStr(Pattern, "* new high-speed USB device * using xhci_hcd"); 21 | //Str=CopyStr(Str,"usb 4-12: new high-speed USB device number 4 using xhci_hcd"); 22 | 23 | 24 | Check("*glorious*"); 25 | Check("glorious"); 26 | Check("*glorious"); 27 | Check("*xlorious*"); 28 | Check("*[Ggx]lorious*"); 29 | Check("*?lorious*"); 30 | Check(Str); 31 | } 32 | -------------------------------------------------------------------------------- /examples/pbkdf2.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | main() 4 | { 5 | char *Hash=NULL; 6 | 7 | PBK2DF2(&Hash, "hmac-sha1", "password", 8, "salt", 4, 1, ENCODE_HEX); 8 | 9 | printf("result: %s\n", Hash); 10 | 11 | Destroy(Hash); 12 | } 13 | -------------------------------------------------------------------------------- /examples/seccomp.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | #include 3 | 4 | main() 5 | { 6 | pid_t pid; 7 | STREAM *S; 8 | 9 | 10 | ProcessApplyConfig("security='client'"); 11 | pid=fork(); 12 | if (pid == 0) 13 | { 14 | 15 | S=STREAMOpen("unix:/tmp/.X11-unix/X0", ""); 16 | STREAMClose(S); 17 | 18 | S=STREAMOpen("http://www.google.com/", ""); 19 | printf("After GOOGLE: %s\n", STREAMGetValue(S, "HTTP:ResponseCode")); 20 | STREAMClose(S); 21 | 22 | S=STREAMServerNew("tcp:0.0.0.0:2048", ""); 23 | printf("Server: %d\n", S); 24 | STREAMClose(S); 25 | 26 | chroot("."); 27 | printf("After chroot\n"); 28 | 29 | ptrace(PTRACE_CONT, getppid(), 0, 0); 30 | printf("After ptrace\n"); 31 | 32 | exit(1); 33 | } 34 | waitpid(pid, 0, 0); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /examples/ssh-listfiles.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | //test running a command on an ssh server 4 | 5 | main(int argc, const char *argv[]) 6 | { 7 | STREAM *S; 8 | char *Tempstr=NULL; 9 | 10 | if (argv < 2) 11 | { 12 | printf("Insufficient arguments: %s \n", argv[0]); 13 | exit(1); 14 | } 15 | 16 | Tempstr=MCopyStr(Tempstr, "ssh:", argv[1], "/*", NULL); 17 | S=STREAMOpen(Tempstr, "l"); 18 | if (S) 19 | { 20 | Tempstr=STREAMReadLine(Tempstr, S); 21 | while (Tempstr) 22 | { 23 | StripTrailingWhitespace(Tempstr); 24 | printf("%s\n", Tempstr); 25 | Tempstr=STREAMReadLine(Tempstr, S); 26 | } 27 | STREAMClose(S); 28 | } 29 | else printf("ERROR: failed to connect to %s\n", Tempstr); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /examples/ssh-time.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | //test running a command on an ssh server 4 | 5 | main(int argc, const char *argv[]) 6 | { 7 | STREAM *S; 8 | char *Tempstr=NULL; 9 | 10 | if (argv < 2) 11 | { 12 | printf("Insufficient arguments: %s \n", argv[0]); 13 | exit(1); 14 | } 15 | 16 | Tempstr=MCopyStr(Tempstr, "ssh:", argv[1], "/date '+%Y-%m-%dT%H:%M:%S'", NULL); 17 | S=STREAMOpen(Tempstr, "x"); 18 | if (S) 19 | { 20 | Tempstr=STREAMReadLine(Tempstr, S); 21 | while (Tempstr) 22 | { 23 | StripTrailingWhitespace(Tempstr); 24 | printf("%s\n", Tempstr); 25 | Tempstr=STREAMReadLine(Tempstr, S); 26 | } 27 | STREAMClose(S); 28 | } 29 | else printf("ERROR: failed to connect to %s\n", Tempstr); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /examples/ssh-tunnel.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | main() 4 | { 5 | STREAM *S; 6 | char *Tempstr=NULL; 7 | 8 | S=STREAMOpen("ssh:opti2|tcp:127.0.0.1:12001", ""); 9 | if (S) 10 | { 11 | STREAMWriteLine("list wallpaper_mgr\n", S); 12 | Tempstr=STREAMReadLine(Tempstr, S); 13 | printf("GOT: %s\n", Tempstr); 14 | STREAMClose(S); 15 | } 16 | 17 | Destroy(Tempstr); 18 | } 19 | -------------------------------------------------------------------------------- /examples/uudecode.c: -------------------------------------------------------------------------------- 1 | #include "../libUseful.h" 2 | 3 | #define HELLO "JBSWY3DPEE======" 4 | 5 | 6 | main(int argc, char *argv[]) 7 | { 8 | char *Chars=NULL; 9 | //char *Input="K:'1T<',Z+R]W=W6]U='5B92YC;VTO=V%T8V@_=CUH26XQ3F8S8F1D40``"; 10 | char *Input="K:'1T<"; 11 | int len; 12 | 13 | len=DecodeBytes(&Chars, Input, ENCODE_UUENC); 14 | printf("%s\n", Chars); 15 | 16 | Chars=EncodeBytes(Chars, "Cat", 3, ENCODE_UUENC); 17 | printf("%s\n", Chars); 18 | } 19 | -------------------------------------------------------------------------------- /includes.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIBUSEFUL_INCLUDES_H 7 | #define LIBUSEFUL_INCLUDES_H 8 | 9 | #define _GNU_SOURCE 10 | #define _USE_POSIX 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include //for uid_t 33 | #include //for gid_t 34 | #include //for math defines like PI 35 | 36 | 37 | 38 | #include "defines.h" 39 | #include "String.h" 40 | #include "List.h" 41 | #include "Time.h" 42 | #include "Stream.h" 43 | #include "Socket.h" 44 | #include "OpenSSL.h" 45 | #include "Vars.h" 46 | #include "Errors.h" 47 | #include "LibSettings.h" 48 | #include "GeneralFunctions.h" 49 | #include "Tokenizer.h" 50 | #include "Process.h" 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /libUseful.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Colum Paget 3 | * SPDX-License-Identifier: LGPL-3.0-or-later 4 | */ 5 | 6 | #ifndef LIB_USEFUL_H 7 | #define LIB_USEFUL_H 8 | 9 | #ifndef FALSE 10 | #define FALSE 0 11 | #endif 12 | 13 | #ifndef TRUE 14 | #define TRUE 1 15 | #endif 16 | 17 | #define __LIBUSEFUL_VERSION__ VERSION 18 | #define __LIBUSEFUL_BUILD_DATE__ __DATE__ 19 | #define __LIBUSEFUL_BUILD_TIME__ __TIME__ 20 | 21 | //__TIME__ 22 | 23 | #include "includes.h" 24 | #include "GeneralFunctions.h" 25 | #include "Entropy.h" 26 | #include "IPAddress.h" 27 | #include "Socket.h" 28 | #include "Server.h" 29 | #include "UnixSocket.h" 30 | #include "String.h" 31 | #include "StringList.h" 32 | #include "Expect.h" 33 | #include "List.h" 34 | #include "Array.h" 35 | #include "Stream.h" 36 | #include "Inet.h" 37 | #include "base64.h" 38 | #include "Tokenizer.h" 39 | #include "FileSystem.h" 40 | #include "DataProcessing.h" 41 | #include "Encodings.h" 42 | #include "Hash.h" 43 | #include "HMAC.h" 44 | #include "OTP.h" 45 | #include "Compression.h" 46 | #include "Time.h" 47 | #include "Vars.h" 48 | #include "Markup.h" 49 | #include "PatternMatch.h" 50 | #include "ConnectionChain.h" 51 | #include "SpawnPrograms.h" 52 | #include "DataParser.h" 53 | #include "CommandLineParser.h" 54 | #include "URL.h" 55 | #include "Pty.h" 56 | #include "Log.h" 57 | #include "Http.h" 58 | #include "HttpUtil.h" 59 | #include "Gemini.h" 60 | #include "OAuth.h" 61 | #include "Ssh.h" 62 | #include "Smtp.h" 63 | #include "RawData.h" 64 | #include "Terminal.h" 65 | #include "TerminalMenu.h" 66 | #include "TerminalChoice.h" 67 | #include "TerminalProgress.h" 68 | #include "TerminalCalendar.h" 69 | #include "TerminalBar.h" 70 | #include "Process.h" 71 | #include "SecureMem.h" 72 | #include "SysInfo.h" 73 | #include "Users.h" 74 | #include "UnitsOfMeasure.h" 75 | #include "HttpServer.h" 76 | #include "WebSocket.h" 77 | #include "PasswordFile.h" 78 | #include "StreamAuth.h" 79 | #include "CGI.h" 80 | #include "LineEdit.h" 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /libuseful.luarocks.in: -------------------------------------------------------------------------------- 1 | package="libUseful" 2 | version="@PACKAGE_VERSION@-1" 3 | source = { 4 | url = "https://github.com/ColumPaget/libUseful", 5 | tag= "v@PACKAGE_VERSION@" 6 | } 7 | description = { 8 | summary = "libUseful - utility library underlying libUseful-lua", 9 | detailed = [[ 10 | libUseful is a C library of useful functions. It is a dependancy of libUseful-lua which provides lua bindings for libUseful 11 | ]], 12 | homepage = "https://github.com/ColumPaget/libUseful", 13 | license = "GPLv3" 14 | } 15 | dependencies = { 16 | } 17 | build = { 18 | type = "command", 19 | build_command = "./configure --prefix=$(PREFIX) --enable-ssl --enable-harden --enable-seccomp --enable-namespaces --enable-sendfile && make clean && make", 20 | install_command = "make install" 21 | } 22 | -------------------------------------------------------------------------------- /md5-global.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: CC-PDDC 3 | */ 4 | 5 | /* This MD5 implmentation is taken from fetchmail, and is declared as 6 | * in the public domain in the COPYING file that comes with fetchmail, 7 | * and in the md5c.c file, relevant section reproduced below: 8 | * 9 | * This code implements the MD5 message-digest algorithm. 10 | * The algorithm is due to Ron Rivest. This code was 11 | * written by Colin Plumb in 1993, no copyright is claimed. 12 | * This code is in the public domain; do with it what you wish. 13 | */ 14 | 15 | /* GLOBAL.H - RSAREF types and constants 16 | */ 17 | 18 | /* PROTOTYPES should be set to one if and only if the compiler supports 19 | function argument prototyping. 20 | The following makes PROTOTYPES default to 0 if it has not already 21 | 22 | been defined with C compiler flags. 23 | */ 24 | #ifndef PROTOTYPES 25 | #define PROTOTYPES 0 26 | #endif 27 | 28 | /* POINTER defines a generic pointer type */ 29 | typedef unsigned char *POINTER; 30 | 31 | /* UINT2 defines a two byte word */ 32 | typedef unsigned short int UINT2; 33 | 34 | /* UINT4 defines a four byte word */ 35 | typedef unsigned long int UINT4; 36 | 37 | /* PROTO_LIST is defined depending on how PROTOTYPES is defined above. 38 | If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it 39 | returns an empty list. 40 | */ 41 | #if PROTOTYPES 42 | #define PROTO_LIST(list) list 43 | #else 44 | #define PROTO_LIST(list) () 45 | #endif 46 | 47 | -------------------------------------------------------------------------------- /md5.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: CC-PDDC 3 | */ 4 | 5 | /* This MD5 implmentation is taken from fetchmail, and is declared as 6 | * in the public domain in the COPYING file that comes with fetchmail, 7 | * and in the md5c.c file, relevant section reproduced below: 8 | * 9 | * This code implements the MD5 message-digest algorithm. 10 | * The algorithm is due to Ron Rivest. This code was 11 | * written by Colin Plumb in 1993, no copyright is claimed. 12 | * This code is in the public domain; do with it what you wish. 13 | */ 14 | 15 | #ifndef MD5_H 16 | #define MD5_H 17 | #ifndef HEADER_MD5_H 18 | /* Try to avoid clashes with OpenSSL */ 19 | #define HEADER_MD5_H 20 | #endif 21 | 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | 28 | #include 29 | 30 | struct MD5Context 31 | { 32 | uint32_t buf[4]; 33 | uint32_t bits[2]; 34 | unsigned char in[64]; 35 | }; 36 | 37 | void MD5Init(struct MD5Context *context); 38 | void MD5Update(struct MD5Context *context, unsigned char const *buf, 39 | unsigned len); 40 | void MD5Final(unsigned char digest[16], struct MD5Context *context); 41 | void MD5Transform(uint32_t buf[4], uint32_t const in[16]); 42 | 43 | /* 44 | * This is needed to make RSAREF happy on some MS-DOS compilers. 45 | */ 46 | typedef struct MD5Context MD5_CTX; 47 | 48 | 49 | #ifdef __cplusplus 50 | } 51 | #endif 52 | 53 | 54 | #endif /* !MD5_H */ 55 | -------------------------------------------------------------------------------- /sha1.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2000-2001, 2003, 2005-2006, 2008-2011 Free Software Foundation, Inc. 3 | * SPDX-License-Identifier: GPL-2.0-or-later 4 | */ 5 | 6 | /* 7 | Declarations of functions and data types used for SHA1 sum 8 | library functions. 9 | Copyright (C) 2000-2001, 2003, 2005-2006, 2008-2011 Free Software Foundation, Inc. 10 | 11 | This program is free software; you can redistribute it and/or modify it 12 | under the terms of the GNU General Public License as published by the 13 | Free Software Foundation; either version 2, or (at your option) any 14 | later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program; if not, write to the Free Software Foundation, 23 | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 24 | */ 25 | 26 | 27 | #ifdef USE_SHA1 28 | 29 | 30 | #ifndef SHA1_H 31 | # define SHA1_H 1 32 | 33 | # include 34 | # include 35 | 36 | # ifdef __cplusplus 37 | extern "C" { 38 | # endif 39 | 40 | #define SHA1_DIGEST_SIZE 20 41 | 42 | /* Structure to save state of computation between the single steps. */ 43 | struct sha1_ctx 44 | { 45 | uint32_t A; 46 | uint32_t B; 47 | uint32_t C; 48 | uint32_t D; 49 | uint32_t E; 50 | 51 | uint32_t total[2]; 52 | uint32_t buflen; 53 | uint32_t buffer[32]; 54 | }; 55 | 56 | 57 | /* Initialize structure containing state of computation. */ 58 | extern void sha1_init_ctx (struct sha1_ctx *ctx); 59 | 60 | /* Starting with the result of former calls of this function (or the 61 | initialization function update the context for the next LEN bytes 62 | starting at BUFFER. 63 | It is necessary that LEN is a multiple of 64!!! */ 64 | extern void sha1_process_block (const void *buffer, size_t len, 65 | struct sha1_ctx *ctx); 66 | 67 | /* Starting with the result of former calls of this function (or the 68 | initialization function update the context for the next LEN bytes 69 | starting at BUFFER. 70 | It is NOT required that LEN is a multiple of 64. */ 71 | extern void sha1_process_bytes (const void *buffer, size_t len, 72 | struct sha1_ctx *ctx); 73 | 74 | /* Process the remaining bytes in the buffer and put result from CTX 75 | in first 20 bytes following RESBUF. The result is always in little 76 | endian byte order, so that a byte-wise output yields to the wanted 77 | ASCII representation of the message digest. */ 78 | extern void *sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf); 79 | 80 | 81 | /* Put result from CTX in first 20 bytes following RESBUF. The result is 82 | always in little endian byte order, so that a byte-wise output yields 83 | to the wanted ASCII representation of the message digest. */ 84 | extern void *sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf); 85 | 86 | 87 | # ifdef __cplusplus 88 | } 89 | # endif 90 | 91 | #endif 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /unicode-names.conf: -------------------------------------------------------------------------------- 1 | micro 00b5 2 | quarter 00bc 3 | half 00bd 4 | 3quarter 00be 5 | 6 | moon 263E 7 | quarternote 2669 8 | eighthnote 266A 9 | music 266B 10 | beamed8note 266B 11 | beamed16note 266C 12 | 13 | sine 223F 14 | information 2139 15 | dagger 2020 16 | double-dagger 2021 17 | bullet 2022 18 | wbullet 25e6 19 | white-bullet 25e6 20 | asterism 2042 21 | 22 | ellipsis 2026 23 | vellipsis 22ee 24 | vert-ellipsis 22ee 25 | vertical-ellipsis 22ee 26 | 27 | leftarrow 2190 28 | rightarrow 2192 29 | uparrow 2191 30 | downarrow 2193 31 | leftrightarrow 2194 32 | updownarrow 2195 33 | 34 | warrow 2190 35 | earrow 2192 36 | nparrow 2191 37 | sownarrow 2193 38 | nwarrow 2196 39 | nearrow 2197 40 | searrow 2198 41 | swarrow 2199 42 | 43 | house 2302 44 | flat 226D 45 | sharp 226F 46 | infinity 221E 47 | widdershins 21BA 48 | counter-clockwise 21BA 49 | clockwise 21BB 50 | 51 | diameter 2300 52 | 53 | left 23F4 54 | right 23F5 55 | up 23F6 56 | down 23F7 57 | 58 | forward 23E9 59 | reverse 23EA 60 | 61 | media-forward 23E9 62 | media-reverse 23EA 63 | media-pause 23F8 64 | media-stop 23F9 65 | media-record 23FA 66 | media-eject 23CF 67 | media-play 23EF 68 | media-play-pause 23EF 69 | eject 23CF 70 | standby 23FB 71 | power 23FC 72 | 73 | sun 2600 74 | cloud 2601 75 | umbrella 2602 76 | snowman 2603 77 | comet 2604 78 | star 2605 79 | star-outline 2606 80 | thunderbolt 2607 81 | thunderbolt2 2608 82 | circumpunct 2609 83 | phone 260E 84 | phone-outline 260F 85 | box 2610 86 | tickbox 2611 87 | checkbox 2612 88 | check 2613 89 | umbrella-rain 2614 90 | coffee 2615 91 | shogi-white 2616 92 | shogi-black 2617 93 | shamrock 2618 94 | clover 2618 95 | fleuron 2619 96 | 97 | skull+crossbones 2620 98 | radiation 2622 99 | biohazard 2623 100 | caduceus 2624 101 | ankh 2625 102 | crosspotent 2629 103 | star+crescent 262A 104 | iran 262B 105 | khanda 262C 106 | soviet 262D 107 | nonukes 262E 108 | yinyang 262F 109 | sadface 2639 110 | happyface 263A 111 | heaven-trigram 2630 112 | menu3 2630 113 | recycle 2672 114 | whiteflag 2690 115 | blackflag 2691 116 | anchor 2693 117 | crossed-swords 2694 118 | asklepian 2695 119 | scales 2696 120 | alembic 2697 121 | flower 2698 122 | cog 2699 123 | atom 269B 124 | fleurdelys 269C 125 | warning 26A0 126 | voltage 26A1 127 | soccer 26BD 128 | baseball 26BE 129 | sun+clouds 26C5 130 | storm 26C8 131 | pixaxe 26CF 132 | skid 26D0 133 | stop 26C4 134 | 135 | dice1 2680 136 | dice2 2681 137 | dice3 2682 138 | dice4 2683 139 | dice5 2684 140 | dice6 2685 141 | 142 | spades 2660 143 | hearts 2665 144 | diamonds 2666 145 | clubs 2663 146 | 147 | keyboard 2328 148 | envelope 2709 149 | tick 2713 150 | heavytick 2714 151 | cross 2A2F 152 | heavycross 274C 153 | sqrt 221A 154 | 155 | clock 23F2 156 | watch 231A 157 | alarm-clock 23F0 158 | 159 | hourglass 29d6 160 | hourglass2 29d7 161 | 162 | scissors 2702 163 | helm 2388 164 | 165 | floppy 1f4be 166 | wfloppy 1f5aa 167 | 168 | euro 20AC 169 | cent 00a2 170 | pound 00a3 171 | currency 00a3 172 | yen 00a5 173 | brokenbar 00a6 174 | section 00a7 175 | copyright 00a9 176 | 177 | division 2797 178 | multiply 00d7 179 | 180 | onsen 2668 181 | hotsprings 2668 182 | wheelchair 267F 183 | 184 | telerecorder 2315 185 | magnifier 2315 186 | search 2315 187 | cup 26FE 188 | book 1F4D6 189 | 190 | male 2642 191 | female 2640 192 | position 2316 193 | crosshairs 2316 194 | 195 | upleft-arc 25DC 196 | upright-arc 25DD 197 | lowright-arc 25DE 198 | lowleft-arc 25DF 199 | 200 | 201 | gclef 1D11E 202 | rainbow 1F308 203 | 204 | globe 1F310 205 | thermometer 1F321 206 | ghost 1F47B 207 | alien 1F47D 208 | invader 1F47E 209 | satdish 1F4E1 210 | lock+key 1F510 211 | lock 1F512 212 | unlock 1F513 213 | key 1F5DD 214 | link 1F517 215 | bomb 1F4A3 216 | folder 1F4C1 217 | openfolder 1F4C2 218 | paperclip 1F4CE 219 | speaker-mute 1F507 220 | speaker 1F508 221 | speaker-low 1F509 222 | speaker-high 1F50A 223 | battery 1F50B 224 | electric-plug 1F50C 225 | magnify-left 1F50D 226 | magnify-right 1F50E 227 | microscope 1F52C 228 | telescope 1F52D 229 | mute 1F507 230 | folder2 1F5C0 231 | openfolder2 1F5C1 232 | document 1F5CE 233 | radio 1F4FB 234 | wifibars 1F4F6 235 | satdish 1F4E1 236 | pushpin 1F4CC 237 | shopping 1F6D2 238 | eye 1F441 239 | 240 | joystick 1F579 241 | menu 11054 242 | menu2 1D362 243 | -------------------------------------------------------------------------------- /whirlpool.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: CC-PDDC 3 | */ 4 | 5 | /* 6 | This module (whirlpool.h and whirlpool.c) are modified from the reference implementation 7 | published by Paulo S.L.M. Barreto and Vincent Rijmen. 8 | 9 | The authors have stated: "WHIRLPOOL is not (and will never be) patented. It may be used free of charge for any purpose. The reference implementations are in the public domain." 10 | 11 | References: 12 | https://en.wikipedia.org/wiki/Whirlpool_(hash_function) 13 | https://web.archive.org/web/20171129084214/http://www.larc.usp.br/~pbarreto/WhirlpoolPage.html 14 | 15 | */ 16 | 17 | #ifndef HASH_WHIRLPOOL_H 18 | #define HASH_WHIRLPOOL_H 19 | 20 | #include 21 | 22 | /* 23 | * Whirlpool-specific definitions. 24 | */ 25 | 26 | #define WHIRLPOOL_DIGESTBYTES 64 27 | #define WHIRLPOOL_DIGESTBITS (8*WHIRLPOOL_DIGESTBYTES) /* 512 */ 28 | 29 | #define WBLOCKBYTES 64 30 | #define WBLOCKBITS (8*WBLOCKBYTES) /* 512 */ 31 | 32 | #define LENGTHBYTES 32 33 | #define LENGTHBITS (8*LENGTHBYTES) /* 256 */ 34 | 35 | 36 | #ifdef __cplusplus 37 | extern "C" { 38 | #endif 39 | 40 | 41 | typedef struct WHIRLPOOLstruct 42 | { 43 | unsigned char bitLength[LENGTHBYTES]; /* global number of hashed bits (256-bit counter) */ 44 | unsigned char buffer[WBLOCKBYTES]; /* buffer of data to hash */ 45 | int bufferBits; /* current number of bits on the buffer */ 46 | int bufferPos; /* current (possibly incomplete) byte slot on the buffer */ 47 | uint64_t hash[WHIRLPOOL_DIGESTBYTES/8]; /* the hashing state */ 48 | } WHIRLPOOLstruct; 49 | 50 | 51 | void WHIRLPOOLinit(struct WHIRLPOOLstruct * const structpointer); 52 | void WHIRLPOOLadd(const unsigned char * const source, unsigned long sourceBits, struct WHIRLPOOLstruct * const structpointer); 53 | void WHIRLPOOLfinalize(struct WHIRLPOOLstruct * const structpointer, unsigned char * const result); 54 | 55 | 56 | #ifdef __cplusplus 57 | } 58 | #endif 59 | 60 | 61 | #endif 62 | 63 | 64 | --------------------------------------------------------------------------------