"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "db.c" between
mairix-0.23.tar.gz and mairix-0.24.tar.gz

About: mairix is a program for indexing and searching email messages stored in maildir, MH or mbox folders.

db.c  (mairix-0.23):db.c  (mairix-0.24)
skipping to change at line 31 skipping to change at line 31
*/ */
/* Handle complete database */ /* Handle complete database */
#include "mairix.h" #include "mairix.h"
#include "reader.h" #include "reader.h"
#include <ctype.h> #include <ctype.h>
#include <assert.h> #include <assert.h>
#include <sys/time.h> #include <sys/time.h>
#include <unistd.h> #include <unistd.h>
#include "imapinterface.h"
struct sortable_token {/*{{{*/ struct sortable_token {/*{{{*/
char *text; char *text;
int index; int index;
}; };
/*}}}*/ /*}}}*/
static int compare_sortable_tokens(const void *a, const void *b)/*{{{*/ static int compare_sortable_tokens(const void *a, const void *b)/*{{{*/
{ {
const struct sortable_token *aa = (const struct sortable_token *) a; const struct sortable_token *aa = (const struct sortable_token *) a;
const struct sortable_token *bb = (const struct sortable_token *) b; const struct sortable_token *bb = (const struct sortable_token *) b;
skipping to change at line 137 skipping to change at line 138
const char **aa = (const char **) a; const char **aa = (const char **) a;
const char **bb = (const char **) b; const char **bb = (const char **) b;
return strcmp(*aa, *bb); return strcmp(*aa, *bb);
} }
/*}}}*/ /*}}}*/
static void check_message_path_integrity(struct database *db)/*{{{*/ static void check_message_path_integrity(struct database *db)/*{{{*/
{ {
/* TODO : for now only checks integrity of non-mbox paths. */ /* TODO : for now only checks integrity of non-mbox paths. */
/* Check there are no duplicates */ /* Check there are no duplicates */
int i; int i;
int n; int n, imap_n;
int has_duplicate = 0; int has_duplicate = 0;
char **paths; char **paths, **imaps;
paths = new_array(char *, db->n_msgs); paths = new_array(char *, db->n_msgs);
for (i=0, n=0; i<db->n_msgs; i++) { imaps = new_array(char *, db->n_msgs);
for (i=0, n=0, imap_n=0; i<db->n_msgs; i++) {
switch (db->type[i]) { switch (db->type[i]) {
case MTY_DEAD: case MTY_DEAD:
case MTY_MBOX: case MTY_MBOX:
break; break;
case MTY_FILE: case MTY_FILE:
paths[n++] = db->msgs[i].src.mpf.path; paths[n++] = db->msgs[i].src.mpf.path;
break; break;
case MTY_IMAP:
imaps[imap_n++] = db->msgs[i].src.mpf.path;
break;
} }
} }
qsort(paths, n, sizeof(char *), compare_strings); qsort(paths, n, sizeof(char *), compare_strings);
qsort(imaps, imap_n, sizeof(char *), compare_strings);
for (i=1; i<n; i++) { for (i=1; i<n; i++) {
if (!strcmp(paths[i-1], paths[i])) { if (!strcmp(paths[i-1], paths[i])) {
fprintf(stderr, "Path <%s> repeated\n", paths[i]); fprintf(stderr, "Path <%s> repeated\n", paths[i]);
has_duplicate = 1; has_duplicate = 1;
} }
} }
for (i=1; i<imap_n; i++) {
if (!strcmp(imaps[i-1], imaps[i])) {
fprintf(stderr, "IMAP message <%s> repeated\n", imaps[i]);
has_duplicate = 1;
}
}
fflush(stderr); fflush(stderr);
assert(!has_duplicate); assert(!has_duplicate);
free(paths); free(paths);
free(imaps);
return; return;
} }
/*}}}*/ /*}}}*/
void check_database_integrity(struct database *db)/*{{{*/ void check_database_integrity(struct database *db)/*{{{*/
{ {
if (verbose) fprintf(stderr, "Checking message path integrity\n"); if (verbose) fprintf(stderr, "Checking message path integrity\n");
check_message_path_integrity(db); check_message_path_integrity(db);
/* Just check encoding chains for now */ /* Just check encoding chains for now */
if (verbose) fprintf(stderr, "Checking to\n"); if (verbose) fprintf(stderr, "Checking to\n");
skipping to change at line 244 skipping to change at line 257
free_toktable2(db->msg_ids); free_toktable2(db->msg_ids);
if (db->msgs) { if (db->msgs) {
for (i=0; i<db->n_msgs; i++) { for (i=0; i<db->n_msgs; i++) {
switch (db->type[i]) { switch (db->type[i]) {
case MTY_DEAD: case MTY_DEAD:
break; break;
case MTY_MBOX: case MTY_MBOX:
break; break;
case MTY_FILE: case MTY_FILE:
case MTY_IMAP:
assert(db->msgs[i].src.mpf.path); assert(db->msgs[i].src.mpf.path);
free(db->msgs[i].src.mpf.path); free(db->msgs[i].src.mpf.path);
break; break;
} }
} }
free(db->msgs); free(db->msgs);
free(db->type); free(db->type);
} }
free(db); free(db);
skipping to change at line 472 skipping to change at line 486
switch (rd_msg_type(input, i)) { switch (rd_msg_type(input, i)) {
case DB_MSG_DEAD: case DB_MSG_DEAD:
result->type[i] = MTY_DEAD; result->type[i] = MTY_DEAD;
break; break;
case DB_MSG_FILE: case DB_MSG_FILE:
result->type[i] = MTY_FILE; result->type[i] = MTY_FILE;
result->msgs[i].src.mpf.path = new_string(input->data + input->path_offs ets[i]); result->msgs[i].src.mpf.path = new_string(input->data + input->path_offs ets[i]);
result->msgs[i].src.mpf.mtime = input->mtime_table[i]; result->msgs[i].src.mpf.mtime = input->mtime_table[i];
result->msgs[i].src.mpf.size = input->size_table[i]; result->msgs[i].src.mpf.size = input->size_table[i];
break; break;
case DB_MSG_IMAP:
result->type[i] = MTY_IMAP;
result->msgs[i].src.mpf.path = new_string(input->data + input->path_offs
ets[i]);
result->msgs[i].src.mpf.mtime = 0;
result->msgs[i].src.mpf.size = 0;
break;
case DB_MSG_MBOX: case DB_MSG_MBOX:
{ {
unsigned int mbi, msgi; unsigned int mbi, msgi;
int n; int n;
struct mbox *mb; struct mbox *mb;
result->type[i] = MTY_MBOX; result->type[i] = MTY_MBOX;
decode_mbox_indices(input->path_offsets[i], &mbi, &msgi); decode_mbox_indices(input->path_offsets[i], &mbi, &msgi);
result->msgs[i].src.mbox.file_index = mbi; result->msgs[i].src.mbox.file_index = mbi;
mb = &result->mboxen[mbi]; mb = &result->mboxen[mbi];
assert(mb->n_so_far == msgi); assert(mb->n_so_far == msgi);
skipping to change at line 716 skipping to change at line 736
case 'R': m->replied = 1; break; case 'R': m->replied = 1; break;
case 'S': m->seen = 1; break; case 'S': m->seen = 1; break;
default: break; default: break;
} }
p++; p++;
} }
} }
} }
} }
/*}}}*/ /*}}}*/
static void scan_new_messages(struct database *db, int start_at)/*{{{*/ static void scan_new_messages(struct database *db, int start_at, struct imap_ll *imapc)/*{{{*/
{ {
int i; int i;
for (i=start_at; i<db->n_msgs; i++) { for (i=start_at; i<db->n_msgs; i++) {
struct rfc822 *msg = NULL; struct rfc822 *msg = NULL;
int len = strlen(db->msgs[i].src.mpf.path); int len = strlen(db->msgs[i].src.mpf.path);
if (len > 10 && !strcmp(db->msgs[i].src.mpf.path + len - 11, "/.gitignore")) if (len > 10 && !strcmp(db->msgs[i].src.mpf.path + len - 11, "/.gitignore"))
continue; continue;
switch (db->type[i]) { switch (db->type[i]) {
case MTY_DEAD: case MTY_DEAD:
assert(0); assert(0);
break; break;
case MTY_MBOX: case MTY_MBOX:
assert(0); /* Should never get here - mbox messages are scanned elsewher e. */ assert(0); /* Should never get here - mbox messages are scanned elsewher e. */
break; break;
case MTY_FILE: case MTY_FILE:
if (verbose) fprintf(stderr, "Scanning <%s>\n", db->msgs[i].src.mpf.path ); if (verbose) fprintf(stderr, "Scanning <%s>\n", db->msgs[i].src.mpf.path );
msg = make_rfc822(db->msgs[i].src.mpf.path); msg = make_rfc822(db->msgs[i].src.mpf.path);
break; break;
case MTY_IMAP:
if (verbose) fprintf(stderr, "Scanning IMAP <%s>\n", db->msgs[i].src.mpf
.path);
msg = make_rfc822_from_imap(db->msgs[i].src.mpf.path, imapc);
break;
} }
if(msg) if(msg)
{ {
db->msgs[i].date = msg->hdrs.date; db->msgs[i].date = msg->hdrs.date;
scan_maildir_flags(&db->msgs[i]); scan_maildir_flags(&db->msgs[i]);
tokenise_message(i, db, msg); tokenise_message(i, db, msg);
free_rfc822(msg); free_rfc822(msg);
} }
else else
fprintf(stderr, "Skipping %s (could not parse message)\n", db->msgs[i].src .mpf.path); fprintf(stderr, "Skipping %s (could not parse message)\n", db->msgs[i].src .mpf.path);
skipping to change at line 787 skipping to change at line 811
} }
/*}}}*/ /*}}}*/
static void find_threading(struct database *db)/*{{{*/ static void find_threading(struct database *db)/*{{{*/
{ {
/* ix is a table mapping path array index to the lowest path array index that /* ix is a table mapping path array index to the lowest path array index that
* is known to share at least one message ID in its hdrs somewhere (i.e. they * is known to share at least one message ID in its hdrs somewhere (i.e. they
* must be in the same thread) */ * must be in the same thread) */
int *ix; int *ix;
int i, m, np, nm, sm; int i, m, np, sm;
int next_tid; int next_tid;
np = db->n_msgs; np = db->n_msgs;
nm = db->msg_ids->n;
sm = db->msg_ids->size; sm = db->msg_ids->size;
ix = new_array(int, np); ix = new_array(int, np);
for (i=0; i<np; i++) { for (i=0; i<np; i++) {
ix[i] = i; /* default - every message in a thread of its own */ ix[i] = i; /* default - every message in a thread of its own */
} }
for (m=0; m<sm; m++) { for (m=0; m<sm; m++) {
struct token2 *tok = db->msg_ids->tokens[m]; struct token2 *tok = db->msg_ids->tokens[m];
if (tok) { if (tok) {
skipping to change at line 848 skipping to change at line 871
db->msgs[i].tid = next_tid++; db->msgs[i].tid = next_tid++;
} else { } else {
db->msgs[i].tid = db->msgs[ix[i]].tid; db->msgs[i].tid = db->msgs[ix[i]].tid;
} }
} }
free(ix); free(ix);
return; return;
} }
/*}}}*/ /*}}}*/
static int lookup_msgpath(struct msgpath *sorted_paths, int n_msgs, char *key)/* {{{*/ static int lookup_msgpath(struct msgpath *sorted_paths, int n_msgs, char *key, e num message_type type)/*{{{*/
{ {
/* Implement bisection search */ /* Implement bisection search */
int l, h, m, r; int l, h, m, r;
l = 0, h = n_msgs; l = 0, h = n_msgs;
m = -1; m = -1;
while (h > l) { while (h > l) {
m = (h + l) >> 1; m = (h + l) >> 1;
/* Should only get called on 'file' type messages - TBC */ /* Should only get called on 'file' type messages - TBC */
r = strcmp(sorted_paths[m].src.mpf.path, key); if (sorted_paths[m].type < type) {
r = -1;
} else if (sorted_paths[m].type > type) {
r = 1;
} else {
r = strcmp(sorted_paths[m].src.mpf.path, key);
}
if (r == 0) break; if (r == 0) break;
if (l == m) return -1; if (l == m) return -1;
if (r > 0) h = m; if (r > 0) h = m;
else l = m; else l = m;
} }
return m; return m;
} }
/*}}}*/ /*}}}*/
void maybe_grow_message_arrays(struct database *db)/*{{{*/ void maybe_grow_message_arrays(struct database *db)/*{{{*/
{ {
skipping to change at line 879 skipping to change at line 908
if (db->max_msgs <= 128) { if (db->max_msgs <= 128) {
db->max_msgs = 256; db->max_msgs = 256;
} else { } else {
db->max_msgs += (db->max_msgs >> 1); db->max_msgs += (db->max_msgs >> 1);
} }
db->msgs = grow_array(struct msgpath, db->max_msgs, db->msgs); db->msgs = grow_array(struct msgpath, db->max_msgs, db->msgs);
db->type = grow_array(enum message_type, db->max_msgs, db->type); db->type = grow_array(enum message_type, db->max_msgs, db->type);
} }
} }
/*}}}*/ /*}}}*/
static void add_msg_path(struct database *db, char *path, time_t mtime, size_t m essage_size)/*{{{*/ static void add_msg_path(struct database *db, char *path, time_t mtime, size_t m essage_size, enum message_type type)/*{{{*/
{ {
maybe_grow_message_arrays(db); maybe_grow_message_arrays(db);
db->type[db->n_msgs] = MTY_FILE; db->type[db->n_msgs] = type;
db->msgs[db->n_msgs].src.mpf.path = new_string(path); db->msgs[db->n_msgs].src.mpf.path = new_string(path);
db->msgs[db->n_msgs].src.mpf.mtime = mtime; db->msgs[db->n_msgs].src.mpf.mtime = mtime;
db->msgs[db->n_msgs].src.mpf.size = message_size; db->msgs[db->n_msgs].src.mpf.size = message_size;
++db->n_msgs; ++db->n_msgs;
} }
/*}}}*/ /*}}}*/
enum stat_result {/*{{{*/
STAT_RESULT_BAD,
STAT_RESULT_FILE,
STAT_RESULT_DIR,
};
/*}}}*/
static int do_stat(struct msgpath *mp)/*{{{*/ static int do_stat(struct msgpath *mp)/*{{{*/
{ {
struct stat sb; struct stat sb;
int status; int status;
if (mp->type == MTY_IMAP) {
mp->src.mpf.mtime = 0;
mp->src.mpf.size = 0;
return STAT_RESULT_FILE;
}
status = stat(mp->src.mpf.path, &sb); status = stat(mp->src.mpf.path, &sb);
if ((status < 0) || if (status < 0) {
!S_ISREG(sb.st_mode)) { return STAT_RESULT_BAD;
return 0; }
} else { if (S_ISREG(sb.st_mode)) {
mp->src.mpf.mtime = sb.st_mtime; mp->src.mpf.mtime = sb.st_mtime;
mp->src.mpf.size = sb.st_size; mp->src.mpf.size = sb.st_size;
return 1; return STAT_RESULT_FILE;
} else if (S_ISDIR(sb.st_mode)) {
return STAT_RESULT_DIR;
} }
return STAT_RESULT_BAD;
} }
/*}}}*/ /*}}}*/
int update_database(struct database *db, struct msgpath *sorted_paths, int n_msg s, int do_fast_index)/*{{{*/ int update_database(struct database *db, struct msgpath *sorted_paths, int n_msg s, int do_fast_index, struct imap_ll *imapc)/*{{{*/
{ {
/* The incoming list must be sorted into order, to make binary searching /* The incoming list must be sorted into order, to make binary searching
* possible. We search for each existing path in the incoming sorted array. * possible. We search for each existing path in the incoming sorted array.
* If the date differs, or the file no longer exist, the existing database * If the date differs, or the file no longer exist, the existing database
* entry for that file is nulled. (These are only recovered if the database * entry for that file is nulled. (These are only recovered if the database
* is actively compressed.) If the date differed, a new entry for the file * is actively compressed.) If the date differed, a new entry for the file
* is put at the end of the list. Similarly, any new file goes at the end. * is put at the end of the list. Similarly, any new file goes at the end.
* These new entries are all rescanned to find tokens and add them to the * These new entries are all rescanned to find tokens and add them to the
* database. */ * database. */
char *file_in_db, *file_in_new_list; char *file_in_db, *file_in_new_list;
int matched_index; int matched_index;
int i, new_entries_start_at; int i, new_entries_start_at;
int any_new, n_newly_pruned, n_already_dead; int any_new, n_newly_pruned, n_already_dead;
int status;
file_in_db = new_array(char, n_msgs); file_in_db = new_array(char, n_msgs);
file_in_new_list = new_array(char, db->n_msgs); file_in_new_list = new_array(char, db->n_msgs);
bzero(file_in_db, n_msgs); bzero(file_in_db, n_msgs);
bzero(file_in_new_list, db->n_msgs); bzero(file_in_new_list, db->n_msgs);
n_already_dead = 0; n_already_dead = 0;
n_newly_pruned = 0; n_newly_pruned = 0;
for (i=0; i<db->n_msgs; i++) { for (i=0; i<db->n_msgs; i++) {
switch (db->type[i]) { switch (db->type[i]) {
case MTY_FILE: case MTY_FILE:
matched_index = lookup_msgpath(sorted_paths, n_msgs, db->msgs[i].src.mpf .path); matched_index = lookup_msgpath(sorted_paths, n_msgs, db->msgs[i].src.mpf .path, MTY_FILE);
if (matched_index >= 0) { if (matched_index >= 0) {
if (do_fast_index) { if (do_fast_index) {
/* Assume the presence of a matching path is good enough without /* Assume the presence of a matching path is good enough without
* even bothering to stat the file that's there now. */ * even bothering to stat the file that's there now. */
file_in_db[matched_index] = 1; file_in_db[matched_index] = 1;
file_in_new_list[i] = 1; file_in_new_list[i] = 1;
} else { } else {
status = do_stat(sorted_paths + matched_index); switch (do_stat(sorted_paths + matched_index)) {
if (status) { case STAT_RESULT_FILE:
if (sorted_paths[matched_index].src.mpf.mtime == db->msgs[i].src.m if (sorted_paths[matched_index].src.mpf.mtime == db->msgs[i].src
pf.mtime) { .mpf.mtime) {
/* Treat stale files as though the path has changed. */ /* Treat stale files as though the path has changed. */
file_in_db[matched_index] = 1; file_in_db[matched_index] = 1;
file_in_new_list[i] = 1; file_in_new_list[i] = 1;
} }
} else { break;
/* This path will get treated as dead, and be re-stated below. default:
* When that stat fails, the path won't get added to the db. */ /* This path will get treated as dead, and be re-stated below.
* When that stat fails, the path won't get added to the db. */
break;
} }
} }
} }
break; break;
case MTY_IMAP:
matched_index = lookup_msgpath(sorted_paths, n_msgs, db->msgs[i].src.mpf
.path, MTY_IMAP);
if (matched_index >= 0) {
file_in_db[matched_index] = 1;
file_in_new_list[i] = 1;
}
break;
case MTY_MBOX: case MTY_MBOX:
/* Nothing to do on this pass. */ /* Nothing to do on this pass. */
break; break;
case MTY_DEAD: case MTY_DEAD:
break; break;
} }
} }
/* Add new entries to database */ /* Add new entries to database */
new_entries_start_at = db->n_msgs; new_entries_start_at = db->n_msgs;
for (i=0; i<db->n_msgs; i++) { for (i=0; i<db->n_msgs; i++) {
/* Weed dead entries */ /* Weed dead entries */
switch (db->type[i]) { switch (db->type[i]) {
case MTY_FILE: case MTY_FILE:
case MTY_IMAP:
if (!file_in_new_list[i]) { if (!file_in_new_list[i]) {
free(db->msgs[i].src.mpf.path); free(db->msgs[i].src.mpf.path);
db->msgs[i].src.mpf.path = NULL; db->msgs[i].src.mpf.path = NULL;
db->type[i] = MTY_DEAD; db->type[i] = MTY_DEAD;
++n_newly_pruned; ++n_newly_pruned;
} }
break; break;
case MTY_MBOX: case MTY_MBOX:
{ {
int msg_index, file_index, number_valid; int msg_index, file_index, number_valid;
skipping to change at line 1006 skipping to change at line 1059
} }
} }
if (verbose) { if (verbose) {
fprintf(stderr, "%d newly dead messages, %d messages now dead in total\n", n _newly_pruned, n_newly_pruned+n_already_dead); fprintf(stderr, "%d newly dead messages, %d messages now dead in total\n", n _newly_pruned, n_newly_pruned+n_already_dead);
} }
any_new = 0; any_new = 0;
for (i=0; i<n_msgs; i++) { for (i=0; i<n_msgs; i++) {
if (!file_in_db[i]) { if (!file_in_db[i]) {
int status;
any_new = 1; any_new = 1;
/* The 'sorted_paths' array is only used for file-per-message folders. */ /* The 'sorted_paths' array is only used for file-per-message folders. */
status = do_stat(sorted_paths + i); switch(do_stat(sorted_paths + i)) {
if (status) { case STAT_RESULT_FILE:
/* We only add files that could be successfully stat()'d as regular /* We only add files that could be successfully stat()'d as regular
* files. */ * files. */
add_msg_path(db, sorted_paths[i].src.mpf.path, sorted_paths[i].src.mpf.m add_msg_path(db, sorted_paths[i].src.mpf.path, sorted_paths[i].src.mpf
time, sorted_paths[i].src.mpf.size); .mtime, sorted_paths[i].src.mpf.size, sorted_paths[i].type);
} else { break;
fprintf(stderr, "Cannot add '%s' to database; stat() failed\n", sorted_p case STAT_RESULT_DIR:
aths[i].src.mpf.path); if (sorted_paths[i].source_ft == FT_MH) {
/* With MH, something that looks like a message but is a
directory is actually a subfolder with a numeric name.
Don't warn about it */
break;
}
/* In all other cases, treat any non-regular-file the same
and warn about it. */
/* fallthrough */
default:
fprintf(stderr, "Cannot add '%s' to database; stat() failed\n", sorted
_paths[i].src.mpf.path);
break;
} }
} }
} }
if (any_new) { if (any_new) {
scan_new_messages(db, new_entries_start_at); scan_new_messages(db, new_entries_start_at, imapc);
} }
/* Add newly found mbox messages. */ /* Add newly found mbox messages. */
any_new |= add_mbox_messages(db); any_new |= add_mbox_messages(db);
if (any_new) { if (any_new) {
find_threading(db); find_threading(db);
} else { } else {
if (verbose) fprintf(stderr, "No new messages found\n"); if (verbose) fprintf(stderr, "No new messages found\n");
} }
skipping to change at line 1255 skipping to change at line 1319
fprintf(stderr, "Culling dead messages\n"); fprintf(stderr, "Culling dead messages\n");
} }
n_old = db->n_msgs; n_old = db->n_msgs;
new_idx = new_array(int, n_old); new_idx = new_array(int, n_old);
for (i=0, j=0; i<n_old; i++) { for (i=0, j=0; i<n_old; i++) {
switch (db->type[i]) { switch (db->type[i]) {
case MTY_FILE: case MTY_FILE:
case MTY_MBOX: case MTY_MBOX:
case MTY_IMAP:
new_idx[i] = j++; new_idx[i] = j++;
break; break;
case MTY_DEAD: case MTY_DEAD:
new_idx[i] = -1; new_idx[i] = -1;
any_culled = 1; any_culled = 1;
break; break;
} }
} }
recode_toktable(db->to, new_idx); recode_toktable(db->to, new_idx);
skipping to change at line 1279 skipping to change at line 1344
recode_toktable(db->attachment_name, new_idx); recode_toktable(db->attachment_name, new_idx);
recode_toktable2(db->msg_ids, new_idx); recode_toktable2(db->msg_ids, new_idx);
/* And crunch down the filename table */ /* And crunch down the filename table */
for (i=0, j=0; i<n_old; i++) { for (i=0, j=0; i<n_old; i++) {
switch (db->type[i]) { switch (db->type[i]) {
case MTY_DEAD: case MTY_DEAD:
break; break;
case MTY_FILE: case MTY_FILE:
case MTY_MBOX: case MTY_MBOX:
case MTY_IMAP:
if (i > j) { if (i > j) {
db->msgs[j] = db->msgs[i]; db->msgs[j] = db->msgs[i];
db->type[j] = db->type[i]; db->type[j] = db->type[i];
} }
j++; j++;
break; break;
} }
} }
db->n_msgs = j; db->n_msgs = j;
 End of changes. 34 change blocks. 
40 lines changed or deleted 109 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)