/** * @brief Select a random truetype font from the directory specified in magma.http.fonts. * @return NULL on failure, or a managed string containing the pathname of the randomly selected font file on success. */ stringer_t * register_captcha_random_font(void) { DIR *directory; stringer_t *path; struct dirent64 *dp; size_t count = 0, selection; // Open the current working directory. if (!(directory = opendir(magma.http.fonts))) { log_pedantic("Unable to open the font directory. { directory = %s }", magma.http.fonts); return NULL; } // Count the number of fonts. while ((dp = readdir64(directory))) { if (!st_cmp_ci_ends(NULLER(dp->d_name), PLACER(".ttf", 4))) { count++; } }; // No fonts were found. if (!count) { log_pedantic("The web fonts directory is empty. { directory = %s }", magma.http.fonts); closedir(directory); return NULL; } // Pick a random font. selection = (rand_get_uint32() % count) + 1; // Reset the directory stream. rewinddir(directory); // Do the loop again. while (selection && (dp = readdir64(directory))) { if (!st_cmp_ci_ends(NULLER(dp->d_name), PLACER(".ttf", 4))) { selection--; } } // Build the path. if (selection || !dp || !(path = st_aprint("%s/%s", magma.http.fonts, dp->d_name))) { log_pedantic("Could not build the font file path."); closedir(directory); return NULL; } closedir(directory); return path; }
/** * @brief Increment the serial number for an object in memcached. * @param type the serial type to be queried (OBJECT_USER, OBJECT_CONFIG, OBJECT_FOLDERS, OBJECT_MESSAGES, or OBJECT_CONTACTS). * @param num the specific object identifier. * @return 0 on failure or the new serial number of the requested object. */ uint64_t serial_increment(uint64_t type, uint64_t num) { uint64_t result = 0; stringer_t *key, *prefix; // Build retrieval key. if (!(prefix = serial_prefix(type)) || !(key = st_aprint("magma.%.*s.%lu", st_length_int(prefix), st_char_get(prefix), num))) { log_pedantic("Unable to build %.*s serial key.", st_length_int(prefix), st_char_get(prefix)); return 0; } // Increment the key. result = cache_increment(key, 1, 1, 2592000); st_free(key); return result; }
/** * @brief Get the serial number (checkpoint value) for an object from memcached. * @param type the serial type to be queried (OBJECT_USER, OBJECT_CONFIG, OBJECT_FOLDERS, OBJECT_MESSAGES, or OBJECT_CONTACTS). * @param num the specific object identifier. * @return 0 on failure or the serial number of the requested object. */ uint64_t serial_get(uint64_t type, uint64_t num) { uint64_t result = 0; stringer_t *key, *prefix; // Build retrieval key. // QUESTION: This is used a few times and definitely should be its own function. if (!(prefix = serial_prefix(type)) || !(key = st_aprint("magma.%.*s.%lu", st_length_int(prefix), st_char_get(prefix), num))) { log_pedantic("Unable to build %.*s serial key.", st_length_int(prefix), st_char_get(prefix)); return 0; } // Get the key value. The increment functions store the value in binary form, so we must use them to access the value, even if we aren't incrementing the value. result = cache_increment(key, 0, 0, 2592000); st_free(key); return result; }
/** * @brief Reset the serial number to 1 for an object in memcached. * @param type the serial type to be queried (OBJECT_USER, OBJECT_CONFIG, OBJECT_FOLDERS, OBJECT_MESSAGES, or OBJECT_CONTACTS). * @param num the specific object identifier. * @return 0 on failure or the new value of the cached serial number (1) on success. */ uint64_t serial_reset(uint64_t type, uint64_t num) { uint64_t result = 0; stringer_t *key, *prefix; // Build key. if (!(prefix = serial_prefix(type)) || !(key = st_aprint("magma.%.*s.%lu", st_length_int(prefix), st_char_get(prefix), num))) { log_pedantic("Unable to build %.*s serial key.", st_length_int(prefix), st_char_get(prefix)); return 0; } // If were able to set the key, return the value one. if (cache_set(key, CONSTANT("1"), 2592000) == 1) { result = 1; } st_free(key); return result; }