diff options
author | kcwu <kcwu@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2007-12-12 09:42:23 +0800 |
---|---|---|
committer | kcwu <kcwu@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2007-12-12 09:42:23 +0800 |
commit | 9a12adf6d29cdefc98afe2566a9e5479489f111b (patch) | |
tree | 6e2b911398cb6dcb08b183ab645817e098182968 /src | |
parent | 3d16ea67c380607528e7c8df0b2cc5a2f2636b9f (diff) | |
download | pttbbs-9a12adf6d29cdefc98afe2566a9e5479489f111b.tar pttbbs-9a12adf6d29cdefc98afe2566a9e5479489f111b.tar.gz pttbbs-9a12adf6d29cdefc98afe2566a9e5479489f111b.tar.bz2 pttbbs-9a12adf6d29cdefc98afe2566a9e5479489f111b.tar.lz pttbbs-9a12adf6d29cdefc98afe2566a9e5479489f111b.tar.xz pttbbs-9a12adf6d29cdefc98afe2566a9e5479489f111b.tar.zst pttbbs-9a12adf6d29cdefc98afe2566a9e5479489f111b.zip |
* extract common functions as library.
git-svn-id: http://opensvn.csie.org/pttbbs/trunk/pttbbs@3673 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
Diffstat (limited to 'src')
-rw-r--r-- | src/libbbs/Makefile | 20 | ||||
-rw-r--r-- | src/libbbs/log.c | 0 | ||||
-rw-r--r-- | src/libbbs/money.c | 37 | ||||
-rw-r--r-- | src/libbbs/string.c | 1 | ||||
-rw-r--r-- | src/libbbsutil/Makefile | 20 | ||||
-rw-r--r-- | src/libbbsutil/file.c | 276 | ||||
-rw-r--r-- | src/libbbsutil/lock.c | 23 | ||||
-rw-r--r-- | src/libbbsutil/log.c | 43 | ||||
-rw-r--r-- | src/libbbsutil/net.c | 114 | ||||
-rw-r--r-- | src/libbbsutil/sort.c | 10 | ||||
-rw-r--r-- | src/libbbsutil/string.c | 284 | ||||
-rw-r--r-- | src/libbbsutil/time.c | 116 |
12 files changed, 944 insertions, 0 deletions
diff --git a/src/libbbs/Makefile b/src/libbbs/Makefile new file mode 100644 index 00000000..efbf9534 --- /dev/null +++ b/src/libbbs/Makefile @@ -0,0 +1,20 @@ + +SRCROOT= ../.. +.include "$(SRCROOT)/pttbbs.mk" + +CFLAGS+= -I$(SRCROOT)/include + +OBJS= log.o string.o money.o +TARGET= libbbs.a + + +.SUFFIXES: .c .o +.c.o: + $(CCACHE) $(DIETCC) $(CC) $(CFLAGS) -c $*.c + +$(TARGET): $(OBJS) + $(AR) cru $@ $(OBJS) + ranlib $@ + +clean: + rm -f $(OBJS) $(TARGET) diff --git a/src/libbbs/log.c b/src/libbbs/log.c new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/src/libbbs/log.c diff --git a/src/libbbs/money.c b/src/libbbs/money.c new file mode 100644 index 00000000..a6d54127 --- /dev/null +++ b/src/libbbs/money.c @@ -0,0 +1,37 @@ +#include <stdio.h> + +#include <libbbs.h> + +/* 計算贈與稅 */ +int +give_tax(int money) +{ + int i, tax = 0; + int tax_bound[] = {1000000, 100000, 10000, 1000, 0}; + double tax_rate[] = {0.4, 0.3, 0.2, 0.1, 0.08}; + for (i = 0; i <= 4; i++) + if (money > tax_bound[i]) { + tax += (money - tax_bound[i]) * tax_rate[i]; + money -= (money - tax_bound[i]); + } + return (tax <= 0) ? 1 : tax; +} + +const char* +money_level(int money) +{ + int i = 0; + + static const char *money_msg[] = + { + "債台高築", "赤貧", "清寒", "普通", "小康", + "小富", "中富", "大富翁", "富可敵國", "比爾蓋\天", NULL + }; + while (money_msg[i] && money > 10) + i++, money /= 10; + + if(!money_msg[i]) + i--; + return money_msg[i]; +} + diff --git a/src/libbbs/string.c b/src/libbbs/string.c new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/src/libbbs/string.c @@ -0,0 +1 @@ + diff --git a/src/libbbsutil/Makefile b/src/libbbsutil/Makefile new file mode 100644 index 00000000..eafe2ab5 --- /dev/null +++ b/src/libbbsutil/Makefile @@ -0,0 +1,20 @@ + +SRCROOT= ../.. +.include "$(SRCROOT)/pttbbs.mk" + +CFLAGS+= -I$(SRCROOT)/include + +OBJS= file.o lock.o log.o net.o sort.o string.o time.o +TARGET= libbbsutil.a + + +.SUFFIXES: .c .o +.c.o: + $(CCACHE) $(DIETCC) $(CC) $(CFLAGS) -c $*.c + +$(TARGET): $(OBJS) + $(AR) cru $@ $(OBJS) + ranlib $@ + +clean: + rm -f $(OBJS) $(TARGET) diff --git a/src/libbbsutil/file.c b/src/libbbsutil/file.c new file mode 100644 index 00000000..c508e2de --- /dev/null +++ b/src/libbbsutil/file.c @@ -0,0 +1,276 @@ +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <limits.h> +#include <strings.h> +#include <dirent.h> +#include <string.h> +#include <sys/wait.h> + +#include "libbbsutil.h" + + +/* ----------------------------------------------------- */ +/* 檔案檢查函數:檔案、目錄、屬於 */ +/* ----------------------------------------------------- */ + +/** + * 傳回 fname 的檔案大小 + * @param fname + */ +off_t +dashs(const char *fname) +{ + struct stat st; + + if (!stat(fname, &st)) + return st.st_size; + else + return -1; +} + +/** + * 傳回 fname 的 mtime + * @param fname + */ +time4_t +dasht(const char *fname) +{ + struct stat st; + + if (!stat(fname, &st)) + return st.st_mtime; + else + return -1; +} + +/** + * 傳回 fname 是否為 symbolic link + * @param fname + */ +int +dashl(const char *fname) +{ + struct stat st; + + return (lstat(fname, &st) == 0 && S_ISLNK(st.st_mode)); +} + +/** + * 傳回 fname 是否為一般的檔案 + * @param fname + */ +int +dashf(const char *fname) +{ + struct stat st; + + return (stat(fname, &st) == 0 && S_ISREG(st.st_mode)); +} + +/** + * 傳回 fname 是否為目錄 + * @param fname + */ +int +dashd(const char *fname) +{ + struct stat st; + + return (stat(fname, &st) == 0 && S_ISDIR(st.st_mode)); +} + +#define BUFFER_SIZE 8192 +int copy_file_to_file(const char *src, const char *dst) +{ + char buf[BUFFER_SIZE]; + int fdr, fdw, len; + + if ((fdr = open(src, O_RDONLY)) < 0) + return -1; + + if ((fdw = open(dst, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) { + close(fdr); + return -1; + } + + while (1) { + len = read(fdr, buf, sizeof(buf)); + if (len <= 0) + break; + write(fdw, buf, len); + if (len < BUFFER_SIZE) + break; + } + + close(fdr); + close(fdw); + return 0; +} +#undef BUFFER_SIZE + +int copy_file_to_dir(const char *src, const char *dst) +{ + char buf[PATH_MAX]; + char *slash; + if ((slash = rindex(src, '/')) == NULL) + snprintf(buf, sizeof(buf), "%s/%s", dst, src); + else + snprintf(buf, sizeof(buf), "%s/%s", dst, slash); + return copy_file_to_file(src, buf); +} + +int copy_dir_to_dir(const char *src, const char *dst) +{ + DIR *dir; + struct dirent *entry; + struct stat st; + char buf[PATH_MAX], buf2[PATH_MAX]; + + if (stat(dst, &st) < 0) + if (mkdir(dst, 0700) < 0) + return -1; + + if ((dir = opendir(src)) == NULL) + return -1; + + while ((entry = readdir(dir)) != NULL) { + if (strcmp(entry->d_name, ".") == 0 || + strcmp(entry->d_name, "..") == 0) + continue; + snprintf(buf, sizeof(buf), "%s/%s", src, entry->d_name); + snprintf(buf2, sizeof(buf2), "%s/%s", dst, entry->d_name); + if (stat(buf, &st) < 0) + continue; + if (S_ISDIR(st.st_mode)) + mkdir(buf2, 0700); + copy_file(buf, buf2); + } + + closedir(dir); + return 0; +} + +/** + * copy src to dst (recursively) + * @param src and dst are file or dir + * @return -1 if failed + */ +int copy_file(const char *src, const char *dst) +{ + struct stat st; + + if (stat(dst, &st) == 0 && S_ISDIR(st.st_mode)) { + if (stat(src, &st) < 0) + return -1; + + if (S_ISDIR(st.st_mode)) + return copy_dir_to_dir(src, dst); + else if (S_ISREG(st.st_mode)) + return copy_file_to_dir(src, dst); + return -1; + } + else if (stat(src, &st) == 0 && S_ISDIR(st.st_mode)) + return copy_dir_to_dir(src, dst); + return copy_file_to_file(src, dst); +} + +int +Rename(const char *src, const char *dst) +{ + if (rename(src, dst) == 0) + return 0; + if (!strchr(src, ';') && !strchr(dst, ';')) + { + pid_t pid = fork(); + if (pid == 0) + execl("/bin/mv", "mv", "-f", src, dst, (char *)NULL); + else if (pid > 0) + waitpid(pid, NULL, 0); + else + return -1; + } + return -1; +} + +int +Copy(const char *src, const char *dst) +{ + int fi, fo, bytes; + char buf[8192]; + fi=open(src, O_RDONLY); + if(fi<0) return -1; + fo=open(dst, O_WRONLY | O_TRUNC | O_CREAT, 0600); + if(fo<0) {close(fi); return -1;} + while((bytes=read(fi, buf, sizeof(buf)))>0) + write(fo, buf, bytes); + close(fo); + close(fi); + return 0; +} + +int +CopyN(const char *src, const char *dst, int n) +{ + int fi, fo, bytes; + char buf[8192]; + + fi=open(src, O_RDONLY); + if(fi<0) return -1; + + fo=open(dst, O_WRONLY | O_TRUNC | O_CREAT, 0600); + if(fo<0) {close(fi); return -1;} + + while(n > 0 && (bytes=read(fi, buf, sizeof(buf)))>0) + { + n -= bytes; + if (n < 0) + bytes += n; + write(fo, buf, bytes); + } + close(fo); + close(fi); + return 0; +} + +/* append data from tail of src (starting point=off) to dst */ +int +AppendTail(const char *src, const char *dst, int off) +{ + int fi, fo, bytes; + char buf[8192]; + + fi=open(src, O_RDONLY); + if(fi<0) return -1; + + fo=open(dst, O_WRONLY | O_APPEND | O_CREAT, 0600); + if(fo<0) {close(fi); return -1;} + + if(off > 0) + lseek(fi, (off_t)off, SEEK_SET); + + while((bytes=read(fi, buf, sizeof(buf)))>0) + { + write(fo, buf, bytes); + } + close(fo); + close(fi); + return 0; +} + +/** + * @param src file + * @param dst file + * @return 0 if success + */ +int +Link(const char *src, const char *dst) +{ + if (symlink(src, dst) == 0) + return 0; + + return Copy(src, dst); +} + diff --git a/src/libbbsutil/lock.c b/src/libbbsutil/lock.c new file mode 100644 index 00000000..4b28bab1 --- /dev/null +++ b/src/libbbsutil/lock.c @@ -0,0 +1,23 @@ +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> + +/** + * lock fd + * @param mode F_WRLCK, F_UNLCK + */ +void +PttLock(int fd, int start, int size, int mode) +{ + static struct flock lock_it; + int ret; + + lock_it.l_whence = SEEK_CUR;/* from current point */ + lock_it.l_start = start; /* -"- */ + lock_it.l_len = size; /* length of data */ + lock_it.l_type = mode; /* set exclusive/write lock */ + lock_it.l_pid = 0; /* pid not actually interesting */ + while ((ret = fcntl(fd, F_SETLKW, &lock_it)) < 0 && errno == EINTR) + sleep(1); +} + diff --git a/src/libbbsutil/log.c b/src/libbbsutil/log.c new file mode 100644 index 00000000..9fe3d514 --- /dev/null +++ b/src/libbbsutil/log.c @@ -0,0 +1,43 @@ +#include <stdarg.h> +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> + +#include "libbbsutil.h" + +int +log_filef(const char *fn, int log_flag, const char *fmt,...) +{ + char msg[256]; + + va_list ap; + va_start(ap, fmt); + vsnprintf(msg, sizeof(msg), fmt, ap); + va_end(ap); + + return log_file(fn, log_flag, msg); +} + +int +log_file(const char *fn, int log_flag, const char *msg) +{ + int fd; + int flag = O_APPEND | O_WRONLY; + int mode = 0664; + + if (log_flag & LOG_CREAT) + flag |= O_CREAT; + + fd = open(fn, flag, mode); + if( fd < 0 ) + return -1; + + if( write(fd, msg, strlen(msg)) < 0 ){ + close(fd); + return -1; + } + close(fd); + return 0; +} + diff --git a/src/libbbsutil/net.c b/src/libbbsutil/net.c new file mode 100644 index 00000000..60208a65 --- /dev/null +++ b/src/libbbsutil/net.c @@ -0,0 +1,114 @@ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <unistd.h> + +#include "libbbsutil.h" + +unsigned int +ipstr2int(const char *ip) +{ + unsigned int i, val = 0; + char buf[32]; + char *nil, *p; + + strlcpy(buf, ip, sizeof(buf)); + p = buf; + for (i = 0; i < 4; i++) { + nil = strchr(p, '.'); + if (nil != NULL) + *nil = 0; + val *= 256; + val += atoi(p); + if (nil != NULL) + p = nil + 1; + } + return val; +} + +int tobind(const char * host, int port) +{ + int sockfd, val = 1; + struct sockaddr_in servaddr; + + if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) { + perror("socket()"); + exit(1); + } + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, + (char *)&val, sizeof(val)); + bzero(&servaddr, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + if (host == NULL || host[0] == 0) + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); + else if (inet_aton(host, &servaddr.sin_addr) == 0) { + perror("inet_aton()"); + exit(1); + } + servaddr.sin_port = htons(port); + if( bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0 ) { + perror("bind()"); + exit(1); + } + if( listen(sockfd, 5) < 0 ) { + perror("listen()"); + exit(1); + } + + return sockfd; +} + +int toconnect(const char *host, int port) +{ + int sock; + struct sockaddr_in serv_name; + if( (sock = socket(AF_INET, SOCK_STREAM, 0)) < 0 ){ + perror("socket"); + return -1; + } + + serv_name.sin_family = AF_INET; + serv_name.sin_addr.s_addr = inet_addr(host); + serv_name.sin_port = htons(port); + if( connect(sock, (struct sockaddr*)&serv_name, sizeof(serv_name)) < 0 ){ + close(sock); + return -1; + } + return sock; +} + +/** + * same as read(2), but read until exactly size len + */ +int toread(int fd, void *buf, int len) +{ + int l; + for( l = 0 ; len > 0 ; ) + if( (l = read(fd, buf, len)) <= 0 ) + return -1; + else{ + buf += l; + len -= l; + } + return l; +} + +/** + * same as write(2), but write until exactly size len + */ +int towrite(int fd, const void *buf, int len) +{ + int l; + for( l = 0 ; len > 0 ; ) + if( (l = write(fd, buf, len)) <= 0 ) + return -1; + else{ + buf += l; + len -= l; + } + return l; +} diff --git a/src/libbbsutil/sort.c b/src/libbbsutil/sort.c new file mode 100644 index 00000000..edecc0a8 --- /dev/null +++ b/src/libbbsutil/sort.c @@ -0,0 +1,10 @@ + +int cmp_int(const void *a, const void *b) +{ + return *(int*)a - *(int*)b; +} + +int cmp_int_desc(const void * a, const void * b) +{ + return cmp_int(b, a); +} diff --git a/src/libbbsutil/string.c b/src/libbbsutil/string.c new file mode 100644 index 00000000..695d65ab --- /dev/null +++ b/src/libbbsutil/string.c @@ -0,0 +1,284 @@ +#include <string.h> +#include <ctype.h> +#include <assert.h> +#include "fnv_hash.h" + +#include "ansi.h" +#include "libbbsutil.h" + +#define CHAR_LOWER(c) ((c >= 'A' && c <= 'Z') ? c|32 : c) +/* ----------------------------------------------------- */ +/* 字串轉換檢查函數 */ +/* ----------------------------------------------------- */ +/** + * 將字串 s 轉為小寫存回 t + * @param t allocated char array + * @param s + */ +void +str_lower(char *t, const char *s) +{ + register unsigned char ch; + + do { + ch = *s++; + *t++ = CHAR_LOWER(ch); + } while (ch); +} + +/** + * 移除字串 buf 後端多餘的空白。 + * @param buf + */ +void +trim(char *buf) +{ /* remove trailing space */ + char *p = buf; + + while (*p) + p++; + while (--p >= buf) { + if (*p == ' ') + *p = '\0'; + else + break; + } +} + +/** + * 移除 src 的 '\n' 並改成 '\0' + * @param src + */ +void chomp(char *src) +{ + while(*src){ + if (*src == '\n') + *src = 0; + else + src++; + } +} + +int +strip_blank(char *cbuf, char *buf) +{ + for (; *buf; buf++) + if (*buf != ' ') + *cbuf++ = *buf; + *cbuf = 0; + return 0; +} + +static const char EscapeFlag[] = { + /* 0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0, 0, 0, 0, 0, + /* 20 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 30 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, /* 0~9 ;= */ + /* 40 */ 0, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, /* ABCDHIJK */ + /* 50 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 60 */ 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 2, 2, 0, 0, /* fhlm */ + /* 70 */ 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* su */ + /* 80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* A0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* B0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* C0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* D0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* E0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* F0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; +/** + * 根據 mode 來 strip 字串 src,並把結果存到 dst + * @param dst + * @param src + * @param mode enum {STRIP_ALL = 0, ONLY_COLOR, NO_RELOAD}; + * STRIP_ALL: 全部吃掉 + * ONLY_COLOR: 吃掉所有跟顏色無關的 (ESC[*m) + * NO_RELOAD: 不 strip (?) + * @return strip 後的長度 + */ +int +strip_ansi(char *dst, const char *src, enum STRIP_FLAG mode) +{ + register int count = 0; +#define isEscapeParam(X) (EscapeFlag[(int)(X)] & 1) +#define isEscapeCommand(X) (EscapeFlag[(int)(X)] & 2) + + for(; *src; ++src) + if( *src != ESC_CHR ){ + if( dst ) + *dst++ = *src; + ++count; + }else{ + const char* p = src + 1; + if( *p != '[' ){ + ++src; + if(*src=='\0') break; + continue; + } + while(isEscapeParam(*++p)); + if( (mode == NO_RELOAD && isEscapeCommand(*p)) || + (mode == ONLY_COLOR && *p == 'm' )){ + register int len = p - src + 1; + if( dst ){ + strncpy(dst, src, len); + dst += len; + } + count += len; + } + src = p; + if(*src=='\0') break; + } + if( dst ) + *dst = 0; + return count; +} + +int +strlen_noansi(const char *s) +{ + // XXX this is almost identical to + // strip_ansi(NULL, s, STRIP_ALL) + register int count = 0, mode = 0; + + if (!s || !*s) + return 0; + + for (; *s; ++s) + { + // 0 - no ansi, 1 - [, 2 - param+cmd + switch (mode) + { + case 0: + if (*s == ESC_CHR) + mode = 1; + else + count ++; + break; + + case 1: + if (*s == '[') + mode = 2; + else + mode = 0; // unknown command + break; + + case 2: + if (isEscapeParam(*s)) + continue; + else if (isEscapeCommand(*s)) + mode = 0; + else + mode = 0; + break; + } + } + return count; +} + +void +strip_nonebig5(unsigned char *str, int maxlen) +{ + int i; + int len=0; + for(i=0;i<maxlen && str[i];i++) { + if(32<=str[i] && str[i]<128) + str[len++]=str[i]; + else if(str[i]==255) { + if(i+1<maxlen) + if(251<=str[i+1] && str[i+1]<=254) { + i++; + if(i+1<maxlen && str[i+1]) + i++; + } + continue; + } else if(str[i]&0x80) { + if(i+1<maxlen) + if((0x40<=str[i+1] && str[i+1]<=0x7e) || + (0xa1<=str[i+1] && str[i+1]<=0xfe)) { + str[len++]=str[i]; + str[len++]=str[i+1]; + i++; + } + } + } + if(len<maxlen) + str[len]='\0'; +} + +/* ----------------------------------------------------- */ +/* 字串檢查函數:英文、數字、檔名、E-mail address */ +/* ----------------------------------------------------- */ + +int +invalid_pname(const char *str) +{ + const char *p1, *p2, *p3; + + p1 = str; + while (*p1) { + if (!(p2 = strchr(p1, '/'))) + p2 = str + strlen(str); + if (p1 + 1 > p2 || p1 + strspn(p1, ".") == p2) /* 不允許用 / 開頭, 或是 // 之間只有 . */ + return 1; + for (p3 = p1; p3 < p2; p3++) + if (!isalnum(*p3) && !strchr("@[]-._", *p3)) /* 只允許 alnum 或這些符號 */ + return 1; + p1 = p2 + (*p2 ? 1 : 0); + } + return 0; +} + +/* + * return 1 if /^[0-9]+$/ + * 0 else, 含空字串 + */ +int is_number(const char *p) +{ + if (*p == '\0') + return 0; + + for(; *p; p++) { + if (*p < '0' || '9' < *p) + return 0; + } + return 1; +} + +unsigned +StringHash(const char *s) +{ + return fnv1a_32_strcase(s, FNV1_32_INIT); +} + +/* qp_encode() modified from mutt-1.5.7/rfc2047.c q_encoder() */ +const char MimeSpecials[] = "@.,;:<>[]\\\"()?/= \t"; +char * qp_encode (char *s, size_t slen, const char *d, const char *tocode) +{ + char hex[] = "0123456789ABCDEF"; + char *s0 = s; + + memcpy (s, "=?", 2), s += 2; + memcpy (s, tocode, strlen (tocode)), s += strlen (tocode); + memcpy (s, "?Q?", 3), s += 3; + assert(s-s0+3<slen); + + while (*d != '\0' && s-s0+6<slen) + { + unsigned char c = *d++; + if (c == ' ') + *s++ = '_'; + else if (c >= 0x7f || c < 0x20 || c == '_' || strchr (MimeSpecials, c)) + { + *s++ = '='; + *s++ = hex[(c & 0xf0) >> 4]; + *s++ = hex[c & 0x0f]; + } + else + *s++ = c; + } + memcpy (s, "?=", 2), s += 2; + *s='\0'; + return s0; +} + diff --git a/src/libbbsutil/time.c b/src/libbbsutil/time.c new file mode 100644 index 00000000..2e0dbdd1 --- /dev/null +++ b/src/libbbsutil/time.c @@ -0,0 +1,116 @@ +#include <time.h> +#include <stdio.h> +#include "libbbsutil.h" + +static char cdate_buffer[32]; + +/** + * 閏年 + */ +int is_leap_year(int year) +{ + return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0); +} + +/** + * 給日期求星座 + * + * @return 1..12 + */ +int getHoroscope(int m, int d) +{ + if (m > 12 || m < 1) + return 1; + + // 摩羯 水瓶 雙魚 牡羊 金牛 雙子 巨蟹 獅子 處女 天秤 天蠍 射手 + const int firstday[12] = { + /* Jan. */ 20, 19, 21, 20, 21, 21, 23, 23, 23, 23, 22, 22 + }; + if (d >= firstday[m - 1]) { + if (m == 12) + return 1; + else + return m + 1; + } + else + return m; +} + +/** + * 23+1 bytes, "12/31/2007 00:00:00 Mon\0" + */ +char * +Cdate(const time4_t *clock) +{ + time_t temp = (time_t)*clock; + struct tm *mytm = localtime(&temp); + + strftime(cdate_buffer, sizeof(cdate_buffer), "%m/%d/%Y %T %a", mytm); + return cdate_buffer; +} + +/** + * 19+1 bytes, "12/31/2007 00:00:00\0" + */ +char * +Cdatelite(const time4_t *clock) +{ + time_t temp = (time_t)*clock; + struct tm *mytm = localtime(&temp); + + strftime(cdate_buffer, sizeof(cdate_buffer), "%m/%d/%Y %T", mytm); + return cdate_buffer; +} + +/** + * 10+1 bytes, "12/31/2007\0" + */ +char * +Cdatedate(const time4_t * clock) +{ + time_t temp = (time_t)*clock; + struct tm *mytm = localtime(&temp); + + strftime(cdate_buffer, sizeof(cdate_buffer), "%m/%d/%Y", mytm); + return cdate_buffer; +} + +#ifdef TIMET64 +char * +ctime4(const time4_t *clock) +{ + time_t temp = (time_t)*clock; + + return ctime(&temp); +} + +struct tm *localtime4(const time4_t *t) +{ + if( t == NULL ) + return localtime(NULL); + else { + time_t temp = (time_t)*t; + return localtime(&temp); + } +} + +time4_t time4(time4_t *ptr) +{ + if( ptr == NULL ) + return time(NULL); + else + return *ptr = (time4_t)time(NULL); +} +#endif + +char * +my_ctime(const time4_t * t, char *ans, int len) +{ + struct tm *tp; + + tp = localtime4((time4_t*)t); + snprintf(ans, len, + "%02d/%02d/%02d %02d:%02d:%02d", (tp->tm_year % 100), + tp->tm_mon + 1, tp->tm_mday, tp->tm_hour, tp->tm_min, tp->tm_sec); + return ans; +} |