add function normalize_path_ex and normalize_uri
parent
df4fdfcab7
commit
6fddce73c5
|
|
@ -54,6 +54,10 @@ src/tests/test_file_write_hole
|
||||||
src/tests/test_file_lock
|
src/tests/test_file_lock
|
||||||
src/tests/test_thread_pool
|
src/tests/test_thread_pool
|
||||||
src/tests/test_data_visible
|
src/tests/test_data_visible
|
||||||
|
src/tests/test_pthread_wait
|
||||||
|
src/tests/test_mutex_lock_perf
|
||||||
|
src/tests/test_queue_perf
|
||||||
|
src/tests/test_normalize_path
|
||||||
|
|
||||||
# other
|
# other
|
||||||
*.swp
|
*.swp
|
||||||
|
|
|
||||||
3
HISTORY
3
HISTORY
|
|
@ -1,7 +1,8 @@
|
||||||
|
|
||||||
Version 1.51 2021-05-20
|
Version 1.51 2021-05-25
|
||||||
* fast_mblock.[hc]: support batch alloc and batch free
|
* fast_mblock.[hc]: support batch alloc and batch free
|
||||||
* uniq_skiplist.[hc]: init function add parameter: allocator_use_lock
|
* uniq_skiplist.[hc]: init function add parameter: allocator_use_lock
|
||||||
|
* add function normalize_path_ex and normalize_uri
|
||||||
|
|
||||||
Version 1.50 2021-05-11
|
Version 1.50 2021-05-11
|
||||||
* add function is_digital_string
|
* add function is_digital_string
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
%define CommitVersion %(echo $COMMIT_VERSION)
|
%define CommitVersion %(echo $COMMIT_VERSION)
|
||||||
|
|
||||||
Name: libfastcommon
|
Name: libfastcommon
|
||||||
Version: 1.0.50
|
Version: 1.0.51
|
||||||
Release: 1%{?dist}
|
Release: 1%{?dist}
|
||||||
Summary: c common functions library extracted from my open source projects FastDFS
|
Summary: c common functions library extracted from my open source projects FastDFS
|
||||||
License: LGPL
|
License: LGPL
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,10 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include "common_define.h"
|
#include "common_define.h"
|
||||||
|
|
||||||
|
#define IS_URL_RESOURCE(str) \
|
||||||
|
((strncasecmp(str, "http://", 7) == 0) || \
|
||||||
|
(strncasecmp(str, "https://", 8) == 0))
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "sockopt.h"
|
#include "sockopt.h"
|
||||||
#include "fc_memory.h"
|
#include "fc_memory.h"
|
||||||
|
#include "http_func.h"
|
||||||
#include "shared_func.h"
|
#include "shared_func.h"
|
||||||
|
|
||||||
#ifdef OS_LINUX
|
#ifdef OS_LINUX
|
||||||
|
|
@ -2989,28 +2990,156 @@ char *format_http_date(time_t t, BufferInfo *buffer)
|
||||||
return buffer->buff;
|
return buffer->buff;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *resolve_path(const char *from, const char *filename,
|
int normalize_path(const char *from, const char *filename,
|
||||||
char *full_filename, const int size)
|
char *full_filename, const int size)
|
||||||
{
|
{
|
||||||
const char *last;
|
const char *last;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
if (*filename == '/') {
|
if (*filename == '/') {
|
||||||
snprintf(full_filename, size, "%s", filename);
|
return snprintf(full_filename, size, "%s", filename);
|
||||||
return full_filename;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
last = strrchr(from, '/');
|
last = strrchr(from, '/');
|
||||||
if (last != NULL) {
|
if (last != NULL) {
|
||||||
len = last - from;
|
len = last - from;
|
||||||
snprintf(full_filename, size, "%.*s/%s", len, from, filename);
|
return snprintf(full_filename, size, "%.*s/%s", len, from, filename);
|
||||||
} else {
|
} else {
|
||||||
logWarning("file: "__FILE__", line: %d, "
|
logWarning("file: "__FILE__", line: %d, "
|
||||||
"no \"/\" in the from filename: %s",
|
"no \"/\" in the from filename: %s",
|
||||||
__LINE__, from);
|
__LINE__, from);
|
||||||
snprintf(full_filename, size, "%s", filename);
|
return snprintf(full_filename, size, "%s", filename);
|
||||||
}
|
}
|
||||||
return full_filename;
|
}
|
||||||
|
|
||||||
|
int normalize_uri(const string_t *from, const char *uri,
|
||||||
|
char *dest, const int size)
|
||||||
|
{
|
||||||
|
#define MAX_UP_PATH_COUNT 8
|
||||||
|
const char *start;
|
||||||
|
const char *end;
|
||||||
|
const char *last;
|
||||||
|
string_t fpath;
|
||||||
|
string_t parts[MAX_UP_PATH_COUNT];
|
||||||
|
int up_count;
|
||||||
|
int path_count;
|
||||||
|
int keep_count;
|
||||||
|
int len;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (*uri == '/') {
|
||||||
|
return snprintf(dest, size, "%s", uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
end = uri + strlen(uri);
|
||||||
|
up_count = 0;
|
||||||
|
start = uri;
|
||||||
|
while (start + 3 < end) {
|
||||||
|
if (memcmp(start, "../", 3) != 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
++up_count;
|
||||||
|
start += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
last = fc_memrchr(from->str, '/', from->len);
|
||||||
|
if (last == NULL) {
|
||||||
|
logWarning("file: "__FILE__", line: %d, "
|
||||||
|
"no \"/\" in the from uri: %s",
|
||||||
|
__LINE__, from->str);
|
||||||
|
return snprintf(dest, size, "/%s", start);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (up_count == 0) {
|
||||||
|
return snprintf(dest, size, "%.*s/%s",
|
||||||
|
(int)(last - from->str), from->str, uri);
|
||||||
|
} else {
|
||||||
|
fpath.str = (char *)from->str;
|
||||||
|
fpath.len = last - from->str;
|
||||||
|
path_count = split_string_ex(&fpath, '/',
|
||||||
|
parts, MAX_UP_PATH_COUNT, true);
|
||||||
|
keep_count = path_count - up_count;
|
||||||
|
if (keep_count < 0) {
|
||||||
|
logWarning("file: "__FILE__", line: %d, "
|
||||||
|
"uri: %s, contails too many \"../\"",
|
||||||
|
__LINE__, uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
for (i=0; i<keep_count; i++) {
|
||||||
|
len += snprintf(dest + len, size - len,
|
||||||
|
"/%.*s", parts[i].len, parts[i].str);
|
||||||
|
}
|
||||||
|
|
||||||
|
len += snprintf(dest + len, size - len, "/%s", start);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int normalize_path_ex(const char *from, const char *filename,
|
||||||
|
char *full_filename, const int size, const int flags)
|
||||||
|
{
|
||||||
|
bool is_url_from;
|
||||||
|
bool is_url_filename;
|
||||||
|
const char *base_end;
|
||||||
|
const char *from_ask;
|
||||||
|
const char *dest_ask;
|
||||||
|
string_t from_uri;
|
||||||
|
int base_len;
|
||||||
|
int full_len;
|
||||||
|
|
||||||
|
if ((flags & NORMALIZE_FLAGS_URL_ENABLED) == 0) {
|
||||||
|
return normalize_path(from, filename, full_filename, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
is_url_from = IS_URL_RESOURCE(from);
|
||||||
|
is_url_filename = IS_URL_RESOURCE(filename);
|
||||||
|
if (!(is_url_from || is_url_filename)) {
|
||||||
|
return normalize_path(from, filename, full_filename, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_url_from) {
|
||||||
|
return snprintf(full_filename, size, "%s", filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_url_filename) {
|
||||||
|
full_len = snprintf(full_filename, size, "%s", filename);
|
||||||
|
if ((flags & NORMALIZE_FLAGS_URL_APPEND_PARAMS) == 0) {
|
||||||
|
return full_len;
|
||||||
|
}
|
||||||
|
from_ask = strchr(from + 8, '?');
|
||||||
|
} else {
|
||||||
|
base_end = strchr(from + 8, '/');
|
||||||
|
if (base_end == NULL) {
|
||||||
|
return snprintf(full_filename, size, "%s%s%s",
|
||||||
|
from, (*filename == '/' ? "" : "/"), filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
base_len = base_end - from;
|
||||||
|
from_ask = strchr(base_end + 1, '?');
|
||||||
|
from_uri.str = (char *)base_end;
|
||||||
|
if (from_ask == NULL) {
|
||||||
|
from_uri.len = strlen(from_uri.str);
|
||||||
|
} else {
|
||||||
|
from_uri.len = from_ask - from_uri.str;
|
||||||
|
}
|
||||||
|
|
||||||
|
full_len = snprintf(full_filename, size, "%.*s", base_len, from);
|
||||||
|
full_len = normalize_uri(&from_uri, filename,
|
||||||
|
full_filename + full_len, size - full_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & NORMALIZE_FLAGS_URL_APPEND_PARAMS) != 0) {
|
||||||
|
if (from_ask != NULL) {
|
||||||
|
dest_ask = strchr(filename, '?');
|
||||||
|
full_len += snprintf(full_filename + full_len,
|
||||||
|
size - full_len, "%c%s", (dest_ask == NULL ?
|
||||||
|
'?' : '&'), from_ask + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return full_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *get_gzip_command_filename()
|
const char *get_gzip_command_filename()
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,16 @@
|
||||||
#include "common_define.h"
|
#include "common_define.h"
|
||||||
#include "ini_file_reader.h"
|
#include "ini_file_reader.h"
|
||||||
|
|
||||||
|
#define NORMALIZE_FLAGS_URL_ENABLED 1
|
||||||
|
#define NORMALIZE_FLAGS_URL_APPEND_PARAMS 2
|
||||||
|
|
||||||
|
#define NORMALIZE_FLAGS_URL_ENABLED_AND_APPEND_PARAMS \
|
||||||
|
(NORMALIZE_FLAGS_URL_ENABLED | NORMALIZE_FLAGS_URL_APPEND_PARAMS)
|
||||||
|
|
||||||
|
#define resolve_path(from, filename, full_filename, size) \
|
||||||
|
normalize_path_ex(from, filename, full_filename, size, \
|
||||||
|
NORMALIZE_FLAGS_URL_ENABLED_AND_APPEND_PARAMS)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -933,11 +943,37 @@ char *format_http_date(time_t t, BufferInfo *buffer);
|
||||||
* filename: the filename to resolve path
|
* filename: the filename to resolve path
|
||||||
* full_filename: store the resolved full path filename
|
* full_filename: store the resolved full path filename
|
||||||
* size: the max size of full_filename
|
* size: the max size of full_filename
|
||||||
* return: the resolved full path filename
|
* return: length of the resolved full path
|
||||||
*/
|
*/
|
||||||
char *resolve_path(const char *from, const char *filename,
|
int normalize_path(const char *from, const char *filename,
|
||||||
char *full_filename, const int size);
|
char *full_filename, const int size);
|
||||||
|
|
||||||
|
/** return absolute uri (the second parameter)
|
||||||
|
* parameters:
|
||||||
|
* from: the input uri to get base path
|
||||||
|
* uri: the uri to resolve
|
||||||
|
* dest: store the resolved absolute uri
|
||||||
|
* size: the max size of dest
|
||||||
|
* return: length of the resolved uri
|
||||||
|
*/
|
||||||
|
int normalize_uri(const string_t *from, const char *uri,
|
||||||
|
char *dest, const int size);
|
||||||
|
|
||||||
|
/** return full path for the filename (the second parameter)
|
||||||
|
* parameters:
|
||||||
|
* from: the input full path filename to get base path
|
||||||
|
* filename: the filename to resolve path
|
||||||
|
* full_filename: store the resolved full path filename
|
||||||
|
* size: the max size of full_filename
|
||||||
|
* flags:
|
||||||
|
* NORMALIZE_FLAGS_URL_ENABLED: support url resolve
|
||||||
|
* NORMALIZE_FLAGS_URL_APPEND_PARAMS: append params of from
|
||||||
|
* return: length of the resolved full path
|
||||||
|
*/
|
||||||
|
int normalize_path_ex(const char *from, const char *filename,
|
||||||
|
char *full_filename, const int size, const int flags);
|
||||||
|
|
||||||
|
|
||||||
/** get gzip command full filename
|
/** get gzip command full filename
|
||||||
* return: the gzip command full filename
|
* return: the gzip command full filename
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,8 @@ ALL_PRGS = test_allocator test_skiplist test_multi_skiplist test_mblock test_blo
|
||||||
test_logger test_skiplist_set test_crc32 test_thourands_seperator test_sched_thread \
|
test_logger test_skiplist_set test_crc32 test_thourands_seperator test_sched_thread \
|
||||||
test_json_parser test_pthread_lock test_uniq_skiplist test_split_string \
|
test_json_parser test_pthread_lock test_uniq_skiplist test_split_string \
|
||||||
test_server_id_func test_pipe test_atomic test_file_write_hole test_file_lock \
|
test_server_id_func test_pipe test_atomic test_file_write_hole test_file_lock \
|
||||||
test_thread_pool test_data_visible test_mutex_lock_perf test_queue_perf
|
test_pthread_wait test_thread_pool test_data_visible test_mutex_lock_perf \
|
||||||
|
test_queue_perf test_normalize_path
|
||||||
|
|
||||||
all: $(ALL_PRGS)
|
all: $(ALL_PRGS)
|
||||||
.c:
|
.c:
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 YuQing <384681@qq.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can use, redistribute, and/or modify
|
||||||
|
* it under the terms of the Lesser GNU General Public License, version 3
|
||||||
|
* or later ("LGPL"), as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the Lesser GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include "fastcommon/logger.h"
|
||||||
|
#include "fastcommon/shared_func.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char full_filename[PATH_MAX];
|
||||||
|
const char *from;
|
||||||
|
const char *filename;
|
||||||
|
|
||||||
|
if (argc < 3) {
|
||||||
|
fprintf(stderr, "Usage: %s <base> <filename>\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_init();
|
||||||
|
from = argv[1];
|
||||||
|
filename = argv[2];
|
||||||
|
normalize_path_ex(from, filename, full_filename, sizeof(full_filename),
|
||||||
|
NORMALIZE_FLAGS_URL_ENABLED_AND_APPEND_PARAMS);
|
||||||
|
printf("%s\n", full_filename);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,134 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 YuQing <384681@qq.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can use, redistribute, and/or modify
|
||||||
|
* it under the terms of the Lesser GNU General Public License, version 3
|
||||||
|
* or later ("LGPL"), as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the Lesser GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include "fastcommon/logger.h"
|
||||||
|
#include "fastcommon/shared_func.h"
|
||||||
|
#include "fastcommon/pthread_func.h"
|
||||||
|
|
||||||
|
static bool continue_flag = true;
|
||||||
|
static pthread_lock_cond_pair_t lcp;
|
||||||
|
|
||||||
|
static void *thread_func(void *arg)
|
||||||
|
{
|
||||||
|
printf("file: "__FILE__", line: %d, "
|
||||||
|
"thread enter ...\n", __LINE__);
|
||||||
|
|
||||||
|
PTHREAD_MUTEX_LOCK(&lcp.lock);
|
||||||
|
pthread_cond_wait(&lcp.cond, &lcp.lock);
|
||||||
|
PTHREAD_MUTEX_UNLOCK(&lcp.lock);
|
||||||
|
|
||||||
|
printf("file: "__FILE__", line: %d, "
|
||||||
|
"thread done! \n", __LINE__);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sigQuitHandler(int sig)
|
||||||
|
{
|
||||||
|
if (continue_flag) {
|
||||||
|
continue_flag = false;
|
||||||
|
printf("file: "__FILE__", line: %d, "
|
||||||
|
"catch signal %d, program exiting...\n",
|
||||||
|
__LINE__, sig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sigHupHandler(int sig)
|
||||||
|
{
|
||||||
|
printf("file: "__FILE__", line: %d, "
|
||||||
|
"catch signal %d\n", __LINE__, sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int setup_signal_handler()
|
||||||
|
{
|
||||||
|
struct sigaction act;
|
||||||
|
memset(&act, 0, sizeof(act));
|
||||||
|
sigemptyset(&act.sa_mask);
|
||||||
|
|
||||||
|
signal(SIGHUP, sigHupHandler);
|
||||||
|
|
||||||
|
/*
|
||||||
|
act.sa_handler = sigHupHandler;
|
||||||
|
if(sigaction(SIGHUP, &act, NULL) < 0) {
|
||||||
|
fprintf(stderr, "file: "__FILE__", line: %d, "
|
||||||
|
"call sigaction fail, errno: %d, error info: %s\n",
|
||||||
|
__LINE__, errno, strerror(errno));
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
act.sa_handler = sigQuitHandler;
|
||||||
|
if(sigaction(SIGINT, &act, NULL) < 0 ||
|
||||||
|
sigaction(SIGTERM, &act, NULL) < 0 ||
|
||||||
|
sigaction(SIGQUIT, &act, NULL) < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "file: "__FILE__", line: %d, "
|
||||||
|
"call sigaction fail, errno: %d, error info: %s\n",
|
||||||
|
__LINE__, errno, strerror(errno));
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
int i;
|
||||||
|
pthread_t tid;
|
||||||
|
|
||||||
|
log_init();
|
||||||
|
|
||||||
|
if ((result=setup_signal_handler()) != 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if ((result=init_pthread_lock_cond_pair(&lcp)) != 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((result=pthread_create(&tid, NULL, thread_func, NULL)) != 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (continue_flag) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
printf("file: "__FILE__", line: %d, "
|
||||||
|
"loop before ...\n", __LINE__);
|
||||||
|
PTHREAD_MUTEX_LOCK(&lcp.lock);
|
||||||
|
pthread_cond_wait(&lcp.cond, &lcp.lock);
|
||||||
|
PTHREAD_MUTEX_UNLOCK(&lcp.lock);
|
||||||
|
|
||||||
|
printf("file: "__FILE__", line: %d, "
|
||||||
|
"loop after\n", __LINE__);
|
||||||
|
*/
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//pthread_cond_signal(&lcp.cond);
|
||||||
|
for (i=0; i<3; i++) {
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("file: "__FILE__", line: %d, "
|
||||||
|
"program exit.\n", __LINE__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue