cSvn-UI for SVN Repositories

cGit-UI – is a web interface for Subversion (SVN) Repositories. cSvn CGI script is writen in C and therefore it's fast enough

6 Commits   0 Branches   2 Tags
bfc1508d (kx 2023-03-24 03:55:33 +0300   1) 
bfc1508d (kx 2023-03-24 03:55:33 +0300   2) #ifdef HAVE_CONFIG_H
bfc1508d (kx 2023-03-24 03:55:33 +0300   3) #include <config.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300   4) #endif
bfc1508d (kx 2023-03-24 03:55:33 +0300   5) 
bfc1508d (kx 2023-03-24 03:55:33 +0300   6) #include <stdlib.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300   7) #include <stdio.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300   8) #include <sys/sysinfo.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300   9) #include <sys/types.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  10) #include <stdint.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  11) #include <dirent.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  12) #include <sys/stat.h> /* chmod(2)    */
bfc1508d (kx 2023-03-24 03:55:33 +0300  13) #include <sys/file.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  14) #include <sys/mman.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  15) #include <fcntl.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  16) #include <limits.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  17) #include <string.h>   /* strdup(3)   */
bfc1508d (kx 2023-03-24 03:55:33 +0300  18) #include <libgen.h>   /* basename(3) */
bfc1508d (kx 2023-03-24 03:55:33 +0300  19) #include <ctype.h>    /* tolower(3)  */
bfc1508d (kx 2023-03-24 03:55:33 +0300  20) #include <errno.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  21) #include <time.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  22) #include <sys/time.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  23) #include <pwd.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  24) #include <grp.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  25) #include <stdarg.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  26) #include <unistd.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  27) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  28) #define PCRE2_CODE_UNIT_WIDTH 8
bfc1508d (kx 2023-03-24 03:55:33 +0300  29) #include <pcre2.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  30) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  31) #include <nls.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  32) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  33) #include <defs.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  34) #include <wrapper.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  35) #include <strbuf.h>
bfc1508d (kx 2023-03-24 03:55:33 +0300  36) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  37) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  38) struct symbol *strbuf_envtab = (struct symbol *)0;
bfc1508d (kx 2023-03-24 03:55:33 +0300  39) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  40) struct symbol *envtab_install( struct symbol **sym, const char *n, const char *v, envtab_error fatal )
bfc1508d (kx 2023-03-24 03:55:33 +0300  41) {
bfc1508d (kx 2023-03-24 03:55:33 +0300  42)   struct symbol *ep = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300  43)   size_t len;
bfc1508d (kx 2023-03-24 03:55:33 +0300  44) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  45)   if( !sym || !n || !v || !fatal )
bfc1508d (kx 2023-03-24 03:55:33 +0300  46)     return (struct symbol *)NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300  47) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  48)   ep = (struct symbol *)malloc( sizeof(struct symbol) );
bfc1508d (kx 2023-03-24 03:55:33 +0300  49)   if( !ep )
bfc1508d (kx 2023-03-24 03:55:33 +0300  50)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300  51)     fatal( "cannot allocate memory for symbol '%s'", n );
bfc1508d (kx 2023-03-24 03:55:33 +0300  52)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300  53)   bzero( (void *)ep, sizeof(struct symbol) );
bfc1508d (kx 2023-03-24 03:55:33 +0300  54) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  55)   len = strlen( n ) + 1;
bfc1508d (kx 2023-03-24 03:55:33 +0300  56)   ep->name = (char *)malloc( len );
bfc1508d (kx 2023-03-24 03:55:33 +0300  57)   if( !ep->name )
bfc1508d (kx 2023-03-24 03:55:33 +0300  58)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300  59)     fatal( "cannot allocate memory for symbol name '%s'", n );
bfc1508d (kx 2023-03-24 03:55:33 +0300  60)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300  61)   bzero( (void *)ep->name, len );
bfc1508d (kx 2023-03-24 03:55:33 +0300  62)   strncpy( ep->name, n, len );
bfc1508d (kx 2023-03-24 03:55:33 +0300  63) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  64)   len = strlen( v ) + 1;
bfc1508d (kx 2023-03-24 03:55:33 +0300  65)   ep->value = (char *)malloc( len );
bfc1508d (kx 2023-03-24 03:55:33 +0300  66)   if( !ep->value )
bfc1508d (kx 2023-03-24 03:55:33 +0300  67)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300  68)     fatal( "cannot allocate memory for symbol value '%s'", v );
bfc1508d (kx 2023-03-24 03:55:33 +0300  69)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300  70)   bzero( (void *)ep->value, len );
bfc1508d (kx 2023-03-24 03:55:33 +0300  71)   strncpy( ep->value, v, len );
bfc1508d (kx 2023-03-24 03:55:33 +0300  72) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  73)   ep->next = *sym;
bfc1508d (kx 2023-03-24 03:55:33 +0300  74)   *sym = ep;
bfc1508d (kx 2023-03-24 03:55:33 +0300  75) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  76)   return ep;
bfc1508d (kx 2023-03-24 03:55:33 +0300  77) }
bfc1508d (kx 2023-03-24 03:55:33 +0300  78) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  79) struct symbol *envtab_lookup( struct symbol **sym, const char *n )
bfc1508d (kx 2023-03-24 03:55:33 +0300  80) {
bfc1508d (kx 2023-03-24 03:55:33 +0300  81)   struct symbol *ep = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300  82) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  83)   if( !sym || !n )
bfc1508d (kx 2023-03-24 03:55:33 +0300  84)     return (struct symbol *)NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300  85) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  86)   for( ep = *sym; ep != (struct symbol *)0; ep = ep->next )
bfc1508d (kx 2023-03-24 03:55:33 +0300  87)       if( strcmp( ep->name, n ) == 0 ) return( ep );
bfc1508d (kx 2023-03-24 03:55:33 +0300  88) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  89)   return (struct symbol *)NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300  90) }
bfc1508d (kx 2023-03-24 03:55:33 +0300  91) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  92) void envtab_release( struct symbol **sym )
bfc1508d (kx 2023-03-24 03:55:33 +0300  93) {
bfc1508d (kx 2023-03-24 03:55:33 +0300  94)   struct symbol *tab = *sym;
bfc1508d (kx 2023-03-24 03:55:33 +0300  95) 
bfc1508d (kx 2023-03-24 03:55:33 +0300  96)   while( tab )
bfc1508d (kx 2023-03-24 03:55:33 +0300  97)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300  98)     struct symbol *ep = tab;
bfc1508d (kx 2023-03-24 03:55:33 +0300  99)     tab = ep->next;
bfc1508d (kx 2023-03-24 03:55:33 +0300 100)     if( ep->name )  free( ep->name );
bfc1508d (kx 2023-03-24 03:55:33 +0300 101)     if( ep->value ) free( ep->value );
bfc1508d (kx 2023-03-24 03:55:33 +0300 102)     free( ep );
bfc1508d (kx 2023-03-24 03:55:33 +0300 103)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 104)   *sym = (struct symbol *)NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300 105) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 106) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 107) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 108) #define STRBUF_ERRMSG_SIZE 4096
bfc1508d (kx 2023-03-24 03:55:33 +0300 109) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 110) void strbuf_fatal( const char *fmt, ... )
bfc1508d (kx 2023-03-24 03:55:33 +0300 111) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 112)   va_list arg_ptr;
bfc1508d (kx 2023-03-24 03:55:33 +0300 113)   char  buf[STRBUF_ERRMSG_SIZE];
bfc1508d (kx 2023-03-24 03:55:33 +0300 114)   char  msg[STRBUF_ERRMSG_SIZE];
bfc1508d (kx 2023-03-24 03:55:33 +0300 115)   char *format = "%s: %s\n";
bfc1508d (kx 2023-03-24 03:55:33 +0300 116) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 117)   va_start( arg_ptr, fmt );
bfc1508d (kx 2023-03-24 03:55:33 +0300 118) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 119)   vsnprintf( msg, STRBUF_ERRMSG_SIZE, (const void *)fmt, arg_ptr );
bfc1508d (kx 2023-03-24 03:55:33 +0300 120) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 121)   va_end( arg_ptr ); /* Reset variable arguments. */
bfc1508d (kx 2023-03-24 03:55:33 +0300 122) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 123)   snprintf( buf, STRBUF_ERRMSG_SIZE, format, "strbuf", msg );
bfc1508d (kx 2023-03-24 03:55:33 +0300 124) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 125)   (void)write( STDERR_FILENO, buf, strlen( buf ) );
bfc1508d (kx 2023-03-24 03:55:33 +0300 126) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 127)   exit( 1 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 128) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 129) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 130) char strbuf_slopbuf[1];
bfc1508d (kx 2023-03-24 03:55:33 +0300 131) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 132) #define alloc_nz(x) (((x)+16)*3/2)
bfc1508d (kx 2023-03-24 03:55:33 +0300 133) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 134) static void alloc_grow( struct strbuf *sb, size_t size )
bfc1508d (kx 2023-03-24 03:55:33 +0300 135) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 136)   if( size > sb->alloc )
bfc1508d (kx 2023-03-24 03:55:33 +0300 137)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 138)     if( alloc_nz(sb->alloc) < (size) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 139)       sb->alloc = size;
bfc1508d (kx 2023-03-24 03:55:33 +0300 140)     else
bfc1508d (kx 2023-03-24 03:55:33 +0300 141)       sb->alloc = alloc_nz(sb->alloc);
bfc1508d (kx 2023-03-24 03:55:33 +0300 142) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 143)     sb->buf = xrealloc( (void *)sb->buf, sb->alloc );
bfc1508d (kx 2023-03-24 03:55:33 +0300 144)     memset( (void *)(sb->buf + sb->len), 0, (size_t)(sb->alloc - sb->len) );
bfc1508d (kx 2023-03-24 03:55:33 +0300 145)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 146) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 147) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 148) void strbuf_grow( struct strbuf *sb, size_t extra )
bfc1508d (kx 2023-03-24 03:55:33 +0300 149) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 150)   int new_buf = !sb->alloc;
bfc1508d (kx 2023-03-24 03:55:33 +0300 151) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 152)   if( new_buf )
bfc1508d (kx 2023-03-24 03:55:33 +0300 153)     sb->buf = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300 154) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 155)   alloc_grow( sb, sb->len + extra + 1 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 156) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 157)   if( new_buf )
bfc1508d (kx 2023-03-24 03:55:33 +0300 158)     sb->buf[0] = '\0';
bfc1508d (kx 2023-03-24 03:55:33 +0300 159) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 160) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 161) /*
bfc1508d (kx 2023-03-24 03:55:33 +0300 162)    Функцию strbuf_init() надо вызывать в том случае, когда необходимо
bfc1508d (kx 2023-03-24 03:55:33 +0300 163)    задать внешнюю функцию обработки фатальной ошибки. Функция обработки
bfc1508d (kx 2023-03-24 03:55:33 +0300 164)    фатальной ошибки, в отличие от стандартной, может выводить как JSON
bfc1508d (kx 2023-03-24 03:55:33 +0300 165)    ответы, так и файлы 404.html, 50x.html, используя собственный буфер.
bfc1508d (kx 2023-03-24 03:55:33 +0300 166)  */
bfc1508d (kx 2023-03-24 03:55:33 +0300 167) void strbuf_init( struct strbuf *sb, strbuf_error fatal, size_t hint )
bfc1508d (kx 2023-03-24 03:55:33 +0300 168) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 169)   sb->alloc = sb->len = 0;
bfc1508d (kx 2023-03-24 03:55:33 +0300 170)   sb->fatal = strbuf_fatal;
bfc1508d (kx 2023-03-24 03:55:33 +0300 171)   sb->buf   = strbuf_slopbuf;
bfc1508d (kx 2023-03-24 03:55:33 +0300 172) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 173)   if( fatal )
bfc1508d (kx 2023-03-24 03:55:33 +0300 174)     sb->fatal = fatal;
bfc1508d (kx 2023-03-24 03:55:33 +0300 175) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 176)   if( hint )
bfc1508d (kx 2023-03-24 03:55:33 +0300 177)     strbuf_grow( sb, hint );
bfc1508d (kx 2023-03-24 03:55:33 +0300 178) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 179) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 180) void strbuf_release( struct strbuf *sb )
bfc1508d (kx 2023-03-24 03:55:33 +0300 181) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 182)   if( sb->alloc )
bfc1508d (kx 2023-03-24 03:55:33 +0300 183)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 184)     free( sb->buf );
bfc1508d (kx 2023-03-24 03:55:33 +0300 185)     strbuf_init( sb, (strbuf_error)0, 0 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 186)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 187) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 188) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 189) char *strbuf_detach( struct strbuf *sb, size_t *sz )
bfc1508d (kx 2023-03-24 03:55:33 +0300 190) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 191)   char *ret;
bfc1508d (kx 2023-03-24 03:55:33 +0300 192)   strbuf_grow( sb, 0 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 193)   ret = sb->buf;
bfc1508d (kx 2023-03-24 03:55:33 +0300 194)   if( sz )
bfc1508d (kx 2023-03-24 03:55:33 +0300 195)     *sz = sb->len;
bfc1508d (kx 2023-03-24 03:55:33 +0300 196)   strbuf_init( sb, sb->fatal, 0 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 197)   return ret;
bfc1508d (kx 2023-03-24 03:55:33 +0300 198) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 199) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 200) void strbuf_attach( struct strbuf *sb, void *buf, size_t len, size_t alloc )
bfc1508d (kx 2023-03-24 03:55:33 +0300 201) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 202)   strbuf_release( sb );
bfc1508d (kx 2023-03-24 03:55:33 +0300 203)   sb->buf   = buf;
bfc1508d (kx 2023-03-24 03:55:33 +0300 204)   sb->len   = len;
bfc1508d (kx 2023-03-24 03:55:33 +0300 205)   sb->alloc = alloc;
bfc1508d (kx 2023-03-24 03:55:33 +0300 206)   strbuf_grow( sb, 0 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 207)   sb->buf[sb->len] = '\0';
bfc1508d (kx 2023-03-24 03:55:33 +0300 208) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 209) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 210) void strbuf_ltrim( struct strbuf *sb )
bfc1508d (kx 2023-03-24 03:55:33 +0300 211) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 212)   char *b = sb->buf;
bfc1508d (kx 2023-03-24 03:55:33 +0300 213)   while( sb->len > 0 && isspace(*b) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 214)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 215)     b++;
bfc1508d (kx 2023-03-24 03:55:33 +0300 216)     sb->len--;
bfc1508d (kx 2023-03-24 03:55:33 +0300 217)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 218)   memmove( sb->buf, b, sb->len );
bfc1508d (kx 2023-03-24 03:55:33 +0300 219)   sb->buf[sb->len] = '\0';
bfc1508d (kx 2023-03-24 03:55:33 +0300 220) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 221) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 222) void strbuf_rtrim( struct strbuf *sb )
bfc1508d (kx 2023-03-24 03:55:33 +0300 223) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 224)   while( sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1]) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 225)     sb->len--;
bfc1508d (kx 2023-03-24 03:55:33 +0300 226)   sb->buf[sb->len] = '\0';
bfc1508d (kx 2023-03-24 03:55:33 +0300 227) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 228) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 229) void strbuf_trim( struct strbuf *sb )
bfc1508d (kx 2023-03-24 03:55:33 +0300 230) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 231)   strbuf_rtrim( sb );
bfc1508d (kx 2023-03-24 03:55:33 +0300 232)   strbuf_ltrim( sb );
bfc1508d (kx 2023-03-24 03:55:33 +0300 233) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 234) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 235) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 236) void strbuf_trim_trailing_dir_sep( struct strbuf *sb )
bfc1508d (kx 2023-03-24 03:55:33 +0300 237) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 238)   while( sb->len > 0 && is_dir_sep((unsigned char)sb->buf[sb->len - 1]) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 239)     sb->len--;
bfc1508d (kx 2023-03-24 03:55:33 +0300 240)   sb->buf[sb->len] = '\0';
bfc1508d (kx 2023-03-24 03:55:33 +0300 241) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 242) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 243) void strbuf_trim_trailing_newline( struct strbuf *sb )
bfc1508d (kx 2023-03-24 03:55:33 +0300 244) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 245)   if( sb->len > 0 && sb->buf[sb->len - 1] == '\n' )
bfc1508d (kx 2023-03-24 03:55:33 +0300 246)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 247)     if( --sb->len > 0 && sb->buf[sb->len - 1] == '\r' )
bfc1508d (kx 2023-03-24 03:55:33 +0300 248)       --sb->len;
bfc1508d (kx 2023-03-24 03:55:33 +0300 249)     sb->buf[sb->len] = '\0';
bfc1508d (kx 2023-03-24 03:55:33 +0300 250)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 251) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 252) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 253) int strbuf_cmp( const struct strbuf *a, const struct strbuf *b )
bfc1508d (kx 2023-03-24 03:55:33 +0300 254) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 255)   size_t len = a->len < b->len ? a->len: b->len;
bfc1508d (kx 2023-03-24 03:55:33 +0300 256)   int    cmp = memcmp( a->buf, b->buf, len );
bfc1508d (kx 2023-03-24 03:55:33 +0300 257)   if( cmp )
bfc1508d (kx 2023-03-24 03:55:33 +0300 258)     return cmp;
bfc1508d (kx 2023-03-24 03:55:33 +0300 259)   return a->len < b->len ? -1: a->len != b->len;
bfc1508d (kx 2023-03-24 03:55:33 +0300 260) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 261) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 262) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 263) /* Adding data to the buffer */
bfc1508d (kx 2023-03-24 03:55:33 +0300 264) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 265) void strbuf_add( struct strbuf *sb, const void *data, size_t len )
bfc1508d (kx 2023-03-24 03:55:33 +0300 266) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 267)   strbuf_grow( sb, len );
bfc1508d (kx 2023-03-24 03:55:33 +0300 268)   memcpy( sb->buf + sb->len, data, len );
bfc1508d (kx 2023-03-24 03:55:33 +0300 269)   strbuf_setlen( sb, sb->len + len );
bfc1508d (kx 2023-03-24 03:55:33 +0300 270) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 271) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 272) void strbuf_addbuf( struct strbuf *sb, const struct strbuf *sb2 )
bfc1508d (kx 2023-03-24 03:55:33 +0300 273) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 274)   strbuf_grow( sb, sb2->len );
bfc1508d (kx 2023-03-24 03:55:33 +0300 275)   memcpy( sb->buf + sb->len, sb2->buf, sb2->len );
bfc1508d (kx 2023-03-24 03:55:33 +0300 276)   strbuf_setlen( sb, sb->len + sb2->len );
bfc1508d (kx 2023-03-24 03:55:33 +0300 277) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 278) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 279) void strbuf_addbuf_percentquote( struct strbuf *dst, const struct strbuf *src )
bfc1508d (kx 2023-03-24 03:55:33 +0300 280) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 281)   size_t i, len = src->len;
bfc1508d (kx 2023-03-24 03:55:33 +0300 282) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 283)   for (i = 0; i < len; i++) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 284)     if( src->buf[i] == '%' )
bfc1508d (kx 2023-03-24 03:55:33 +0300 285)       strbuf_addch( dst, '%' );
bfc1508d (kx 2023-03-24 03:55:33 +0300 286)     strbuf_addch( dst, src->buf[i] );
bfc1508d (kx 2023-03-24 03:55:33 +0300 287)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 288) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 289) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 290) void strbuf_addchars( struct strbuf *sb, int c, size_t n )
bfc1508d (kx 2023-03-24 03:55:33 +0300 291) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 292)   strbuf_grow( sb, n );
bfc1508d (kx 2023-03-24 03:55:33 +0300 293)   memset( sb->buf + sb->len, c, n );
bfc1508d (kx 2023-03-24 03:55:33 +0300 294)   strbuf_setlen( sb, sb->len + n );
bfc1508d (kx 2023-03-24 03:55:33 +0300 295) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 296) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 297) void strbuf_vaddf( struct strbuf *sb, const char *fmt, va_list ap )
bfc1508d (kx 2023-03-24 03:55:33 +0300 298) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 299)   int len;
bfc1508d (kx 2023-03-24 03:55:33 +0300 300)   va_list cp;
bfc1508d (kx 2023-03-24 03:55:33 +0300 301) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 302)   if( !strbuf_avail( sb ) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 303)     strbuf_grow( sb, 64 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 304)   va_copy( cp, ap );
bfc1508d (kx 2023-03-24 03:55:33 +0300 305)   len = vsnprintf( sb->buf + sb->len, sb->alloc - sb->len, fmt, cp );
bfc1508d (kx 2023-03-24 03:55:33 +0300 306)   va_end( cp );
bfc1508d (kx 2023-03-24 03:55:33 +0300 307)   if( len < 0 )
bfc1508d (kx 2023-03-24 03:55:33 +0300 308)     sb->fatal( "your vsnprintf is broken (returned %d)", len );
bfc1508d (kx 2023-03-24 03:55:33 +0300 309)   if( len > strbuf_avail( sb ) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 310)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 311)     strbuf_grow( sb, len );
bfc1508d (kx 2023-03-24 03:55:33 +0300 312)     len = vsnprintf( sb->buf + sb->len, sb->alloc - sb->len, fmt, ap );
bfc1508d (kx 2023-03-24 03:55:33 +0300 313)     if( len > strbuf_avail( sb ) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 314)       sb->fatal( "your vsnprintf is broken (insatiable)" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 315)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 316)   strbuf_setlen( sb, sb->len + len );
bfc1508d (kx 2023-03-24 03:55:33 +0300 317) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 318) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 319) void strbuf_addf( struct strbuf *sb, const char *fmt, ... )
bfc1508d (kx 2023-03-24 03:55:33 +0300 320) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 321)   va_list ap;
bfc1508d (kx 2023-03-24 03:55:33 +0300 322)   va_start( ap, fmt );
bfc1508d (kx 2023-03-24 03:55:33 +0300 323)   strbuf_vaddf( sb, fmt, ap );
bfc1508d (kx 2023-03-24 03:55:33 +0300 324)   va_end( ap );
bfc1508d (kx 2023-03-24 03:55:33 +0300 325) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 326) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 327) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 328) size_t strbuf_fread( struct strbuf *sb, FILE *fp )
bfc1508d (kx 2023-03-24 03:55:33 +0300 329) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 330)   size_t ret, nb = 64, read = 0;
bfc1508d (kx 2023-03-24 03:55:33 +0300 331)   size_t oldalloc = sb->alloc;
bfc1508d (kx 2023-03-24 03:55:33 +0300 332) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 333)   if( !sb || !fp ) return read;
bfc1508d (kx 2023-03-24 03:55:33 +0300 334) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 335)   do
bfc1508d (kx 2023-03-24 03:55:33 +0300 336)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 337)     strbuf_grow( sb, nb );
bfc1508d (kx 2023-03-24 03:55:33 +0300 338)     ret = fread( sb->buf + sb->len, 1, nb, fp );
bfc1508d (kx 2023-03-24 03:55:33 +0300 339)     if( ret > 0 )
bfc1508d (kx 2023-03-24 03:55:33 +0300 340)     {
bfc1508d (kx 2023-03-24 03:55:33 +0300 341)       strbuf_setlen( sb, sb->len + ret );
bfc1508d (kx 2023-03-24 03:55:33 +0300 342)       read += ret;
bfc1508d (kx 2023-03-24 03:55:33 +0300 343)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300 344)     else if( oldalloc == 0 )
bfc1508d (kx 2023-03-24 03:55:33 +0300 345)     {
bfc1508d (kx 2023-03-24 03:55:33 +0300 346)       strbuf_release( sb );
bfc1508d (kx 2023-03-24 03:55:33 +0300 347)       return ret;
bfc1508d (kx 2023-03-24 03:55:33 +0300 348)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300 349) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 350)   } while( ret == nb );
bfc1508d (kx 2023-03-24 03:55:33 +0300 351) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 352)   return read;
bfc1508d (kx 2023-03-24 03:55:33 +0300 353) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 354) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 355) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 356) #define NAMELEN_MAX  128
bfc1508d (kx 2023-03-24 03:55:33 +0300 357) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 358) size_t strbuf_env_fread( struct strbuf *sb, FILE *fp )
bfc1508d (kx 2023-03-24 03:55:33 +0300 359) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 360)   size_t  read = 0;
bfc1508d (kx 2023-03-24 03:55:33 +0300 361)   char   *ln, line[STRBUF_MAXLINE], retline[STRBUF_MAXLINE];
bfc1508d (kx 2023-03-24 03:55:33 +0300 362) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 363)   if( !sb || !fp ) return read;
bfc1508d (kx 2023-03-24 03:55:33 +0300 364) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 365)   bzero( (void *)line, STRBUF_MAXLINE );
bfc1508d (kx 2023-03-24 03:55:33 +0300 366)   bzero( (void *)retline, STRBUF_MAXLINE );
bfc1508d (kx 2023-03-24 03:55:33 +0300 367) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 368)   while( (ln = fgets( line, STRBUF_MAXLINE, fp )) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 369)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 370)     char *start = NULL, *stop = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300 371)     char *sp = ln;
bfc1508d (kx 2023-03-24 03:55:33 +0300 372) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 373)     if( (start = strstr( sp, "${" )) && (stop = strstr( sp, "}" )) && ((stop - start) > 1) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 374)     {
bfc1508d (kx 2023-03-24 03:55:33 +0300 375)       struct symbol *sym = NULL;
bfc1508d (kx 2023-03-24 03:55:33 +0300 376)       char  *lp = retline;
bfc1508d (kx 2023-03-24 03:55:33 +0300 377) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 378)       do
bfc1508d (kx 2023-03-24 03:55:33 +0300 379)       {
bfc1508d (kx 2023-03-24 03:55:33 +0300 380)         /* may be multiple variables on a single line: */
bfc1508d (kx 2023-03-24 03:55:33 +0300 381) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 382)         *start = '\0'; *stop++ = '\0';
bfc1508d (kx 2023-03-24 03:55:33 +0300 383)         if( (sym = envtab_lookup( &strbuf_envtab, start+2 )) && sym->value && sym->value[0] )
bfc1508d (kx 2023-03-24 03:55:33 +0300 384)         {
bfc1508d (kx 2023-03-24 03:55:33 +0300 385)           strncpy( lp, (const char *)sp, (size_t)(start - sp + 1) );
bfc1508d (kx 2023-03-24 03:55:33 +0300 386)           lp += (start - sp);
bfc1508d (kx 2023-03-24 03:55:33 +0300 387)           strcpy( lp, (const char *)sym->value );
bfc1508d (kx 2023-03-24 03:55:33 +0300 388)           lp += strlen( sym->value );
bfc1508d (kx 2023-03-24 03:55:33 +0300 389)           strcpy( lp, (const char *)stop );
bfc1508d (kx 2023-03-24 03:55:33 +0300 390)           sp = stop;
bfc1508d (kx 2023-03-24 03:55:33 +0300 391)         }
bfc1508d (kx 2023-03-24 03:55:33 +0300 392)         else
bfc1508d (kx 2023-03-24 03:55:33 +0300 393)         {
bfc1508d (kx 2023-03-24 03:55:33 +0300 394)           strncpy( lp, (const char *)sp, (size_t)(start - sp + 1) );
bfc1508d (kx 2023-03-24 03:55:33 +0300 395)           lp += (start - sp);
bfc1508d (kx 2023-03-24 03:55:33 +0300 396)           strcpy( lp, (const char *)stop );
bfc1508d (kx 2023-03-24 03:55:33 +0300 397)           sp = stop;
bfc1508d (kx 2023-03-24 03:55:33 +0300 398)         }
bfc1508d (kx 2023-03-24 03:55:33 +0300 399) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 400)       } while( (start = strstr( sp, "${" )) && (stop = strstr( sp, "}" )) && ((stop - start) > 1) );
bfc1508d (kx 2023-03-24 03:55:33 +0300 401) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 402)       strbuf_addstr( sb, retline );
bfc1508d (kx 2023-03-24 03:55:33 +0300 403)       read += strlen( retline );;
bfc1508d (kx 2023-03-24 03:55:33 +0300 404)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300 405)     else
bfc1508d (kx 2023-03-24 03:55:33 +0300 406)     {
bfc1508d (kx 2023-03-24 03:55:33 +0300 407)       strbuf_addstr( sb, line );
bfc1508d (kx 2023-03-24 03:55:33 +0300 408)       read += strlen( line );;
bfc1508d (kx 2023-03-24 03:55:33 +0300 409)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300 410) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 411)   } /* End of while( ln ) */
bfc1508d (kx 2023-03-24 03:55:33 +0300 412) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 413)   return read;
bfc1508d (kx 2023-03-24 03:55:33 +0300 414) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 415) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 416) ssize_t strbuf_read( struct strbuf *sb, int fd, size_t hint )
bfc1508d (kx 2023-03-24 03:55:33 +0300 417) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 418)   size_t oldlen   = sb->len;
bfc1508d (kx 2023-03-24 03:55:33 +0300 419)   size_t oldalloc = sb->alloc;
bfc1508d (kx 2023-03-24 03:55:33 +0300 420) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 421)   strbuf_grow(sb, hint ? hint : 8192);
bfc1508d (kx 2023-03-24 03:55:33 +0300 422)   for( ;; )
bfc1508d (kx 2023-03-24 03:55:33 +0300 423)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 424)     ssize_t want = sb->alloc - sb->len - 1;
bfc1508d (kx 2023-03-24 03:55:33 +0300 425)     ssize_t got  = read_in_full( fd, sb->buf + sb->len, want );
bfc1508d (kx 2023-03-24 03:55:33 +0300 426) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 427)     if( got < 0 )
bfc1508d (kx 2023-03-24 03:55:33 +0300 428)     {
bfc1508d (kx 2023-03-24 03:55:33 +0300 429)       if( oldalloc == 0 )
bfc1508d (kx 2023-03-24 03:55:33 +0300 430)         strbuf_release( sb );
bfc1508d (kx 2023-03-24 03:55:33 +0300 431)       else
bfc1508d (kx 2023-03-24 03:55:33 +0300 432)         strbuf_setlen( sb, oldlen );
bfc1508d (kx 2023-03-24 03:55:33 +0300 433)       return -1;
bfc1508d (kx 2023-03-24 03:55:33 +0300 434)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300 435)     sb->len += got;
bfc1508d (kx 2023-03-24 03:55:33 +0300 436)     if( got < want )
bfc1508d (kx 2023-03-24 03:55:33 +0300 437)       break;
bfc1508d (kx 2023-03-24 03:55:33 +0300 438)     strbuf_grow( sb, 8192 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 439)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 440) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 441)   sb->buf[sb->len] = '\0';
bfc1508d (kx 2023-03-24 03:55:33 +0300 442)   return sb->len - oldlen;
bfc1508d (kx 2023-03-24 03:55:33 +0300 443) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 444) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 445) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 446) size_t strbuf_fwrite( struct strbuf *sb, FILE *fp )
bfc1508d (kx 2023-03-24 03:55:33 +0300 447) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 448)   return sb->len ? fwrite( sb->buf, 1, sb->len, fp ) : 0;
bfc1508d (kx 2023-03-24 03:55:33 +0300 449) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 450) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 451) ssize_t strbuf_write( struct strbuf *sb, int fd )
bfc1508d (kx 2023-03-24 03:55:33 +0300 452) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 453)   return sb->len ? write( fd, (const void *)sb->buf, sb->len ) : 0;
bfc1508d (kx 2023-03-24 03:55:33 +0300 454) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 455) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 456) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 457) /* XML quoted: */
bfc1508d (kx 2023-03-24 03:55:33 +0300 458) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 459) void strbuf_addstr_xml_quoted( struct strbuf *sb, const char *s )
bfc1508d (kx 2023-03-24 03:55:33 +0300 460) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 461)   while( *s )
bfc1508d (kx 2023-03-24 03:55:33 +0300 462)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 463)     size_t len = strcspn( s, "\"<>&" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 464)     strbuf_add( sb, s, len );
bfc1508d (kx 2023-03-24 03:55:33 +0300 465)     s += len;
bfc1508d (kx 2023-03-24 03:55:33 +0300 466) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 467)     switch( *s )
bfc1508d (kx 2023-03-24 03:55:33 +0300 468)     {
bfc1508d (kx 2023-03-24 03:55:33 +0300 469)       case '"':
bfc1508d (kx 2023-03-24 03:55:33 +0300 470)         strbuf_addstr( sb, "&quot;" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 471)         break;
bfc1508d (kx 2023-03-24 03:55:33 +0300 472)       case '<':
bfc1508d (kx 2023-03-24 03:55:33 +0300 473)         strbuf_addstr( sb, "&lt;" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 474)         break;
bfc1508d (kx 2023-03-24 03:55:33 +0300 475)       case '>':
bfc1508d (kx 2023-03-24 03:55:33 +0300 476)         strbuf_addstr( sb, "&gt;" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 477)         break;
bfc1508d (kx 2023-03-24 03:55:33 +0300 478)       case '&':
bfc1508d (kx 2023-03-24 03:55:33 +0300 479)         strbuf_addstr( sb, "&amp;" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 480)         break;
bfc1508d (kx 2023-03-24 03:55:33 +0300 481)       case 0:
bfc1508d (kx 2023-03-24 03:55:33 +0300 482)         return;
bfc1508d (kx 2023-03-24 03:55:33 +0300 483)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300 484)     s++;
bfc1508d (kx 2023-03-24 03:55:33 +0300 485)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 486) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 487) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 488) static int is_html_quoted( const char *str )
bfc1508d (kx 2023-03-24 03:55:33 +0300 489) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 490)   int         rc = 0, error = 0;
bfc1508d (kx 2023-03-24 03:55:33 +0300 491)   PCRE2_SIZE  offset = 0;
bfc1508d (kx 2023-03-24 03:55:33 +0300 492)   const char  pattern[] = "^(&[#A-Za-z0-9]*;)";
bfc1508d (kx 2023-03-24 03:55:33 +0300 493) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 494)   pcre2_match_data *match;
bfc1508d (kx 2023-03-24 03:55:33 +0300 495) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 496)   pcre2_code *regexp = pcre2_compile( (PCRE2_SPTR)pattern, PCRE2_ZERO_TERMINATED, 0, &error, &offset, NULL );
bfc1508d (kx 2023-03-24 03:55:33 +0300 497)   if( regexp == NULL )
bfc1508d (kx 2023-03-24 03:55:33 +0300 498)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 499)     return 0; /* PCRE compilation failed */
bfc1508d (kx 2023-03-24 03:55:33 +0300 500)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 501) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 502)   match = pcre2_match_data_create_from_pattern( regexp, NULL );
bfc1508d (kx 2023-03-24 03:55:33 +0300 503) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 504)   rc = pcre2_match( regexp, (PCRE2_SPTR)str, (PCRE2_SIZE)strlen(str), 0, 0, match, NULL ); /* sizeof(match)/sizeof(match[0]) */
bfc1508d (kx 2023-03-24 03:55:33 +0300 505)   if( rc < 0 )
bfc1508d (kx 2023-03-24 03:55:33 +0300 506)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 507)     /* not match */
bfc1508d (kx 2023-03-24 03:55:33 +0300 508)     pcre2_match_data_free( match );
bfc1508d (kx 2023-03-24 03:55:33 +0300 509)     pcre2_code_free( regexp );
bfc1508d (kx 2023-03-24 03:55:33 +0300 510)     return 0;
bfc1508d (kx 2023-03-24 03:55:33 +0300 511)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 512)   else
bfc1508d (kx 2023-03-24 03:55:33 +0300 513)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 514)     /* match */
bfc1508d (kx 2023-03-24 03:55:33 +0300 515)     pcre2_match_data_free( match );
bfc1508d (kx 2023-03-24 03:55:33 +0300 516)     pcre2_code_free( regexp );
bfc1508d (kx 2023-03-24 03:55:33 +0300 517)     return 1;
bfc1508d (kx 2023-03-24 03:55:33 +0300 518)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 519) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 520) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 521) void strbuf_addstr_html_quoted( struct strbuf *sb, const char *s )
bfc1508d (kx 2023-03-24 03:55:33 +0300 522) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 523)   while( *s )
bfc1508d (kx 2023-03-24 03:55:33 +0300 524)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 525)     size_t len = strcspn( s, "\"<>&" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 526)     strbuf_add( sb, s, len );
bfc1508d (kx 2023-03-24 03:55:33 +0300 527)     s += len;
bfc1508d (kx 2023-03-24 03:55:33 +0300 528) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 529)     switch( *s )
bfc1508d (kx 2023-03-24 03:55:33 +0300 530)     {
bfc1508d (kx 2023-03-24 03:55:33 +0300 531)       case '"':
bfc1508d (kx 2023-03-24 03:55:33 +0300 532)         strbuf_addstr( sb, "&quot;" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 533)         break;
bfc1508d (kx 2023-03-24 03:55:33 +0300 534)       case '<':
bfc1508d (kx 2023-03-24 03:55:33 +0300 535)         strbuf_addstr( sb, "&lt;" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 536)         break;
bfc1508d (kx 2023-03-24 03:55:33 +0300 537)       case '>':
bfc1508d (kx 2023-03-24 03:55:33 +0300 538)         strbuf_addstr( sb, "&gt;" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 539)         break;
bfc1508d (kx 2023-03-24 03:55:33 +0300 540)       case '&':
bfc1508d (kx 2023-03-24 03:55:33 +0300 541)         if( !is_html_quoted( s ) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 542)           strbuf_addstr( sb, "&amp;" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 543)         else
bfc1508d (kx 2023-03-24 03:55:33 +0300 544)           strbuf_addch( sb, *s );
bfc1508d (kx 2023-03-24 03:55:33 +0300 545)         break;
bfc1508d (kx 2023-03-24 03:55:33 +0300 546)       case 0:
bfc1508d (kx 2023-03-24 03:55:33 +0300 547)         return;
bfc1508d (kx 2023-03-24 03:55:33 +0300 548)     }
bfc1508d (kx 2023-03-24 03:55:33 +0300 549)     s++;
bfc1508d (kx 2023-03-24 03:55:33 +0300 550)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 551) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 552) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 553) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 554) /* urlencode: */
bfc1508d (kx 2023-03-24 03:55:33 +0300 555) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 556) int is_rfc3986_reserved_or_unreserved( char ch )
bfc1508d (kx 2023-03-24 03:55:33 +0300 557) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 558)   if( is_rfc3986_unreserved(ch) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 559)     return 1;
bfc1508d (kx 2023-03-24 03:55:33 +0300 560)   switch( ch )
bfc1508d (kx 2023-03-24 03:55:33 +0300 561)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 562)     case '!': case '*': case '\'': case '(': case ')': case ';':
bfc1508d (kx 2023-03-24 03:55:33 +0300 563)     case ':': case '@': case '&': case '=': case '+': case '$':
bfc1508d (kx 2023-03-24 03:55:33 +0300 564)     case ',': case '/': case '?': case '#': case '[': case ']':
bfc1508d (kx 2023-03-24 03:55:33 +0300 565)       return 1;
bfc1508d (kx 2023-03-24 03:55:33 +0300 566)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 567)   return 0;
bfc1508d (kx 2023-03-24 03:55:33 +0300 568) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 569) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 570) int is_rfc3986_unreserved( char ch )
bfc1508d (kx 2023-03-24 03:55:33 +0300 571) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 572)   return isalnum(ch) || ch == '-' || ch == '_' || ch == '.' || ch == '~';
bfc1508d (kx 2023-03-24 03:55:33 +0300 573) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 574) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 575) static void
bfc1508d (kx 2023-03-24 03:55:33 +0300 576) strbuf_add_urlencode( struct strbuf *sb, const char *s, size_t len,
bfc1508d (kx 2023-03-24 03:55:33 +0300 577)                       char_predicate allow_unencoded_fn )
bfc1508d (kx 2023-03-24 03:55:33 +0300 578) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 579)   strbuf_grow( sb, len );
bfc1508d (kx 2023-03-24 03:55:33 +0300 580)   while( len-- )
bfc1508d (kx 2023-03-24 03:55:33 +0300 581)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 582)     char ch = *s++;
bfc1508d (kx 2023-03-24 03:55:33 +0300 583)     if( allow_unencoded_fn(ch) )
bfc1508d (kx 2023-03-24 03:55:33 +0300 584)       strbuf_addch( sb, ch );
bfc1508d (kx 2023-03-24 03:55:33 +0300 585)     else
bfc1508d (kx 2023-03-24 03:55:33 +0300 586)       strbuf_addf( sb, "%%%02x", (unsigned char)ch );
bfc1508d (kx 2023-03-24 03:55:33 +0300 587)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 588) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 589) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 590) void strbuf_addstr_urlencode( struct strbuf *sb, const char *s, char_predicate allow_unencoded_fn )
bfc1508d (kx 2023-03-24 03:55:33 +0300 591) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 592)   strbuf_add_urlencode( sb, s, strlen(s), allow_unencoded_fn );
bfc1508d (kx 2023-03-24 03:55:33 +0300 593) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 594) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 595) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 596) /* humanise: */
bfc1508d (kx 2023-03-24 03:55:33 +0300 597) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 598) static void strbuf_humanise( struct strbuf *sb, off_t bytes, int humanise_rate )
bfc1508d (kx 2023-03-24 03:55:33 +0300 599) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 600)   if( bytes > 1 << 30 )
bfc1508d (kx 2023-03-24 03:55:33 +0300 601)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 602)     strbuf_addf( sb,
bfc1508d (kx 2023-03-24 03:55:33 +0300 603)       humanise_rate == 0 ?
bfc1508d (kx 2023-03-24 03:55:33 +0300 604)         /* TRANSLATORS: IEC 80000-13:2008 gibibyte */
bfc1508d (kx 2023-03-24 03:55:33 +0300 605)         _("%u.%2.2u GiB") :
bfc1508d (kx 2023-03-24 03:55:33 +0300 606)         /* TRANSLATORS: IEC 80000-13:2008 gibibyte/second */
bfc1508d (kx 2023-03-24 03:55:33 +0300 607)         _("%u.%2.2u GiB/s"),
bfc1508d (kx 2023-03-24 03:55:33 +0300 608)         (unsigned)(bytes >> 30),
bfc1508d (kx 2023-03-24 03:55:33 +0300 609)         (unsigned)(bytes & ((1 << 30) - 1)) / 10737419 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 610)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 611)   else if( bytes > 1 << 20 )
bfc1508d (kx 2023-03-24 03:55:33 +0300 612)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 613)     unsigned x = bytes + 5243;  /* for rounding */
bfc1508d (kx 2023-03-24 03:55:33 +0300 614)     strbuf_addf( sb,
bfc1508d (kx 2023-03-24 03:55:33 +0300 615)       humanise_rate == 0 ?
bfc1508d (kx 2023-03-24 03:55:33 +0300 616)         /* TRANSLATORS: IEC 80000-13:2008 mebibyte */
bfc1508d (kx 2023-03-24 03:55:33 +0300 617)         _("%u.%2.2u MiB") :
bfc1508d (kx 2023-03-24 03:55:33 +0300 618)         /* TRANSLATORS: IEC 80000-13:2008 mebibyte/second */
bfc1508d (kx 2023-03-24 03:55:33 +0300 619)         _("%u.%2.2u MiB/s"),
bfc1508d (kx 2023-03-24 03:55:33 +0300 620)         x >> 20, ((x & ((1 << 20) - 1)) * 100) >> 20 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 621)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 622)   else if( bytes > 1 << 10 )
bfc1508d (kx 2023-03-24 03:55:33 +0300 623)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 624)     unsigned x = bytes + 5;  /* for rounding */
bfc1508d (kx 2023-03-24 03:55:33 +0300 625)     strbuf_addf( sb,
bfc1508d (kx 2023-03-24 03:55:33 +0300 626)       humanise_rate == 0 ?
bfc1508d (kx 2023-03-24 03:55:33 +0300 627)         /* TRANSLATORS: IEC 80000-13:2008 kibibyte */
bfc1508d (kx 2023-03-24 03:55:33 +0300 628)         _("%u.%2.2u KiB") :
bfc1508d (kx 2023-03-24 03:55:33 +0300 629)         /* TRANSLATORS: IEC 80000-13:2008 kibibyte/second */
bfc1508d (kx 2023-03-24 03:55:33 +0300 630)         _("%u.%2.2u KiB/s"),
bfc1508d (kx 2023-03-24 03:55:33 +0300 631)         x >> 10, ((x & ((1 << 10) - 1)) * 100) >> 10 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 632)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 633)   else
bfc1508d (kx 2023-03-24 03:55:33 +0300 634)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 635)     strbuf_addf( sb,
bfc1508d (kx 2023-03-24 03:55:33 +0300 636)       humanise_rate == 0 ?
bfc1508d (kx 2023-03-24 03:55:33 +0300 637)         /* TRANSLATORS: IEC 80000-13:2008 byte */
bfc1508d (kx 2023-03-24 03:55:33 +0300 638)         Q_("%u byte", "%u bytes", (unsigned)bytes) :
bfc1508d (kx 2023-03-24 03:55:33 +0300 639)         /* TRANSLATORS: IEC 80000-13:2008 byte/second */
bfc1508d (kx 2023-03-24 03:55:33 +0300 640)         Q_("%u byte/s", "%u bytes/s", (unsigned)bytes),
bfc1508d (kx 2023-03-24 03:55:33 +0300 641)       (unsigned)bytes );
bfc1508d (kx 2023-03-24 03:55:33 +0300 642)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 643) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 644) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 645) void strbuf_humanise_bytes( struct strbuf *sb, off_t bytes )
bfc1508d (kx 2023-03-24 03:55:33 +0300 646) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 647)   strbuf_humanise( sb, bytes, 0 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 648) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 649) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 650) void strbuf_humanise_rate( struct strbuf *sb, off_t bytes )
bfc1508d (kx 2023-03-24 03:55:33 +0300 651) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 652)   strbuf_humanise( sb, bytes, 1 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 653) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 654) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 655) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 656) int is_directory( const char *path )
bfc1508d (kx 2023-03-24 03:55:33 +0300 657) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 658)   struct stat st;
bfc1508d (kx 2023-03-24 03:55:33 +0300 659)   return ( !stat( path, &st ) && S_ISDIR(st.st_mode) );
bfc1508d (kx 2023-03-24 03:55:33 +0300 660) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 661) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 662) void strbuf_selfdir( struct strbuf *sb )
bfc1508d (kx 2023-03-24 03:55:33 +0300 663) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 664)   char    path[PATH_MAX];
bfc1508d (kx 2023-03-24 03:55:33 +0300 665)   ssize_t len;
bfc1508d (kx 2023-03-24 03:55:33 +0300 666) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 667)   bzero( (void *)path, PATH_MAX );
bfc1508d (kx 2023-03-24 03:55:33 +0300 668) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 669)   len = readlink( "/proc/self/exe", &path[0], (size_t)PATH_MAX );
bfc1508d (kx 2023-03-24 03:55:33 +0300 670)   if( len > 0 && len < PATH_MAX )
bfc1508d (kx 2023-03-24 03:55:33 +0300 671)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 672)     strbuf_addstr( sb, (const char *)dirname( (char *)&path[0] ) );
bfc1508d (kx 2023-03-24 03:55:33 +0300 673)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 674)   else
bfc1508d (kx 2023-03-24 03:55:33 +0300 675)     sb->fatal( "cannot get selfdir" );
bfc1508d (kx 2023-03-24 03:55:33 +0300 676) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 677) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 678) void strbuf_relpath( struct strbuf *sb, const char *path )
bfc1508d (kx 2023-03-24 03:55:33 +0300 679) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 680)   struct strbuf self = STRBUF_INIT;
bfc1508d (kx 2023-03-24 03:55:33 +0300 681)   char   p[PATH_MAX];
bfc1508d (kx 2023-03-24 03:55:33 +0300 682) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 683)   bzero( (void *)p, PATH_MAX );
bfc1508d (kx 2023-03-24 03:55:33 +0300 684) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 685)   if( realpath( path, (char *)&p[0] ) == NULL )
bfc1508d (kx 2023-03-24 03:55:33 +0300 686)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 687)     sb->fatal( "cannot get relative path of '%s'", path );
bfc1508d (kx 2023-03-24 03:55:33 +0300 688)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 689) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 690)   strbuf_init( &self, sb->fatal, 0 );
bfc1508d (kx 2023-03-24 03:55:33 +0300 691)   strbuf_selfdir( &self );
bfc1508d (kx 2023-03-24 03:55:33 +0300 692) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 693)   strbuf_addstr( sb, (const char *)&p[self.len] );
bfc1508d (kx 2023-03-24 03:55:33 +0300 694) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 695)   strbuf_release( &self );
bfc1508d (kx 2023-03-24 03:55:33 +0300 696) }
bfc1508d (kx 2023-03-24 03:55:33 +0300 697) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 698) void strbuf_abspath( struct strbuf *sb, const char *path )
bfc1508d (kx 2023-03-24 03:55:33 +0300 699) {
bfc1508d (kx 2023-03-24 03:55:33 +0300 700)   char p[PATH_MAX];
bfc1508d (kx 2023-03-24 03:55:33 +0300 701) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 702)   if( realpath( path, (char *)&p[0] ) == NULL )
bfc1508d (kx 2023-03-24 03:55:33 +0300 703)   {
bfc1508d (kx 2023-03-24 03:55:33 +0300 704)     sb->fatal( "cannot get absolute path of '%s'", path );
bfc1508d (kx 2023-03-24 03:55:33 +0300 705)   }
bfc1508d (kx 2023-03-24 03:55:33 +0300 706) 
bfc1508d (kx 2023-03-24 03:55:33 +0300 707)   strbuf_addstr( sb, (char *)&p[0] );
bfc1508d (kx 2023-03-24 03:55:33 +0300 708) }