static int meta_escape(char*,size_t);
static FILE *meta_search(const char*);
-static ssize_t next_line(FILE*,char*,size_t);
+static ssize_t next_line(FILE*,char**,char**,char*,size_t);
int meta_entry(const char *path, struct rss_entry *entry) {
char buf[META_MAX_LINE_SIZE];
char *key, *value;
FILE *fp;
+ ssize_t i;
+
+ if(NULL==path) { return -1; }
+ if(NULL==entry) { return -1; }
fp = meta_search(path);
if(NULL==fp) { return 0; }
- while((i = next_line(fp,&key,buf,META_MAX_SIZE))>0) {
+ while((i = next_line(fp,&key,&value,buf,META_MAX_LINE_SIZE))>0) {
if(strcmp(key,RSS_TAG_TITLE)==0) {
entry->title = strndup(value,i);
} else if(strcmp(key,RSS_TAG_LINK)==0) {
case '<':
if(left<=4) { return -1; }
memmove(&(p[4]),p,len);
- strcpy(p,"<")
+ strcpy(p,"<");
p += 4;
break;
case '\\':
p++;
}
break;
- case '>';
+ case '>':
if(left<=4) { return -1; }
memmove(&(p[4]),p,len);
- strcpy(p,">")
+ strcpy(p,">");
p += 4;
break;
case '&':
if(left<=5) { return -1; }
memmove(&(p[5]),p,len);
- strcpy(p,"&")
+ strcpy(p,"&");
p += 5;
break;
default:
char buf[META_MAX_LINE_SIZE];
char *key, *value;
FILE *fp;
+ ssize_t i;
+
+ if(NULL==path) { return -1; }
+ if(NULL==info) { return -1; }
fp = meta_search(path);
if(NULL==fp) { return 0; }
- while((i = next_line(fp,&key,&value,buf,META_MAX_SIZE))>0) {
+ while((i = next_line(fp,&key,&value,buf,META_MAX_LINE_SIZE))>0) {
if(strcmp(key,RSS_TAG_TITLE)==0) {
info->title = strndup(value,i);
} else if(strcmp(key,RSS_TAG_LINK)==0) {
} else if(strcmp(key,RSS_TAG_DESCRIPTION)==0) {
info->description = strndup(value,i);
} else if(strcmp(key,RSS_TAG_LANGUAGE)==0) {
- entry->language = strndup(value,i);
+ info->language = strndup(value,i);
} else if(strcmp(key,RSS_TAG_LASTBUILDDATE)==0) {
return -1;
} else { goto panic; }
}
static FILE *meta_search(const char *path) {
+ FILE *fp;
char *p;
size_t len;
if(NULL==p) { return NULL; }
strcpy(p,path);
- strncat(p,".meta",5);
+ strcat(p,".meta");
}
fp = fopen(p,"r");
return fp;
}
-static ssize_t next_line(FILE *fp, char *buf, size_t buf_size) {
+static ssize_t next_line(FILE *fp, char **key, char **value, char *buf, size_t buf_size) {
if(fgets(buf,buf_size,fp)==NULL) { return -1; }
if(meta_escape(buf,buf_size)<0) { return -1; }
- return 1;
+ (*key) = buf;
+ (*value) = strchr(buf,'=');
+ if(NULL==(*value)) { return -1; }
+
+ (*value) = '\0';
+ (*value)++;
+ return buf_size - strlen(*key);
}
--- /dev/null
+#include<test_utils.h>
+
+#include<meta.h>
+
+int main();
+static void meta_entry_basic_test();
+static void meta_info_basic_test();
+
+int main() {
+ setup_env();
+
+ meta_entry_basic_test();
+ meta_info_basic_test();
+
+ clean_env();
+
+ return EXIT_SUCCESS;
+}
+
+static void meta_entry_basic_test() {
+ struct rss_entry *entry;
+
+ assert(1==rss_entry_init(&entry));
+
+ assert(meta_entry(NULL,NULL)==-1);
+ assert(meta_entry(TEST_FILE_1,NULL)==-1);
+
+ // TEST_FILE_3's .meta file contains invalid fields
+ assert(meta_entry(TEST_FILE_3,entry)==-1);
+
+ // PREFIX's .meta file is meant to contain channel info
+ // (and as such will have invalid fields)
+ assert(meta_entry(PREFIX,entry)==-1);
+
+ assert(meta_entry(TEST_FILE_1,entry)==1);
+
+ assert(strcmp(entry->title,"test title")==0);
+ assert(strcmp(entry->link,"https://whatisarealink.com")==0);
+// assert(strcmp(entry->pub_date,"")==0);
+ assert(strcmp(entry->description,"I wonder if \n this'll properly be formatted/escaped \\><?")==0);
+ assert(strcmp(entry->guid,"magnet=asldkfjsldkfjslkdjfldsdjlfkjsdf")==0);
+
+ rss_entry_free(entry);
+}
+
+static void meta_info_basic_test() {
+ struct rss_channel_info *info;
+
+ assert(rss_channel_info_init(&info)==1);
+
+ assert(meta_info(NULL,NULL)==-1);
+ assert(meta_info(PREFIX,NULL)==-1);
+
+ // TEST_FILE_3's .meta file contains invalid fields
+ assert(meta_info(TEST_FILE_3,info)==-1);
+
+ // TEST_FILE_1's .meta file is meant to contain entry fields
+ // (and as such will have invalid fields)
+ assert(meta_info(TEST_FILE_1,info)==-1);
+
+ assert(meta_info(PREFIX,info)==1);
+
+ assert(strcmp(info->title,"TITLE")==0);
+ assert(strcmp(info->link,"http://test.com")==0);
+ assert(strcmp(info->description,"what is a description")==0);
+ assert(strcmp(info->language,"en-us")==0);
+// assert(strcmp(info->last_build_date,"")==0);
+
+ rss_channel_info_free(info);
+}
int main();
static FILE *setup_file_pointer();
+static void rss_channel_info_init_basic_test();
static void rss_entry_basic_test();
static void rss_entry_correctness_test();
+static void rss_entry_init_basic_test();
static void rss_footer_basic_test();
static void rss_footer_correctness_test();
static void rss_header_basic_test();
int main() {
setup_env();
+ rss_entry_init_basic_test();
+ rss_channel_info_init_basic_test();
rss_entry_basic_test();
rss_entry_correctness_test();
rss_footer_basic_test();
return EXIT_SUCCESS;
}
+static void rss_channel_info_init_basic_test() {
+ struct rss_channel_info *p;
+
+ assert(rss_channel_info_init(NULL)==-1);
+ assert(rss_channel_info_init(&p)==1);
+
+ rss_channel_info_free(p);
+}
+
static void rss_entry_basic_test() {
FILE *fp;
- struct rss_entry p;
+ struct rss_entry *p;
+ char *tmp;
- memset(&p,0,sizeof(struct rss_entry));
+ assert(rss_entry_init(&p)==1);
fp = setup_file_pointer();
assert(rss_entry(NULL,NULL)==-1);
assert(rss_entry(fp,NULL)==-1);
- assert(rss_entry(fp,&p)==-1);
+ assert(rss_entry(fp,p)==-1);
char bad_title[] = "";
char sample_title[] = "sample title";
char sample_description[] = "sample description";
char sample_guid[] = "laskdjflkasdjf";
- p.title = sample_title;
- p.link = sample_link;
- p.description = sample_description;
- p.guid = sample_guid;
- p.pub_date = *localtime(&(time_t){time(NULL)});
+ p->title = strdup(sample_title);
+ p->link = strdup(sample_link);
+ p->description = strdup(sample_description);
+ p->guid = strdup(sample_guid);
+ p->pub_date = *localtime(&(time_t){time(NULL)});
- assert(rss_entry(fp,&p)==1);
+ assert(rss_entry(fp,p)==1);
- p.title = bad_title;
- assert(rss_entry(fp,&p)==-1);
- p.title = sample_title;
-
- p.link = bad_link;
- assert(rss_entry(fp,&p)==-1);
- p.link = sample_link;
-
- p.description = bad_description;
- assert(rss_entry(fp,&p)==1);
- p.description = sample_description;
- assert(rss_entry(fp,&p)==1);
+ tmp = p->title;
+ p->title = bad_title;
+ assert(rss_entry(fp,p)==-1);
+ p->title = tmp;
+
+ tmp = p->link;
+ p->link = bad_link;
+ assert(rss_entry(fp,p)==-1);
+ p->link = tmp;
+
+ tmp = p->description;
+ p->description = bad_description;
+ assert(rss_entry(fp,p)==1);
+ p->description = tmp;
+ assert(rss_entry(fp,p)==1);
- p.guid = NULL;
- assert(rss_entry(fp,&p)==1);
- p.guid = sample_guid;
- assert(rss_entry(fp,&p)==1);
+ tmp = p->guid;
+ p->guid = NULL;
+ assert(rss_entry(fp,p)==1);
+ p->guid = tmp;
+ assert(rss_entry(fp,p)==1);
fclose(fp);
+
+ rss_entry_free(p);
+
reset_env();
}
static void rss_entry_correctness_test() {
FILE *fp;
- struct rss_entry p;
+ struct rss_entry *p;
unsigned char hash[crypto_hash_sha256_BYTES];
unsigned char expected[crypto_hash_sha256_BYTES] = {252,1,77,6,36,221,191,114,180,137,47,54,77,39,151,196,0,85,115,184,127,210,230,152,114,130,36,140,33,239,194,30};
- memset(&p,0,sizeof(struct rss_entry));
+ assert(1==rss_entry_init(&p));
fp = setup_file_pointer();
char sample_description[] = "sample description";
char sample_guid[] = "laskdjflkasdjf";
- p.title = sample_title;
- p.link = sample_link;
- p.description = sample_description;
- p.guid = sample_guid;
+ p->title = strdup(sample_title);
+ p->link = strdup(sample_link);
+ p->description = strdup(sample_description);
+ p->guid = strdup(sample_guid);
time_t seconds = 1231006505;
- memcpy(&(p.pub_date), gmtime(&seconds), sizeof(struct tm));
+ memcpy(&(p->pub_date), gmtime(&seconds), sizeof(struct tm));
- assert(rss_entry(fp,&p)==1);
+ assert(rss_entry(fp,p)==1);
fclose(fp);
hash_file(TEST_FILE_7,hash,crypto_hash_sha256_BYTES);
assert(memcmp(hash,expected,crypto_hash_sha256_BYTES)==0);
+ rss_entry_free(p);
+
reset_env();
}
+static void rss_entry_init_basic_test() {
+ struct rss_entry *p;
+
+ assert(rss_entry_init(NULL)==-1);
+ assert(rss_entry_init(&p)==1);
+
+ rss_entry_free(p);
+}
+
static void rss_footer_basic_test() {
FILE *fp;
static void rss_info_basic_test() {
FILE *fp;
- struct rss_channel_info p;
+ struct rss_channel_info *p;
+ char *tmp;
- memset(&p,0,sizeof(struct rss_channel_info));
+ assert(1==rss_channel_info_init(&p));
fp = setup_file_pointer();
char bad_language_2[] = "alskdjflkasdjfaslkdf";
char sample_language[] = "en-us";
- p.title = sample_title;
- p.link = sample_link;
- p.description = sample_description;
- p.language = sample_language;
- p.last_build_date = *localtime(&(time_t){time(NULL)});
-
- assert(rss_info(fp,&p)==1);
-
- p.title = bad_title;
- assert(rss_info(fp,&p)==-1);
- p.title = sample_title;
+ p->title = strdup(sample_title);
+ p->link = strdup(sample_link);
+ p->description = strdup(sample_description);
+ p->language = strdup(sample_language);
+ p->last_build_date = *localtime(&(time_t){time(NULL)});
+
+ assert(rss_info(fp,p)==1);
+
+ tmp = p->title;
+ p->title = bad_title;
+ assert(rss_info(fp,p)==-1);
+ p->title = tmp;
+
+ tmp = p->link;
+ p->link = bad_link;
+ assert(rss_info(fp,p)==-1);
+ p->link = tmp;
+
+ tmp = p->description;
+ p->description = bad_description;
+ assert(rss_info(fp,p)==1);
+ p->description = tmp;
+ assert(rss_info(fp,p)==1);
+
+ tmp = p->language;
+ p->language = bad_language_1;
+ assert(rss_info(fp,p)==1); // should succeed (fills with default)
+ p->language = bad_language_2;
+ assert(rss_info(fp,p)==1); // no locale checking done (out of scope of rss_info)
+ p->language = tmp;
- p.link = bad_link;
- assert(rss_info(fp,&p)==-1);
- p.link = sample_link;
-
- p.description = bad_description;
- assert(rss_info(fp,&p)==1);
- p.description = sample_description;
- assert(rss_info(fp,&p)==1);
+ fclose(fp);
- p.language = bad_language_1;
- assert(rss_info(fp,&p)==1); // should succeed (fills with default)
- p.language = bad_language_2;
- assert(rss_info(fp,&p)==1); // no locale checking done (out of scope of rss_info)
- p.language = sample_language;
+ rss_channel_info_free(p);
- fclose(fp);
reset_env();
}
static void rss_info_correctness_test() {
FILE *fp;
- struct rss_channel_info p;
+ struct rss_channel_info *p;
unsigned char hash[crypto_hash_sha256_BYTES];
unsigned char expected[crypto_hash_sha256_BYTES] = {175,238,191,8,225,134,109,105,86,61,240,232,31,206,163,165,243,43,229,34,169,83,166,18,54,229,225,99,110,47,38,243};
- memset(&p,0,sizeof(struct rss_channel_info));
+ assert(1==rss_channel_info_init(&p));
fp = setup_file_pointer();
char sample_description[] = "alsdjflaksdjfoikasjdfliasjdfoijawdf";
char sample_language[] = "en-us";
- p.title = sample_title;
- p.link = sample_link;
- p.description = sample_description;
- p.language = sample_language;
+ p->title = strdup(sample_title);
+ p->link = strdup(sample_link);
+ p->description = strdup(sample_description);
+ p->language = strdup(sample_language);
time_t seconds = 1231006505;
- memcpy(&(p.last_build_date), gmtime(&seconds), sizeof(struct tm));
+ memcpy(&(p->last_build_date), gmtime(&seconds), sizeof(struct tm));
- assert(rss_info(fp,&p)==1);
+ assert(rss_info(fp,p)==1);
fclose(fp);
hash_file(TEST_FILE_7,hash,crypto_hash_sha256_BYTES);
assert(memcmp(hash,expected,crypto_hash_sha256_BYTES)==0);
+ rss_channel_info_free(p);
+
reset_env();
}