From d81158e4b60f0e0dff1e13adb253c2e01865de0d Mon Sep 17 00:00:00 2001 From: Chip Black Date: Thu, 30 May 2013 19:03:23 -0500 Subject: [PATCH 01/16] Paranoia fix for reading password version --- common/auth.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/common/auth.c b/common/auth.c index 6e5f346..3fd0376 100644 --- a/common/auth.c +++ b/common/auth.c @@ -66,7 +66,7 @@ int auth_get_password_version(const char *username) { char filename[512]; int fd; char str[4]; - int version; + int len; sprintf(filename, "%s/%s/password_version", DATA_PATH, username); if (access(filename, F_OK) != 0) { @@ -74,8 +74,9 @@ int auth_get_password_version(const char *username) { } fd = open(filename, O_RDONLY); - read(fd, str, 4); + len = read(fd, str, 4); close(fd); + str[len] = 0; /* strtol returns zero if there isn't a number */ return strtol(str, NULL, 10); } -- 2.25.1 From 5b9a1c597b87485253a11339067b60d08534f8b0 Mon Sep 17 00:00:00 2001 From: Chip Black Date: Sat, 1 Jun 2013 03:02:51 -0500 Subject: [PATCH 02/16] Bug hunting: Deadlocks, data safety, and dumb shit - Don't preallocate index files, instead just ftruncate() them to size. Index locality is pretty well moot when we're never reading more than 50 entries at a time. - Factor out data remapping - Added extra bounds checks for segments and records - Wasn't actually updating blerg->current_segment when switching segments, causing deadlock when the second record is written in a new segment. - Use posix_fallocate() instead of writing zeroes - Update record count *after* successfully writing a record, not before - Use fstat to determine new record data offset instead of ftell (not sure if this is better, but it sure looks cleaner). - Don't bother trying to write the rest of the data when we get a short write. Truncate and move on. --- database/database.c | 135 +++++++++++++++++++++++++------------------- 1 file changed, 77 insertions(+), 58 deletions(-) diff --git a/database/database.c b/database/database.c index e6e8707..c0ec591 100644 --- a/database/database.c +++ b/database/database.c @@ -45,15 +45,42 @@ void blerg_segment_close(struct blerg *blerg) { close(blerg->index_fd); } +int blerg_remap_data(struct blerg *blerg) { + struct stat st; + + if (blerg->data != NULL) + munmap(blerg->data, blerg->data_size); + fstat(blerg->data_fd, &st); + if (st.st_size == 0) { + /* Can't map an empty data file. */ + return 1; + } + blerg->data = (char *) mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, blerg->data_fd, 0); + if (blerg->data == MAP_FAILED) { + perror("Could not remap data"); + return 0; + } + blerg->data_size = st.st_size; + return 1; +} + int blerg_segment_switch(struct blerg *blerg, int new_segment) { char filename[512]; - uint64_t max_sequence = blerg_get_record_count(blerg); + uint64_t max_sequence_no = blerg_get_record_count(blerg); struct stat st; - if (new_segment > max_sequence / RECORDS_PER_SEGMENT) { + if (blerg->index != NULL && blerg->data != NULL && new_segment == blerg->current_segment) { + return 1; + } + + if (new_segment > max_sequence_no / RECORDS_PER_SEGMENT) { fprintf(stderr, "Cannot switch to sequence beyond last record\n"); return 0; } + if (new_segment < 0) { + fprintf(stderr, "Cannot switch to negative segment\n"); + return 0; + } blerg_segment_close(blerg); @@ -67,12 +94,10 @@ int blerg_segment_switch(struct blerg *blerg, int new_segment) { flock(blerg->index_fd, LOCK_EX); fstat(blerg->index_fd, &st); if (st.st_size == 0) { - int i; - struct record r; - memset((void *)&r, 0, sizeof(struct record)); - for (i = 0; i < RECORDS_PER_SEGMENT; i++) { - write(blerg->index_fd, &r, sizeof(struct record)); - } + /* ftruncate() means never having to say you're sorry. Sorry + in this case meaning "allocating disk space for a 1MB file + full or zeroes". */ + ftruncate(blerg->index_fd, RECORDS_PER_SEGMENT * sizeof(struct record)); } flock(blerg->index_fd, LOCK_UN); @@ -85,27 +110,23 @@ int blerg_segment_switch(struct blerg *blerg, int new_segment) { /* Load data file */ sprintf(filename, "%s/data%d", blerg->base_path, new_segment); blerg->data_fd = open(filename, O_RDWR | O_APPEND | O_CREAT, 0600); - fstat(blerg->data_fd, &st); - blerg->data_size = st.st_size; if (blerg->data_fd == -1) { perror("Could not open data"); goto open_failed_data_open; } - if (blerg->data_size > 0) { - blerg->data = (char *) mmap(NULL, blerg->data_size, PROT_READ, MAP_SHARED, blerg->data_fd, 0); - if (blerg->data == MAP_FAILED) { - perror("Could not mmap data"); - goto open_failed_data_mmap; - } + if (!blerg_remap_data(blerg)) { + goto open_failed_data_mmap; } + blerg->current_segment = new_segment; + return 1; open_failed_data_mmap: close(blerg->data_fd); open_failed_data_open: - munmap((void *)blerg->index, sizeof(RECORDS_PER_SEGMENT * sizeof(struct record))); + munmap((void *)blerg->index, RECORDS_PER_SEGMENT * sizeof(struct record)); open_failed_index_mmap: close(blerg->index_fd); open_failed_index_open: @@ -165,17 +186,10 @@ struct blerg *blerg_open(const char *name) { } fstat(blerg->meta_fd, &st); if (st.st_size < sizeof(struct meta)) { - // Fill the difference in size between sizeof(struct meta) and - // the file size with nulls. This allows seamless upgrades as - // long as struct meta only adds members. - int len = sizeof(struct meta) - st.st_size; - char *buf = (char *) malloc(len); - memset(buf, 0, len); - int tmpfd = dup(blerg->meta_fd); - FILE* tmp = fdopen(tmpfd, "a"); - fwrite(buf, len, 1, tmp); - fclose(tmp); - free(buf); + /* Extend the file if sizeof(struct meta) is larger than the + file. This allows seamless upgrades as long as struct meta + only adds members. */ + posix_fallocate(blerg->meta_fd, 0, sizeof(struct meta)); } blerg->meta = (struct meta *) mmap(NULL, sizeof(struct meta), PROT_READ | PROT_WRITE, MAP_SHARED, blerg->meta_fd, 0); if (blerg->meta == MAP_FAILED) { @@ -214,6 +228,9 @@ int blerg_close(struct blerg *blerg) { } int blerg_store(struct blerg *blerg, const char *data, int len) { + struct stat st; + int n; + if (len > MAX_RECORD_SIZE) { fprintf(stderr, "len > 64K\n"); return -1; @@ -222,8 +239,8 @@ int blerg_store(struct blerg *blerg, const char *data, int len) { flock(blerg->index_fd, LOCK_EX); flock(blerg->data_fd, LOCK_EX); - uint64_t record = blerg_increment_record_count(blerg); - if (record == -1) { + uint64_t record = blerg_get_record_count(blerg); + if (record == -1) { /* Intentional signed-unsigned coercion */ fprintf(stderr, "Could not find free record\n"); return -1; } @@ -233,30 +250,31 @@ int blerg_store(struct blerg *blerg, const char *data, int len) { int seg_rec = record % RECORDS_PER_SEGMENT; /* Get the position for the new data */ - FILE *datafile = fdopen(dup(blerg->data_fd), "a"); - fseek(datafile, 0, SEEK_END); - int curpos = ftell(datafile); - fclose(datafile); - - int bytes = 0; - do { - int n = write(blerg->data_fd, data + bytes, len); - if (n == -1) { - perror("Could not write data"); - /* Truncate anything we may have written */ - ftruncate(blerg->data_fd, curpos); - return -1; - } - bytes += n; - } while (bytes < len); + fstat(blerg->data_fd, &st); + int curpos = st.st_size; + + /* Write data to the data log */ + n = write(blerg->data_fd, data, len); + if (n < len) { + perror("Could not write data"); + /* Truncate anything we may have written */ + ftruncate(blerg->data_fd, curpos); + return -1; + } + + /* Update the index */ blerg->index[seg_rec].flags = 0x0001; blerg->index[seg_rec].offset = curpos; blerg->index[seg_rec].length = len; blerg->index[seg_rec].timestamp = time(NULL); + /* And finally increment the record count */ + blerg_increment_record_count(blerg); + flock(blerg->data_fd, LOCK_UN); flock(blerg->index_fd, LOCK_UN); + /* Now do those dirty microblogging deeds */ tag_scan(blerg->name, data, len, record); subscription_notify(blerg->name, record); @@ -268,6 +286,10 @@ int blerg_fetch(struct blerg *blerg, int record, char **data, int *length) { fprintf(stderr, "Invalid record\n"); return 0; } + if (record >= blerg_get_record_count(blerg)) { + fprintf(stderr, "Invalid record\n"); + return 0; + } int segment = record / RECORDS_PER_SEGMENT; if (segment != blerg->current_segment) @@ -282,20 +304,13 @@ int blerg_fetch(struct blerg *blerg, int record, char **data, int *length) { int rec_offset = blerg->index[seg_rec].offset; int rec_length = blerg->index[seg_rec].length; if (rec_offset >= blerg->data_size) { - /* We're accessing an out-of-bounds record in our mmap. - Recheck size and remap. */ - struct stat st; - fstat(blerg->data_fd, &st); - blerg->data_size = st.st_size; - if (rec_offset > blerg->data_size) { - fprintf(stderr, "Record offset outside of data!?"); + /* We're accessing an out-of-bounds record in our mmap. Remap + and recheck. */ + if (!blerg_remap_data(blerg)) { return 0; } - - munmap(blerg->data, blerg->data_size); - blerg->data = (char *) mmap(NULL, blerg->data_size, PROT_READ, MAP_SHARED, blerg->data_fd, 0); - if (blerg->data == MAP_FAILED) { - perror("Could not remap data"); + if (rec_offset >= blerg->data_size) { + fprintf(stderr, "Record offset outside of data!?"); return 0; } } @@ -318,6 +333,10 @@ time_t blerg_get_timestamp(struct blerg *blerg, int record) { fprintf(stderr, "Invalid record\n"); return 0; } + if (record >= blerg_get_record_count(blerg)) { + fprintf(stderr, "Invalid record\n"); + return 0; + } int segment = record / RECORDS_PER_SEGMENT; if (segment != blerg->current_segment) -- 2.25.1 From 142c00ad296af327d5d1718d60f23c0807033f15 Mon Sep 17 00:00:00 2001 From: Chip Black Date: Sun, 2 Jun 2013 18:59:47 -0500 Subject: [PATCH 03/16] More safety checks --- database/database.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/database/database.c b/database/database.c index c0ec591..c8b9b58 100644 --- a/database/database.c +++ b/database/database.c @@ -17,6 +17,12 @@ #include "util.h" #include "config.h" +#define CHECK_VALID_BLERG(r) \ + if (blerg == NULL) { \ + fprintf(stderr, "Invalid struct blerg\n"); \ + return r; \ + } + uint64_t blerg_get_record_count(struct blerg *blerg) { uint64_t count; flock(blerg->meta_fd, LOCK_SH); @@ -218,6 +224,7 @@ open_failed_blerg_malloc: } int blerg_close(struct blerg *blerg) { + CHECK_VALID_BLERG(0) blerg_segment_close(blerg); munmap((void *)blerg->meta, sizeof(struct meta)); close(blerg->meta_fd); @@ -231,8 +238,10 @@ int blerg_store(struct blerg *blerg, const char *data, int len) { struct stat st; int n; - if (len > MAX_RECORD_SIZE) { - fprintf(stderr, "len > 64K\n"); + CHECK_VALID_BLERG(-1) + + if (len > MAX_RECORD_SIZE || len <= 0) { + fprintf(stderr, "len out of bounds\n"); return -1; } @@ -282,12 +291,13 @@ int blerg_store(struct blerg *blerg, const char *data, int len) { } int blerg_fetch(struct blerg *blerg, int record, char **data, int *length) { - if (record < 0) { + CHECK_VALID_BLERG(0) + if (record < 0 || record >= blerg_get_record_count(blerg)) { fprintf(stderr, "Invalid record\n"); return 0; } - if (record >= blerg_get_record_count(blerg)) { - fprintf(stderr, "Invalid record\n"); + if (data == NULL || length == NULL) { + fprintf(stderr, "data or length is null\n"); return 0; } @@ -329,11 +339,8 @@ int blerg_fetch(struct blerg *blerg, int record, char **data, int *length) { } time_t blerg_get_timestamp(struct blerg *blerg, int record) { - if (record < 0) { - fprintf(stderr, "Invalid record\n"); - return 0; - } - if (record >= blerg_get_record_count(blerg)) { + CHECK_VALID_BLERG(0) + if (record < 0 || record >= blerg_get_record_count(blerg)) { fprintf(stderr, "Invalid record\n"); return 0; } @@ -352,9 +359,12 @@ time_t blerg_get_timestamp(struct blerg *blerg, int record) { } int blerg_set_subscription_mark(struct blerg *blerg) { + CHECK_VALID_BLERG(0) blerg->meta->subscription_mark = subscription_count_items(blerg->name); + return 1; } uint64_t blerg_get_subscription_mark(struct blerg *blerg) { + CHECK_VALID_BLERG(0) return blerg->meta->subscription_mark; } -- 2.25.1 From 767693caf2b41c2e857688d10d2c71bc77c0bbad Mon Sep 17 00:00:00 2001 From: Chip Black Date: Sun, 2 Jun 2013 19:25:35 -0500 Subject: [PATCH 04/16] Add support for "muting" accounts Muted accounts do not update reference or subscription indexes, making them effectively invisible, but unaware of the fact. --- database/database.c | 23 ++++++++++++++++++++--- database/database.h | 5 +++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/database/database.c b/database/database.c index c8b9b58..618c0d3 100644 --- a/database/database.c +++ b/database/database.c @@ -283,9 +283,11 @@ int blerg_store(struct blerg *blerg, const char *data, int len) { flock(blerg->data_fd, LOCK_UN); flock(blerg->index_fd, LOCK_UN); - /* Now do those dirty microblogging deeds */ - tag_scan(blerg->name, data, len, record); - subscription_notify(blerg->name, record); + if (!blerg_get_mute(blerg)) { + /* Now do those dirty microblogging deeds */ + tag_scan(blerg->name, data, len, record); + subscription_notify(blerg->name, record); + } return record; } @@ -368,3 +370,18 @@ uint64_t blerg_get_subscription_mark(struct blerg *blerg) { CHECK_VALID_BLERG(0) return blerg->meta->subscription_mark; } + +int blerg_set_mute(struct blerg *blerg, int v) { + CHECK_VALID_BLERG(0) + if (v) { + blerg->meta->status |= BLERGMETA_MUTED; + } else { + blerg->meta->status &= ~BLERGMETA_MUTED; + } + return 1; +} + +int blerg_get_mute(struct blerg *blerg) { + CHECK_VALID_BLERG(0) + return (blerg->meta->status & BLERGMETA_MUTED) > 0; +} diff --git a/database/database.h b/database/database.h index 412d6c7..aa2403a 100644 --- a/database/database.h +++ b/database/database.h @@ -20,8 +20,11 @@ struct record { struct meta { uint64_t sequence; uint64_t subscription_mark; + uint32_t status; }; +#define BLERGMETA_MUTED 0x00000001 + struct blerg { int meta_fd; int index_fd; @@ -44,5 +47,7 @@ uint64_t blerg_get_record_count(struct blerg *); time_t blerg_get_timestamp(struct blerg *blerg, int record); int blerg_set_subscription_mark(struct blerg *blerg); uint64_t blerg_get_subscription_mark(struct blerg *blerg); +int blerg_set_mute(struct blerg *blerg, int v); +int blerg_get_mute(struct blerg *blerg); #endif //_DATABASE_H -- 2.25.1 From fd07ab46f5f37057e9290441931d5de92d62761b Mon Sep 17 00:00:00 2001 From: Chip Black Date: Sun, 2 Jun 2013 22:38:25 -0500 Subject: [PATCH 05/16] Add mute support to blergtool --- tools/blergtool.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/tools/blergtool.c b/tools/blergtool.c index b0e7368..ab98a94 100644 --- a/tools/blergtool.c +++ b/tools/blergtool.c @@ -50,10 +50,11 @@ int main(int argc, char *argv[]) { char *data; int size; - blerg_fetch(f, record, &data, &size); + if (blerg_fetch(f, record, &data, &size)) { + fwrite(data, 1, size, stdout); + free(data); + } blerg_close(f); - fwrite(data, 1, size, stdout); - free(data); } else if (strncmp(argv[1], "list", 4) == 0) { char *tag = argv[2]; int count = 50; @@ -67,6 +68,26 @@ int main(int argc, char *argv[]) { } free(list); } + } else if (strncmp(argv[1], "mute", 4) == 0) { + char *store = argv[2]; + struct blerg *f = blerg_open(store); + if (!f) { + printf("Blerg open failed\n"); + exit(1); + } + + blerg_set_mute(f, 1); + blerg_close(f); + } else if (strncmp(argv[1], "unmute", 6) == 0) { + char *store = argv[2]; + struct blerg *f = blerg_open(store); + if (!f) { + printf("Blerg open failed\n"); + exit(1); + } + + blerg_set_mute(f, 0); + blerg_close(f); } else { help(); } -- 2.25.1 From 974dbf20da7aec573384615db50f7e03e56c1667 Mon Sep 17 00:00:00 2001 From: Chip Black Date: Sun, 2 Jun 2013 22:58:14 -0500 Subject: [PATCH 06/16] Changelog for 1.8.1 --- www/doc/changelog.html | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/www/doc/changelog.html b/www/doc/changelog.html index a7936d3..378372e 100644 --- a/www/doc/changelog.html +++ b/www/doc/changelog.html @@ -11,6 +11,25 @@ The intent of this changelog is to give an overview of the major changes and fixes made to Blërg. For a detailed changelog, see the git log. +

Version 1.8.1 - released Sunday, July 2, 2013 + +

Features Added

+
    +
  • Added a flag to account metadata allowing accounts to be "muted" so +their posts do not update tags/references/subscription indices.
  • +
  • Post indices are no longer preallocated, but instead created as +sparse files.
  • +
+ +

Bugs Squashed +
    +
  • Numerous safety and integrity checks added
  • +
  • The internal segment counter wasn't being updated when switching +segments, causing deadlock on the 65537th entry.
  • +
  • Record count is now updated after successfully writing a record +rather than before.
  • +
+

Version 1.8 - released Thursday, May 30, 2013

Features Added

-- 2.25.1 From 1b5012f54151382cddfe5ead3475f993ea947273 Mon Sep 17 00:00:00 2001 From: Chip Black Date: Sun, 2 Jun 2013 23:49:01 -0500 Subject: [PATCH 07/16] Properly initialize data_size for empty data segment --- database/database.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/database/database.c b/database/database.c index 618c0d3..52ebe8c 100644 --- a/database/database.c +++ b/database/database.c @@ -57,16 +57,16 @@ int blerg_remap_data(struct blerg *blerg) { if (blerg->data != NULL) munmap(blerg->data, blerg->data_size); fstat(blerg->data_fd, &st); - if (st.st_size == 0) { + blerg->data_size = st.st_size; + if (blerg->data_size == 0) { /* Can't map an empty data file. */ return 1; } - blerg->data = (char *) mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, blerg->data_fd, 0); + blerg->data = (char *) mmap(NULL, blerg->data_size, PROT_READ, MAP_SHARED, blerg->data_fd, 0); if (blerg->data == MAP_FAILED) { perror("Could not remap data"); return 0; } - blerg->data_size = st.st_size; return 1; } -- 2.25.1 From b8652ebcc24f8c9cc73ebcd453fed6c9d4fc8ba7 Mon Sep 17 00:00:00 2001 From: Chip Black Date: Tue, 11 Jun 2013 02:14:27 -0700 Subject: [PATCH 08/16] Make dialogs center on the screen, not the page --- www/css/blerg.css | 1 + 1 file changed, 1 insertion(+) diff --git a/www/css/blerg.css b/www/css/blerg.css index 45a553f..b99c134 100644 --- a/www/css/blerg.css +++ b/www/css/blerg.css @@ -325,6 +325,7 @@ h1, h2, h3 { } .blerg-dialog { + position: fixed; width: 300px; padding: 8px; } -- 2.25.1 From 260bc694bf7c988f064077758da3536a775d5eb2 Mon Sep 17 00:00:00 2001 From: Chip Black Date: Sat, 16 Nov 2013 02:27:13 -0800 Subject: [PATCH 09/16] Change some Welcome style as suggested by Benny --- www/css/blerg.css | 52 ++++++++++++++++++++++++++++++++------ www/development.html | 3 +++ www/jssrc/blerg/Welcome.js | 16 +++++++++--- 3 files changed, 59 insertions(+), 12 deletions(-) diff --git a/www/css/blerg.css b/www/css/blerg.css index b99c134..eb34757 100644 --- a/www/css/blerg.css +++ b/www/css/blerg.css @@ -152,7 +152,7 @@ h1, h2, h3 { } .blerg-main { - padding: 15pt 15pt 20pt 15pt; + padding: 15pt 15pt 0 15pt; } .signup-button { @@ -291,27 +291,62 @@ h1, h2, h3 { margin: 1em 0; } +.latest { + display: table; + margin: 0 auto; + border-spacing: 10px; + height: 600px; +} + .latest h2 { font-size: 16pt; + margin-top: 0; +} + +.latest-scroller { + max-height: 600px; + padding: 12px; + overflow-y: auto; +} + +.latest-posts { + display: table-cell; + border: 2px solid #E6E6E6; + color: #4C4C4C; + width: 850px; +} + +.latest-posts .record { + font-size: 12pt; + margin: 10px 0; } .latest-tags { - text-align: center; + display: table-cell; + border: 2px solid #E6E6E6; + background-color: #FAE3FC; line-height: 2em; + width: 480px; } .latest-tags a { margin: 0 0.75em; } -.latest-posts { - height: 184pt; - overflow: hidden; +@media screen and (min-width: 1400px) { + .latest { width: 1340px; } } -.latest-posts .record { - font-size: 12pt; - margin: 8pt 0; +@media screen and (max-width: 1100px) { + .latest { display: block; } + .latest-posts { + display: block; + width: auto; + margin-right: 0; + overflow: auto; + height: auto; + } + .latest-tags { display: block; width: auto; } } .author { @@ -364,6 +399,7 @@ table.help td { } footer { + clear: both; margin: 15pt; font-size: small; color: #333; diff --git a/www/development.html b/www/development.html index 86c2403..6a5601a 100644 --- a/www/development.html +++ b/www/development.html @@ -17,5 +17,8 @@ + diff --git a/www/jssrc/blerg/Welcome.js b/www/jssrc/blerg/Welcome.js index aff858f..6b7f2ad 100644 --- a/www/jssrc/blerg/Welcome.js +++ b/www/jssrc/blerg/Welcome.js @@ -20,10 +20,18 @@ enyo.kind({ {style: "clear: both;"}, {name: "contentBox", allowHtml: true}, {classes: "latest", components: [ - {tag: "h2", content: "Latest posts"}, - {name: "latestPosts", classes: "latest-posts", onmouseover: "pauseTicker", onmouseout: "startTicker"}, - {tag: "h2", content: "Latest tags"}, - {name: "latestTags", classes: "latest-tags"} + {classes: "latest-posts", components: [ + {classes: "latest-scroller", components: [ + {tag: "h2", content: "Latest posts"}, + {name: "latestPosts", onmouseover: "pauseTicker", onmouseout: "startTicker"} + ]} + ]}, + {classes: "latest-tags", components: [ + {classes: "latest-scroller", components: [ + {tag: "h2", content: "Latest tags"}, + {name: "latestTags"} + ]} + ]} ]} ], create: function() { -- 2.25.1 From 2703bbeff27955ceb6354e4e34b09b0169eb4465 Mon Sep 17 00:00:00 2001 From: Chip Black Date: Sun, 17 Nov 2013 15:07:01 -0800 Subject: [PATCH 10/16] Upgrade to Enyo 2.2 --- www/jssrc/blerg/API.js | 151 +++++++++++++++++++++++------------------ www/jssrc/enyo | 2 +- www/jssrc/lib/onyx | 2 +- 3 files changed, 86 insertions(+), 69 deletions(-) diff --git a/www/jssrc/blerg/API.js b/www/jssrc/blerg/API.js index 95cdbcd..908c213 100644 --- a/www/jssrc/blerg/API.js +++ b/www/jssrc/blerg/API.js @@ -35,29 +35,34 @@ enyo.kind({ signup: function(username, password) { var req = new enyo.Ajax({ url: baseURL + '/create', - method: 'POST' + method: 'POST', + postBody: { + username: username, + password: password, + } }); - req.response(function(inSender, inResponse) { + req.response(this, function(inSender, inResponse) { if (inResponse.status == 'success') { this.bubble('onSignupSuccess', {username: username}); } else { this.bubble('onSignupFailure', {username: username}); } - }.bind(this)); - req.error(function() { + }); + req.error(this, function() { this.bubble('onSignupFailure', {username: username}); - }.bind(this)); - req.go(enyo.Ajax.objectToQuery({ - username: username, - password: password, - })); + }); + req.go(); }, login: function(username, password) { var req = new enyo.Ajax({ url: baseURL + '/login', - method: 'POST' + method: 'POST', + postBody: { + username: username, + password: password + } }); - req.response(function(inSender, inResponse) { + req.response(this, function(inSender, inResponse) { if (inResponse.status == 'success') { blerg.API.loggedIn = true; blerg.API.username = username; @@ -67,44 +72,50 @@ enyo.kind({ enyo.setCookie('username', '', {"Max-Age": 0}); this.bubble('onLoginFailed'); } - }.bind(this)); - req.go(enyo.Ajax.objectToQuery({ - username: username, - password: password - })); + }); + req.error(this, function() { + enyo.setCookie('username', '', {"Max-Age": 0}); + this.bubble('onLoginFailed'); + }); + req.go(); }, logout: function() { var req = new enyo.Ajax({ url: baseURL + '/logout', - method: 'POST' + method: 'POST', + postBody: { + username: blerg.API.username + } }); - req.response(function(inSender, inResponse) { + req.response(this, function(inSender, inResponse) { blerg.API.loggedIn = false; enyo.setCookie('auth', '', {"Max-Age": 0}); this.bubble('onLogoutSuccessful'); - }.bind(this)); - req.go(enyo.Ajax.objectToQuery({ - username: blerg.API.username - })); + }); + req.go(); enyo.setCookie('username', '', {"Max-Age": 0}); }, changePassword: function(oldpassword, newpassword) { var req = new enyo.Ajax({ url: baseURL + '/passwd', - method: 'POST' + method: 'POST', + postBody: { + username: blerg.API.username, + password: oldpassword, + new_password: newpassword + } }); - req.response(function(inSender, inResponse) { + req.response(this, function(inSender, inResponse) { if (inResponse.status == 'success') { this.bubble('onPasswordChangeSuccessful'); } else { this.bubble('onPasswordChangeFailed'); } - }.bind(this)); - req.go(enyo.Ajax.objectToQuery({ - username: blerg.API.username, - password: oldpassword, - new_password: newpassword - })); + }); + req.error(this, function() { + this.bubble('onPasswordChangeFailed'); + }); + req.go(); }, loadUserRecords: function(username, from ,to) { var url; @@ -168,14 +179,15 @@ enyo.kind({ var req = new enyo.Ajax({ url: baseURL + '/feedinfo', - method: 'POST' + method: 'POST', + postBody: { + username: blerg.API.username + } }); - req.response(function(inSender, inResponse) { + req.response(this, function(inSender, inResponse) { this.bubble('onFeedInfo', inResponse); - }.bind(this)); - req.go(enyo.Ajax.objectToQuery({ - username: blerg.API.username - })); + }); + req.go(); }, loadFeed: function() { if (!blerg.API.loggedIn) @@ -183,69 +195,77 @@ enyo.kind({ var req = new enyo.Ajax({ url: baseURL + '/feed', - method: 'POST' + method: 'POST', + postBody: { + username: blerg.API.username + } }); - req.response(function(inSender, inResponse) { + req.response(this, function(inSender, inResponse) { this.bubble('onItemsLoaded', { type: "feed", entries: inResponse }); - }.bind(this)); - req.go(enyo.Ajax.objectToQuery({ - username: blerg.API.username - })); + }); + req.go(); }, getSubscriptionStatus: function(username) { var req = new enyo.Ajax({ url: baseURL + '/feedinfo/' + username, - method: 'POST' + method: 'POST', + postBody: { + username: blerg.API.username + } }); - req.response(function(inSender, inResponse) { + req.response(this, function(inSender, inResponse) { this.bubble('onSubscriptionStatus', { username: username, subscribed: inResponse.subscribed }); - }.bind(this)); - req.go(enyo.Ajax.objectToQuery({ - username: blerg.API.username - })); + }); + req.go(); }, subscribe: function(username) { var req = new enyo.Ajax({ url: baseURL + '/subscribe/' + username, - method: 'POST' + method: 'POST', + postBody: { + username: blerg.API.username + } }); - req.response(function(inSender, inResponse) { + req.response(this, function(inSender, inResponse) { this.bubble('onSubscriptionStatus', { username: username, subscribed: inResponse.status == "success" }); - }.bind(this)); - req.go(enyo.Ajax.objectToQuery({ - username: blerg.API.username - })); + }); + req.go(); }, unsubscribe: function(username) { var req = new enyo.Ajax({ url: baseURL + '/unsubscribe/' + username, - method: 'POST' + method: 'POST', + postBody: { + username: blerg.API.username + } }); - req.response(function(inSender, inResponse) { + req.response(this, function(inSender, inResponse) { this.bubble('onSubscriptionStatus', { username: username, subscribed: inResponse.status != "success" }); - }.bind(this)); - req.go(enyo.Ajax.objectToQuery({ - username: blerg.API.username - })); + }); + req.go(); }, post: function(data) { var req = new enyo.Ajax({ url: baseURL + '/put', - method: 'POST' + method: 'POST', + postBody: { + username: blerg.API.username, + data: data + } }); - req.response(function(inSender, inResponse) { + req.response(this, function(inSender, inResponse) { if (inResponse && inResponse.status == 'success') { this.bubble('onPostSuccessful', { username: blerg.API.username, @@ -257,10 +277,7 @@ enyo.kind({ data: data }); } - }.bind(this)); - req.go(enyo.Ajax.objectToQuery({ - username: blerg.API.username, - data: data - })); + }); + req.go(); } }); diff --git a/www/jssrc/enyo b/www/jssrc/enyo index c3a4965..ad50ee2 160000 --- a/www/jssrc/enyo +++ b/www/jssrc/enyo @@ -1 +1 @@ -Subproject commit c3a49650ad03f65e9c270bf95256d94debe38519 +Subproject commit ad50ee2de0a568a4826c11f931a7aa209c309161 diff --git a/www/jssrc/lib/onyx b/www/jssrc/lib/onyx index e5873bc..f00190a 160000 --- a/www/jssrc/lib/onyx +++ b/www/jssrc/lib/onyx @@ -1 +1 @@ -Subproject commit e5873bca7ba5111f58cf99fb5d66fb17d5a5bbce +Subproject commit f00190a2dbc04fcc92bc689865dbfcae5f7bca88 -- 2.25.1 From 950ab7653cf70c585ecf5d35cdad92d277495b6c Mon Sep 17 00:00:00 2001 From: Chip Black Date: Sun, 17 Nov 2013 15:09:11 -0800 Subject: [PATCH 11/16] Fix for going to your account after posting --- www/jssrc/blerg/Post.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/www/jssrc/blerg/Post.js b/www/jssrc/blerg/Post.js index de01c86..c1b889c 100644 --- a/www/jssrc/blerg/Post.js +++ b/www/jssrc/blerg/Post.js @@ -46,7 +46,8 @@ enyo.kind({ this.setData(''); this.closePost(); if (location.hash != '#' + blerg.API.username) { - qlink(blerg.API.username); + location.hash = '#' + blerg.API.username + this.bubble('onNavigate'); } else { this.bubble('onReload'); } -- 2.25.1 From c3a777f760bedf3f196571612a7f3a1b3c707dbf Mon Sep 17 00:00:00 2001 From: Chip Black Date: Sun, 17 Nov 2013 15:13:27 -0800 Subject: [PATCH 12/16] Fix qlink handling in Firefox --- www/jssrc/blerg/Util.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/www/jssrc/blerg/Util.js b/www/jssrc/blerg/Util.js index 2734b36..18f3169 100644 --- a/www/jssrc/blerg/Util.js +++ b/www/jssrc/blerg/Util.js @@ -3,9 +3,9 @@ blerg = window.blerg || {}; blerg.Util = {}; // Dirty, terrible shim for rewritten links below -blerg.Util.qlink = function() { +blerg.Util.qlink = function(ev) { try { - location.href = event.target.href; + location.href = ev.target.href; } catch(e) { } enyo.$.blerg.bubble('onNavigate'); return false; @@ -82,8 +82,8 @@ blerg.Util.blergFormat = function(text) { l = l.replace(/([^\w\\]|^)\*(\w[^*]*)\*(\W|$)/g, '$1$2$3'); // Turn refs and tags into links - l = l.replace(/(\s|^)#([A-Za-z0-9_-]+)/g, '$1#$2'); - l = l.replace(/(\s|^)@([A-Za-z0-9_-]+)(\/\d+)?/g, '$1@$2'); + l = l.replace(/(\s|^)#([A-Za-z0-9_-]+)/g, '$1#$2'); + l = l.replace(/(\s|^)@([A-Za-z0-9_-]+)(\/\d+)?/g, '$1@$2'); // Create lists when lines begin with * if (l[0] == '*') { -- 2.25.1 From 1a21466c7e3f8c18c4c35df56c270546ae8e6434 Mon Sep 17 00:00:00 2001 From: Chip Black Date: Sun, 17 Nov 2013 15:14:17 -0800 Subject: [PATCH 13/16] Make new page layout responsive; fix ticker --- www/css/blerg.css | 27 +++++++++++++++++++++++---- www/jssrc/blerg/Welcome.js | 21 ++++++++++++++------- 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/www/css/blerg.css b/www/css/blerg.css index eb34757..9149194 100644 --- a/www/css/blerg.css +++ b/www/css/blerg.css @@ -295,7 +295,6 @@ h1, h2, h3 { display: table; margin: 0 auto; border-spacing: 10px; - height: 600px; } .latest h2 { @@ -304,7 +303,7 @@ h1, h2, h3 { } .latest-scroller { - max-height: 600px; + height: 600px; padding: 12px; overflow-y: auto; } @@ -338,15 +337,35 @@ h1, h2, h3 { } @media screen and (max-width: 1100px) { - .latest { display: block; } + .latest { + display: block; + margin-top: 15px; + } .latest-posts { display: block; width: auto; margin-right: 0; overflow: auto; + } + .latest-tags { + display: block; + width: auto; + margin-top: 10px; + } + .latest-tags .latest-scroller { + height: auto; + } +} + +@media screen and (max-width: 800px) { + .latest-posts, .latest-tags { + border: none; + background-color: inherit; + } + .latest-scroller { height: auto; + padding: 0; } - .latest-tags { display: block; width: auto; } } .author { diff --git a/www/jssrc/blerg/Welcome.js b/www/jssrc/blerg/Welcome.js index 6b7f2ad..ece3d6f 100644 --- a/www/jssrc/blerg/Welcome.js +++ b/www/jssrc/blerg/Welcome.js @@ -21,9 +21,9 @@ enyo.kind({ {name: "contentBox", allowHtml: true}, {classes: "latest", components: [ {classes: "latest-posts", components: [ - {classes: "latest-scroller", components: [ + {name: "latestPostsScroller", classes: "latest-scroller", onmouseover: "pauseTicker", onmouseout: "startTicker", components: [ {tag: "h2", content: "Latest posts"}, - {name: "latestPosts", onmouseover: "pauseTicker", onmouseout: "startTicker"} + {name: "latestPosts"} ]} ]}, {classes: "latest-tags", components: [ @@ -87,10 +87,17 @@ enyo.kind({ req.go(); }, startTickerCycle: function() { - this.tickerTimeout = setTimeout(function() { - this.$.latestPosts.node.scrollTop = 0; - this.startTicker(); - }.bind(this), 2500); + var starter = function() { + if (this.$.latestPostsScroller.hasNode()) { + var n = this.$.latestPostsScroller.node; + if (n.scrollTop >= n.scrollHeight - n.clientHeight) + n.scrollTop = 0; + this.startTicker(); + } else { + this.tickerTimeout = setTimeout(starter, 1000); + } + }.bind(this) + this.tickerTimeout = setTimeout(starter, 2500); }, startTicker: function() { if (this.tickerInterval) @@ -108,7 +115,7 @@ enyo.kind({ this.tickerInterval = null; }, ticker: function() { - var n = this.$.latestPosts.node; + var n = this.$.latestPostsScroller.node; if (n.scrollTop < n.scrollHeight - n.clientHeight) { n.scrollTop += 2; } else { -- 2.25.1 From 0085ebfed447d3e7a828eb691a78c5ccc2c21a8c Mon Sep 17 00:00:00 2001 From: Chip Black Date: Sun, 17 Nov 2013 15:25:09 -0800 Subject: [PATCH 14/16] Handle empty responses and errors for tag listings --- www/jssrc/blerg/API.js | 12 ++++++++++-- www/jssrc/blerg/Pager.js | 14 +++++++++----- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/www/jssrc/blerg/API.js b/www/jssrc/blerg/API.js index 908c213..986ac09 100644 --- a/www/jssrc/blerg/API.js +++ b/www/jssrc/blerg/API.js @@ -163,14 +163,22 @@ enyo.kind({ var req = new enyo.Ajax({ url: url }); - req.response(function(inSender, inResponse) { + req.response(this, function(inSender, inResponse) { this.bubble('onItemsLoaded', { type: 'tag', tagType: type, tag: tag, entries: inResponse }); - }.bind(this)); + }); + req.error(this, function() { + this.bubble('onItemsLoaded', { + type: 'tag', + tagType: type, + tag: tag, + entries: [] + }); + }); req.go(); }, getFeedInfo: function() { diff --git a/www/jssrc/blerg/Pager.js b/www/jssrc/blerg/Pager.js index 92f6f4c..f311d1f 100644 --- a/www/jssrc/blerg/Pager.js +++ b/www/jssrc/blerg/Pager.js @@ -8,11 +8,15 @@ enyo.kind({ {name: "spinner", kind: "OldSchoolSpinner", showing: false} ], addItems: function(items) { - this.$.records.createComponents(items, {kind: this.listKind}); - for (var i = 0; i < items.length; i++) { - var r = parseInt(items[i].record); - if (r < this.lastRecord || this.lastRecord == null) - this.lastRecord = r; + if (items.length > 0) { + this.$.records.createComponents(items, {kind: this.listKind}); + for (var i = 0; i < items.length; i++) { + var r = parseInt(items[i].record); + if (r < this.lastRecord || this.lastRecord == null) + this.lastRecord = r; + } + } else { + this.$.records.createComponent({content: "No items"}); } this.$.records.render(); this.stopLoadAnimation(); -- 2.25.1 From 15f8a303bfc30ec592e2045fc994437132645456 Mon Sep 17 00:00:00 2001 From: Chip Black Date: Sun, 17 Nov 2013 15:27:55 -0800 Subject: [PATCH 15/16] Fix the rest of the enyo.Ajax instances to use new bind style --- www/jssrc/blerg/API.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/www/jssrc/blerg/API.js b/www/jssrc/blerg/API.js index 986ac09..cd85745 100644 --- a/www/jssrc/blerg/API.js +++ b/www/jssrc/blerg/API.js @@ -128,7 +128,7 @@ enyo.kind({ var req = new enyo.Ajax({ url: url }); - req.response(function(inSender, inResponse) { + req.response(this, function(inSender, inResponse) { this.bubble('onItemsLoaded', { type: 'user', username: username, @@ -136,13 +136,13 @@ enyo.kind({ to: to, entries: inResponse }); - }.bind(this)); - req.error(function(inSender, inResponse) { + }); + req.error(this, function(inSender, inResponse) { if (inResponse == 404) this.bubble('onUserNotFound'); else this.bubble('onAPIError', {response: inResponse}); - }.bind(this)); + }); req.go(); }, loadTagRecords: function(type, tag) { -- 2.25.1 From 0595c4ad4f349efc7d907b5bc4ad774c231f2588 Mon Sep 17 00:00:00 2001 From: Chip Black Date: Mon, 18 Nov 2013 03:11:38 -0600 Subject: [PATCH 16/16] Changelog for 1.8.2 --- www/doc/changelog.html | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/www/doc/changelog.html b/www/doc/changelog.html index 378372e..0e54aa7 100644 --- a/www/doc/changelog.html +++ b/www/doc/changelog.html @@ -11,6 +11,23 @@ The intent of this changelog is to give an overview of the major changes and fixes made to Blërg. For a detailed changelog, see the git log. +

Version 1.8.2 - released Monday, November 18th, 2013

+ +

Features(?) Added

+
    +
  • Updated frontpage style to better scale to different screen sizes, +and maybe even look better.
  • +
  • Upgraded to Enyo 2.2.
  • +
+ +

Bugs Squashed

+
    +
  • After posting, you are now redirected to your user page. This was +intended behavior, but broken for the past few releases.
  • +
  • Fix clicking on internal hash/user references in Firefox.
  • +
  • Properly handle nonexistent/empty hash/user pages.
  • +
+

Version 1.8.1 - released Sunday, July 2, 2013

Features Added

-- 2.25.1