Subversion Repositories RepoView

Rev

Rev 15 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

/* $Id: util.c 29 2024-08-21 19:23:54Z nishi $ */

#include "rv_util.h"

#include "../config.h"

#include "rv_version.h"
#include "rv_db.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>

char* rv_strcat(const char* a, const char* b) {
        char* str = malloc(strlen(a) + strlen(b) + 1);
        memcpy(str, a, strlen(a));
        memcpy(str + strlen(a), b, strlen(b));
        str[strlen(a) + strlen(b)] = 0;
        return str;
}

char* rv_strcat3(const char* a, const char* b, const char* c) {
        char* tmp = rv_strcat(a, b);
        char* str = rv_strcat(tmp, c);
        free(tmp);
        return str;
}

char* rv_strdup(const char* str) { return rv_strcat(str, ""); }

void rv_error_http(void) {
        printf("Content-Type: text/plain\r\n");
        printf("Status: 500 Internal Server Error\r\n");
        printf("\r\n");
        printf("This is RepoView version %s, named `%s`.\n", rv_get_version(), INSTANCE_NAME);
        printf("Unrecoverable error has occured.\n");
        printf("Admin contact: %s\n", INSTANCE_ADMIN);
        printf("Developer contact: Nishi <nishi@nishi.boats>\n");
        printf("-----\n");
}

int hex_to_num(char c) {
        if('0' <= c && c <= '9') {
                return c - '0';
        } else if('a' <= c && c <= 'f') {
                return c - 'a' + 10;
        } else if('A' <= c && c <= 'F') {
                return c - 'A' + 10;
        }
        return 0;
}

char* rv_url_decode(const char* str) {
        char* r = malloc(1);
        r[0] = 0;
        int i;
        char cbuf[2];
        cbuf[1] = 0;
        for(i = 0; str[i] != 0; i++) {
                if(str[i] == '%') {
                        if(str[i + 1] == 0) break;
                        if(str[i + 2] == 0) break;
                        cbuf[0] = (hex_to_num(str[i + 1]) << 4) | hex_to_num(str[i + 2]);
                        char* tmp = r;
                        r = rv_strcat(tmp, cbuf);
                        free(tmp);
                        i += 2;
                } else if(str[i] == '+') {
                        char* tmp = r;
                        r = rv_strcat(tmp, " ");
                        free(tmp);
                } else {
                        cbuf[0] = str[i];
                        char* tmp = r;
                        r = rv_strcat(tmp, cbuf);
                        free(tmp);
                }
        }
        return r;
}

char* rv_new_token(const char* username) {
        const char tokenstr[] = "0123456789abcdefghijklmnopqrstuvwxyz";
        char* token = malloc(17);
        token[16] = 0;
        int i;
        unsigned char uc;
        FILE* f = fopen("/dev/urandom", "rb");
regenerate:
        for(i = 0; i < 16; i++) {
                fread(&uc, 1, 1, f);
                token[i] = tokenstr[uc % strlen(tokenstr)];
        }
        fclose(f);
        if(rv_has_token(token)) goto regenerate;
        rv_save_token(username, token);
        return token;
}

void rv_add_auth(const char* username, const char* password) {
        pid_t pid = fork();
        if(pid == 0) {
                char* cmd[] = {"htpasswd", "-b", APACHE_PASSWD, (char*)username, (char*)password, NULL};
                execvp("htpasswd", cmd);
                _exit(0);
        } else {
                waitpid(pid, 0, 0);
        }
}