123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- /*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * Author: g0tsu
- * Email: g0tsu at dnmx.0rg
- */
- #include <global.h>
- #include <libcaptcha.h>
- #include <stdint.h>
- #include <string.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/syscall.h>
- #include <errno.h>
- #include <assert.h>
- int lc_random_bytes(void *bytes, size_t size) {
- size_t read_bytes = 0;
- ssize_t n;
- /* Linux getrandom(2) syscall or FreeBSD getrandom(2) function*/
- /* Keep reading until we get enough entropy */
- while (read_bytes < size) {
- /* Below, (bytes + read_bytes) is pointer arithmetic.
- bytes read_bytes size
- | | |
- [#######=============] (we're going to write over the = region)
- \\\\\\\\\\\\\
- amount_to_read
- */
- size_t amount_to_read = size - read_bytes;
- n = syscall(SYS_getrandom, bytes + read_bytes, amount_to_read, 0);
- if (n == -1) {
- if (errno == ENOSYS) {
- /* This can happen if PHP was compiled against a newer kernel where getrandom()
- * is available, but then runs on an older kernel without getrandom(). If this
- * happens we simply fall back to reading from /dev/urandom. */
- assert(read_bytes == 0);
- break;
- } else if (errno == EINTR || errno == EAGAIN) {
- /* Try again */
- continue;
- } else {
- /* If the syscall fails, fall back to reading from /dev/urandom */
- break;
- }
- }
- read_bytes += (size_t) n;
- }
- if (read_bytes < size) {
- int fd;
- struct stat st;
- if (fd < 0) {
- #if HAVE_DEV_URANDOM
- fd = open("/dev/urandom", O_RDONLY);
- #else
- fd = open("/dev/random", O_RDONLY);
- #endif
- if (fd < 0) {
- return 1;
- }
- /* Does the file exist and is it a character device? */
- if (fstat(fd, &st) != 0 ||
- # ifdef S_ISNAM
- !(S_ISNAM(st.st_mode) || S_ISCHR(st.st_mode))
- # else
- !S_ISCHR(st.st_mode)
- # endif
- ) {
- close(fd);
- return 1;
- }
- }
- for (read_bytes = 0; read_bytes < size; read_bytes += (size_t) n) {
- n = read(fd, bytes + read_bytes, size - read_bytes);
- if (n <= 0) {
- break;
- }
- }
- if (read_bytes < size) {
- return 1;
- }
- }
- return 0;
- }
- const char lc_cval[16] = "0123456789abcdef";
- static int lc_val_pos(const char c) {
- for (int i = 0; i < 16; i++) {
- if (lc_cval[i] == c)
- return i;
- }
- return 0;
- }
- lc_rgb *lc_rgb_from_text(const char *str) {
- char *cp = (char *)str;
- char c;
- lc_rgb *rgb;
- if (strlen(str) < 7)
- return NULL;
- cp++; // skip #
- rgb = (lc_rgb *)malloc(sizeof(*rgb));
- for (int i = 0; i < 6; i++, cp++) {
- c = tolower(*cp);
- switch (i) {
- case 0:
- rgb->r = lc_val_pos(c) * 16;
- break;
- case 1:
- rgb->r += lc_val_pos(c);
- case 2:
- rgb->g = lc_val_pos(c) * 16;
- break;
- case 3:
- rgb->g += lc_val_pos(c);
- case 4:
- rgb->b = lc_val_pos(c) * 16;
- break;
- case 5:
- rgb->b += lc_val_pos(c);
- default:
- break;
- }
- }
- return rgb;
- }
|