add function normalize_path_ex and normalize_uri

iovec_array
YuQing 2021-05-25 16:41:11 +08:00
parent df4fdfcab7
commit 6fddce73c5
9 changed files with 365 additions and 12 deletions

4
.gitignore vendored
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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
*/ */

View File

@ -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:

View File

@ -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;
}

View File

@ -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;
}