static inline int ncurses_typingsend(const int len, const int first) { const char *sid = session_uid_get(ncurses_typing_win->session); const char *uid = get_uid(ncurses_typing_win->session, ncurses_typing_win->target); if (((first > 1) || (ncurses_typing_win->in_active)) && uid) return query_emit_id(NULL, PROTOCOL_TYPING_OUT, &sid, &uid, &len, &first); else return -1; }
static void logs_window_new(window_t *w) { const char *uid; if (!w->target || !w->session || w->id == WINDOW_CONTACTS_ID) /* XXX w->id in WINDOW_RESERVED_ID ??? */ return; uid = get_uid_any(w->session, w->target); /* XXX, do we really want/need to create log struct with invalid uid? XXX */ logs_log_new(NULL, session_uid_get(w->session), uid ? uid : w->target); }
static void logs_window_new(window_t *w) { const char *uid; if (!w->target || !w->session || w->id == 1000) return; uid = get_uid_any(w->session, w->target); /* XXX, do we really want/need to create log struct with invalid uid? XXX */ logs_log_new(NULL, session_uid_get(w->session), uid ? uid : w->target); }
/* kind = 0 for sent, 1 for toobig */ static void xmsg_unlink_dotfiles(session_t *s, const char *varname) { if (session_int_get(s, varname)) { const int kind = !xstrcasecmp(varname, "unlink_sent"); const int maxfs = session_int_get(s, "max_filesize"); const char *dfsuffix = session_get(s, "dotfile_suffix"); const char *dir = xmsg_dirfix(session_uid_get(s)+XMSG_UID_DIROFFSET); DIR *d; struct dirent *de; struct stat st, std; char *df, *dfd, *dp, *dpd; if (!dir || !(d = opendir(dir))) { xdebug("unable to open specified directory"); return; } df = xmalloc(xstrlen(dir) + NAME_MAX + 2); dfd = xmalloc(xstrlen(dir) + NAME_MAX + 3 + xstrlen(dfsuffix)); xstrcpy(df, dir); dp = df + xstrlen(df); *(dp++) = '/'; xstrcpy(dfd, df); dpd = dfd + xstrlen(dfd); *(dpd++) = '.'; while ((de = readdir(d))) { if (de->d_name[0] == '.') continue; if (xstrlen(de->d_name) > NAME_MAX) { xdebug2(DEBUG_ERROR, "Filename longer than NAME_MAX (%s), skipping.", de->d_name); continue; } xstrcpy(dp, de->d_name); xstrcpy(dpd, de->d_name); xstrcat(dpd, dfsuffix); if (!stat(df, &st) && !stat(dfd, &std) && ((!maxfs || (st.st_size < maxfs)) == kind)) { xdebug("removing %s", de->d_name); unlink(df); unlink(dfd); } } closedir(d); xfree(df); xfree(dfd); } }
static COMMAND(xmsg_connect) { if (session_connected_get(session)) { printq("already_connected", session_name(session)); return -1; } if (command_exec(NULL, session, "/session --lock", 0) == -1) return -1; if (xmsg_add_watch(session, session_uid_get(session)+XMSG_UID_DIROFFSET)) { print("conn_failed", format_find("xmsg_addwatch_failed"), session_name(session)); return -1; } session_status_set(session, EKG_STATUS_AVAIL); protocol_connected_emit(session); xmsg_iterate_dir(0, (void*) session); xmsg_timer_change(session, "rescan_timer"); return 0; }
static TIMER_SESSION(xmsg_iterate_dir) { const char *dir; DIR *d; struct dirent *de; int n = 0; const int maxn = session_int_get(s, "max_oneshot_files"); if (type || !s || !session_connected_get(s)) return -1; session_status_set(s, EKG_STATUS_AVAIL); if (!(dir = xmsg_dirfix(session_uid_get(s)+XMSG_UID_DIROFFSET)) || !(d = opendir(dir))) { xerr("unable to open specified directory"); return 0; } while ((de = readdir(d))) { if (!xmsg_handle_file(s, de->d_name)) n++; if ((maxn > 0) && n >= maxn) { const int i = session_int_get(s, "oneshot_resume_timer"); if ((i > 0) && timer_add_session(s, "o", i, 0, xmsg_iterate_dir)) xdebug("oneshot resume timer added"); session_status_set(s, EKG_STATUS_AWAY); break; } } closedir(d); xdebug("processed %d files", n); return 0; }
static void logs_buffer_raw_display(window_t *w) { char *line, **lines; logs_log_t *ll; int i, j, n, all = (config_logs_remind_number <= 0); if (!w || !w->session) return; if ((WINDOW_STATUS_ID == w->id) || (WINDOW_CONTACTS_ID == w->id) || (WINDOW_LASTLOG_ID ==w->id )) return; if (!(ll = logs_log_open(session_uid_get(w->session), w->target, TRUE))) return; if (!all) lines = g_new0(char *, config_logs_remind_number + 1); // read log n = 0; fseek(ll->file, 0, SEEK_SET); while ((line = read_file(ll->file, 0))) { ekg_fix_utf8(line); if (all) { time_t t = g_ascii_strtoll(line, &line, 10); if (t>0 && *line == ' ') line++; logs_print_window(w->session, w, line, t); } else { j = n % config_logs_remind_number; g_free(lines[j]); lines[j] = g_strdup(line); n++; } } if (all) { query_emit(NULL, "ui-window-refresh"); return; } ftruncate(fileno(ll->file), 0); // display and rewrite log w->lock++; for (i=0; i < config_logs_remind_number; i++, n++) { time_t t; j = n % config_logs_remind_number; if (!lines[j]) continue; fputs(lines[j], ll->file); fputc('\n', ll->file); t = g_ascii_strtoll(lines[j], &line, 10); if (t>0 && *line == ' ') line++; logs_print_window(w->session, w, line, t); } w->lock--; g_strfreev(lines); query_emit(NULL, "ui-window-refresh"); }
static int xmsg_handle_file(session_t *s, const char *fn) { const int nounlink = !session_int_get(s, "unlink_sent"); const int utb = session_int_get(s, "unlink_toobig"); const int maxfs = session_int_get(s, "max_filesize"); const char *dfsuffix = session_get(s, "dotfile_suffix"); char *namesep = (char*) session_get(s, "name_separator"); char *dir; int dirlen; char *msg = NULL; int err, fs; time_t ft = 0; if (*fn == '.') /* we're skipping ALL dotfiles */ return -1; dir = (char*) xmsg_dirfix(session_uid_get(s)+XMSG_UID_DIROFFSET); dirlen = xstrlen(dir); /* first check if buffer is long enough to fit the whole path for dotfile */ if (strlcpy(dir+dirlen+1, fn, PATH_MAX-dirlen-2-xstrlen(dfsuffix)) >= PATH_MAX-dirlen-2-xstrlen(dfsuffix)) xerr("Buffer too small for: fn = %s, len(fn) = %d, dirlen = %d, dfsuffixlen = %d", fn, xstrlen(fn), dirlen, xstrlen(dfsuffix)); /* then fill in middle part of path */ dir[dirlen] = '/'; /* and take a much closer look the file */ xdebug("s = %s, d = %s, fn = %s", session_uid_get(s), dir, fn); if ((err = xmsg_checkoutfile(dir, &msg, &fs, &ft, maxfs))) { if (err == EFBIG) { print((utb ? "xmsg_toobigrm" : "xmsg_toobig"), fn, session_name(s)); if (utb) { unlink(dir); return -1; } /* else we need to create the dotfile first */ } else if (err != ENOENT && err != EINVAL) return -1; } else if (!nounlink && (utb == (err == EFBIG))) unlink(dir); /* here: dir = dotf */ memmove(dir+dirlen+2, dir+dirlen+1, xstrlen(dir) - dirlen); dir[dirlen+1] = '.'; xstrcpy(dir+xstrlen(dir), dfsuffix); /* we've already checked whether it fits */ { struct stat st; int r; if (nounlink || !utb) { r = !(stat(dir, &st) || S_ISDIR(st.st_mode)); } else r = 0; if (err == ENOENT) { if (r) /* clean up stale dotfile */ unlink(dir); xfree(msg); return -1; } else if (r) { xfree(msg); /* XXX: I think that we rather shouldn't first read, then check if it is needed, at least for nounlink mode */ return -1; } else if ((nounlink && !(utb && err == EFBIG)) || (!utb && err == EFBIG)) close(open(dir, O_WRONLY|O_CREAT|O_TRUNC|O_NOFOLLOW, 0600)); } if (err == EFBIG) return -1; else if (err == EINVAL) xdebug("empty file, not submitting"); else { char *uid = xmalloc(strlen(fn) + 6); char *msgx = NULL; { const char *charset = session_get(s, "charset"); if (charset && (msgx = ekg_convert_string(msg, charset, NULL))) xfree(msg); else msgx = msg; } xstrcpy(uid, "xmsg:"); xstrcat(uid, fn); if (namesep) { char *p, *q = NULL; for (p = namesep; *p; p++) { char *r = xstrrchr(uid+XMSG_UID_DIROFFSET, *p); if (r > q) q = r; } if (q) *q = '\0'; } protocol_message_emit(s, uid, NULL, msgx, NULL, ft, EKG_MSGCLASS_CHAT, NULL, EKG_TRY_BEEP, 0); xfree(msgx); xfree(uid); } return 0; }