コード例 #1
0
ファイル: friendlist.c プロジェクト: privacee/toxic
int load_blocklist(char *path)
{
    if (path == NULL)
        return -1;

    FILE *fp = fopen(path, "rb");

    if (fp == NULL)
        return -1;

    off_t len = file_size(path);

    if (len == 0) {
        fclose(fp);
        return -1;
    }

    char *data = malloc(len);

    if (data == NULL) {
        fclose(fp);
        exit_toxic_err("Failed in load_blocklist", FATALERR_MEMORY);
    }

    if (fread(data, len, 1, fp) != 1) {
        fclose(fp);
        free(data);
        return -1;
    }

    if (len % sizeof(BlockedFriend) != 0) {
        fclose(fp);
        free(data);
        return -1;
    }

    int num = len / sizeof(BlockedFriend);
    Blocked.max_idx = num;
    realloc_blocklist(num);

    int i;

    for (i = 0; i < num; ++i) {
        memset(&Blocked.list[i], 0, sizeof(BlockedFriend));

        BlockedFriend tmp;
        memcpy(&tmp, data + i * sizeof(BlockedFriend), sizeof(BlockedFriend));
        Blocked.list[i].active = true;
        Blocked.list[i].num = i;
        Blocked.list[i].namelength = ntohs(tmp.namelength);
        memcpy(Blocked.list[i].name, tmp.name, Blocked.list[i].namelength + 1);
        memcpy(Blocked.list[i].pub_key, tmp.pub_key, TOX_PUBLIC_KEY_SIZE);

        uint8_t lastonline[sizeof(uint64_t)];
        memcpy(lastonline, &tmp.last_on, sizeof(uint64_t));
        net_to_host(lastonline, sizeof(uint64_t));
        memcpy(&Blocked.list[i].last_on, lastonline, sizeof(uint64_t));

        ++Blocked.num_blocked;
    }

    free(data);
    fclose(fp);
    sort_blocklist_index();

    return 0;
}
コード例 #2
0
/* Returns a new Tox object on success.
 * If object fails to initialize the toxic process will terminate.
 */
static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, TOX_ERR_NEW *new_err)
{
    Tox *m = NULL;

    FILE *fp = fopen(data_path, "rb");

    if (fp != NULL) {   /* Data file exists */
        off_t len = file_size(data_path);

        if (len == 0) {
            fclose(fp);
            exit_toxic_err("failed in load_tox", FATALERR_FILEOP);
        }

        char data[len];

        if (fread(data, sizeof(data), 1, fp) != 1) {
            fclose(fp);
            exit_toxic_err("failed in load_tox", FATALERR_FILEOP);
        }

        bool is_encrypted = tox_is_data_encrypted((uint8_t *) data);

        /* attempt to encrypt an already encrypted data file */
        if (arg_opts.encrypt_data && is_encrypted) {
            fclose(fp);
            exit_toxic_err("failed in load_tox", FATALERR_ENCRYPT);
        }

        if (arg_opts.unencrypt_data && is_encrypted)
            queue_init_message("Data file '%s' has been unencrypted", data_path);
        else if (arg_opts.unencrypt_data)
            queue_init_message("Warning: passed --unencrypt-data option with unencrypted data file '%s'", data_path);

        if (is_encrypted) {
            if (!arg_opts.unencrypt_data)
                user_password.data_is_encrypted = true;

            size_t pwlen = 0;
            int pweval = user_settings->password_eval[0];

            if (!pweval) {
                system("clear");   // TODO: is this portable?
                printf("Enter password (q to quit) ");
            }

            size_t plain_len = len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
            char plain[plain_len];

            while (true) {
                if (pweval) {
                    pwlen = password_eval(user_password.pass, sizeof(user_password.pass));
                } else {
                    pwlen = password_prompt(user_password.pass, sizeof(user_password.pass));
                }

                user_password.len = pwlen;

                if (strcasecmp(user_password.pass, "q") == 0) {
                    fclose(fp);
                    exit(0);
                }

                if (pwlen < MIN_PASSWORD_LEN) {
                    system("clear");
                    sleep(1);
                    printf("Invalid password. Try again. ");
                    pweval = 0;
                    continue;
                }

                TOX_ERR_DECRYPTION pwerr;
                tox_pass_decrypt((uint8_t *) data, len, (uint8_t *) user_password.pass, pwlen,
                                 (uint8_t *) plain, &pwerr);

                if (pwerr == TOX_ERR_DECRYPTION_OK) {
                    tox_opts->savedata_type = TOX_SAVEDATA_TYPE_TOX_SAVE;
                    tox_opts->savedata_data = (uint8_t *) plain;
                    tox_opts->savedata_length = plain_len;

                    m = tox_new(tox_opts, new_err);

                    if (m == NULL) {
                        fclose(fp);
                        return NULL;
                    }

                    break;
                } else if (pwerr == TOX_ERR_DECRYPTION_FAILED) {
                    system("clear");
                    sleep(1);
                    printf("Invalid password. Try again. ");
                    pweval = 0;
                } else {
                    fclose(fp);
                    exit_toxic_err("tox_pass_decrypt() failed", pwerr);
                }
            }
        } else {   /* data is not encrypted */
            tox_opts->savedata_type = TOX_SAVEDATA_TYPE_TOX_SAVE;
            tox_opts->savedata_data = (uint8_t *) data;
            tox_opts->savedata_length = len;

            m = tox_new(tox_opts, new_err);

            if (m == NULL) {
                fclose(fp);
                return NULL;
            }
        }

        fclose(fp);
    } else {   /* Data file does not/should not exist */
        if (file_exists(data_path))
            exit_toxic_err("failed in load_tox", FATALERR_FILEOP);

        tox_opts->savedata_type = TOX_SAVEDATA_TYPE_NONE;

        m = tox_new(tox_opts, new_err);

        if (m == NULL)
            return NULL;

        if (store_data(m, data_path) == -1)
            exit_toxic_err("failed in load_tox", FATALERR_FILEOP);
    }

    return m;
}
コード例 #3
0
static void parse_args(int argc, char *argv[])
{
    set_default_opts();

    static struct option long_opts[] = {
        {"file", required_argument, 0, 'f'},
        {"ipv4", no_argument, 0, '4'},
        {"debug", no_argument, 0, 'b'},
        {"default-locale", no_argument, 0, 'd'},
        {"config", required_argument, 0, 'c'},
        {"encrypt-data", no_argument, 0, 'e'},
        {"nodes", required_argument, 0, 'n'},
        {"help", no_argument, 0, 'h'},
        {"noconnect", no_argument, 0, 'o'},
        {"namelist", required_argument, 0, 'r'},
        {"force-tcp", no_argument, 0, 't'},
        {"tcp-server", required_argument, 0, 'T'},
        {"SOCKS5-proxy", required_argument, 0, 'p'},
        {"HTTP-proxy", required_argument, 0, 'P'},
        {"unencrypt-data", no_argument, 0, 'u'},
        {NULL, no_argument, NULL, 0},
    };

    const char *opts_str = "4bdehotuxc:f:n:r:p:P:T:";
    int opt, indexptr;
    long int port = 0;

    while ((opt = getopt_long(argc, argv, opts_str, long_opts, &indexptr)) != -1) {
        switch (opt) {
            case '4':
                arg_opts.use_ipv4 = 1;
                break;

            case 'b':
                arg_opts.debug = 1;
                queue_init_message("stderr enabled");
                break;

            case 'c':
                snprintf(arg_opts.config_path, sizeof(arg_opts.config_path), "%s", optarg);

                if (!file_exists(arg_opts.config_path))
                    queue_init_message("Config file not found");

                break;

            case 'd':
                arg_opts.default_locale = 1;
                queue_init_message("Using default POSIX locale");
                break;

            case 'e':
                arg_opts.encrypt_data = 1;
                break;

            case 'f':
                arg_opts.use_custom_data = 1;

                if (DATA_FILE)
                    free(DATA_FILE);

                if (BLOCK_FILE)
                    free(BLOCK_FILE);

                DATA_FILE = malloc(strlen(optarg) + 1);
                strcpy(DATA_FILE, optarg);

                if (DATA_FILE == NULL)
                    exit_toxic_err("failed in parse_args", FATALERR_MEMORY);

                BLOCK_FILE = malloc(strlen(optarg) + strlen("-blocklist") + 1);

                if (BLOCK_FILE == NULL)
                    exit_toxic_err("failed in parse_args", FATALERR_MEMORY);

                strcpy(BLOCK_FILE, optarg);
                strcat(BLOCK_FILE, "-blocklist");

                queue_init_message("Using '%s' data file", DATA_FILE);

                break;

            case 'n':
                snprintf(arg_opts.nodes_path, sizeof(arg_opts.nodes_path), "%s", optarg);
                break;

            case 'o':
                arg_opts.no_connect = 1;
                queue_init_message("DHT disabled");
                break;

            case 'p':
                arg_opts.proxy_type = TOX_PROXY_TYPE_SOCKS5;
                snprintf(arg_opts.proxy_address, sizeof(arg_opts.proxy_address), "%s", optarg);

                if (++optind > argc || argv[optind - 1][0] == '-')
                    exit_toxic_err("Proxy error", FATALERR_PROXY);

                port = strtol(argv[optind - 1], NULL, 10);

                if (port <= 0 || port > MAX_PORT_RANGE)
                    exit_toxic_err("Proxy error", FATALERR_PROXY);

                arg_opts.proxy_port = port;
                break;

            case 'P':
                arg_opts.proxy_type = TOX_PROXY_TYPE_HTTP;
                snprintf(arg_opts.proxy_address, sizeof(arg_opts.proxy_address), "%s", optarg);

                if (++optind > argc || argv[optind - 1][0] == '-')
                    exit_toxic_err("Proxy error", FATALERR_PROXY);

                port = strtol(argv[optind - 1], NULL, 10);

                if (port <= 0 || port > MAX_PORT_RANGE)
                    exit_toxic_err("Proxy error", FATALERR_PROXY);

                arg_opts.proxy_port = port;
                break;

            case 'r':
                snprintf(arg_opts.nameserver_path, sizeof(arg_opts.nameserver_path), "%s", optarg);

                if (!file_exists(arg_opts.nameserver_path))
                    queue_init_message("nameserver list not found");

                break;

            case 't':
                arg_opts.force_tcp = 1;
                break;

            case 'T':
                port = strtol(optarg, NULL, 10);

                if (port <= 0 || port > MAX_PORT_RANGE)
                    port = 14191;

                arg_opts.tcp_port = port;
                break;

            case 'u':
                arg_opts.unencrypt_data = 1;
                break;

            case 'h':
            default:
                print_usage();
                exit(EXIT_SUCCESS);
        }
    }
}
コード例 #4
0
ファイル: toxic.c プロジェクト: prodigeni/toxic
int main(int argc, char *argv[])
{
    parse_args(argc, argv);
    /* Make sure all written files are read/writeable only by the current user. */
    umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
    signal(SIGINT, catch_SIGINT);
    int config_err = init_data_files();

    /* init user_settings struct and load settings from conf file */
    user_settings_ = calloc(1, sizeof(struct user_settings));

    if (user_settings_ == NULL)
        exit_toxic_err("failed in main", FATALERR_MEMORY);

    char *p = arg_opts.config_path[0] ? arg_opts.config_path : NULL;
    int settings_err = settings_load(user_settings_, p);

    Tox *m = init_tox(arg_opts.use_ipv4);
    init_term();

    if (m == NULL)
        exit_toxic_err("failed in main", FATALERR_NETWORKINIT);

    if (!arg_opts.ignore_data_file)
        load_data(m, DATA_FILE);

    prompt = init_windows(m);
    prompt_init_statusbar(prompt, m);

    /* thread for ncurses stuff */
    if (pthread_mutex_init(&Winthread.lock, NULL) != 0)
        exit_toxic_err("failed in main", FATALERR_MUTEX_INIT);

    if (pthread_create(&Winthread.tid, NULL, thread_winref, (void *) m) != 0)
        exit_toxic_err("failed in main", FATALERR_THREAD_CREATE);

#ifdef _AUDIO

    av = init_audio(prompt, m);


    set_primary_device(input, user_settings_->audio_in_dev);
    set_primary_device(output, user_settings_->audio_out_dev);
#elif _SOUND_NOTIFY
    if ( init_devices() == de_InternalError )
        line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to init devices");

#endif /* _AUDIO */
    
    init_notify(60, 3000);

#ifdef _SOUND_NOTIFY
    notify(prompt, self_log_in, 0);
#endif /* _SOUND_NOTIFY */
    
    const char *msg;

    if (config_err) {
        msg = "Unable to determine configuration directory. Defaulting to 'data' for data file...";
        line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, 0, msg);
    }

    if (settings_err == -1) {
        msg = "Failed to load user settings";
        line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, 0, msg);
    }

    uint64_t last_save = (uint64_t) time(NULL);

    while (true) {
        update_unix_time();
        do_toxic(m, prompt);
        uint64_t cur_time = get_unix_time();

        if (timed_out(last_save, cur_time, AUTOSAVE_FREQ)) {
            pthread_mutex_lock(&Winthread.lock);
            store_data(m, DATA_FILE);
            pthread_mutex_unlock(&Winthread.lock);

            last_save = cur_time;
        }

        usleep(40000);
    }

    return 0;
}
コード例 #5
0
int main(int argc, char **argv)
{
    parse_args(argc, argv);

    /* Use the -b flag to enable stderr */
    if (!arg_opts.debug)
        freopen("/dev/null", "w", stderr);

    if (arg_opts.encrypt_data && arg_opts.unencrypt_data) {
        arg_opts.encrypt_data = 0;
        arg_opts.unencrypt_data = 0;
        queue_init_message("Warning: Using --unencrypt-data and --encrypt-data simultaneously has no effect");
    }

    /* Make sure all written files are read/writeable only by the current user. */
    umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);

    init_default_data_files();

    bool datafile_exists = file_exists(DATA_FILE);

    if (!datafile_exists && !arg_opts.unencrypt_data)
        first_time_encrypt("Creating new data file. Would you like to encrypt it? Y/n (q to quit)");
    else if (arg_opts.encrypt_data)
        first_time_encrypt("Encrypt existing data file? Y/n (q to quit)");


    /* init user_settings struct and load settings from conf file */
    user_settings = calloc(1, sizeof(struct user_settings));

    if (user_settings == NULL)
        exit_toxic_err("failed in main", FATALERR_MEMORY);

    const char *p = arg_opts.config_path[0] ? arg_opts.config_path : NULL;

    if (settings_load(user_settings, p) == -1) {
        queue_init_message("Failed to load user settings");
    }

    int curl_init = curl_global_init(CURL_GLOBAL_ALL);
    int nameserver_ret = name_lookup_init(curl_init);

    if (nameserver_ret == -1) {
        queue_init_message("curl failed to initialize; name lookup service is disabled.");
    } else if (nameserver_ret == -2) {
        queue_init_message("Name lookup server list could not be found.");
    } else if (nameserver_ret == -3) {
        queue_init_message("Name lookup server list does not contain any valid entries.");
    }

#ifdef X11

    if (init_xtra(DnD_callback) == -1)
        queue_init_message("X failed to initialize");

#endif

    Tox *m = load_toxic(DATA_FILE);

    if (arg_opts.encrypt_data && !datafile_exists)
        arg_opts.encrypt_data = 0;


    init_term();

    prompt = init_windows(m);
    prompt_init_statusbar(prompt, m);

    /* thread for ncurses stuff */
    if (pthread_mutex_init(&Winthread.lock, NULL) != 0)
        exit_toxic_err("failed in main", FATALERR_MUTEX_INIT);

    if (pthread_create(&Winthread.tid, NULL, thread_winref, (void *) m) != 0)
        exit_toxic_err("failed in main", FATALERR_THREAD_CREATE);

    /* thread for message queue */
    if (pthread_create(&cqueue_thread.tid, NULL, thread_cqueue, (void *) m) != 0)
        exit_toxic_err("failed in main", FATALERR_THREAD_CREATE);

#ifdef AUDIO

    av = init_audio(prompt, m);

#ifdef VIDEO
    init_video(prompt, m);

#endif /* VIDEO */

    /* AV thread */
    if (pthread_create(&av_thread.tid, NULL, thread_av, (void *) av) != 0)
        exit_toxic_err("failed in main", FATALERR_THREAD_CREATE);

    set_primary_device(input, user_settings->audio_in_dev);
    set_primary_device(output, user_settings->audio_out_dev);

#elif SOUND_NOTIFY

    if ( init_devices() == de_InternalError )
        queue_init_message("Failed to init audio devices");

#endif /* AUDIO */

    init_notify(60, 3000);

    /* screen/tmux auto-away timer */
    if (init_mplex_away_timer(m) == -1)
        queue_init_message("Failed to init mplex auto-away.");

    int nodeslist_ret = load_DHT_nodeslist();

    if (nodeslist_ret != 0) {
        queue_init_message("DHT nodeslist failed to load (error %d)", nodeslist_ret);
    }

    pthread_mutex_lock(&Winthread.lock);
    print_init_messages(prompt);
    pthread_mutex_unlock(&Winthread.lock);

    cleanup_init_messages();

    /* set user avatar from config file. if no path is supplied tox_unset_avatar is called */
    char avatarstr[MAX_STR_SIZE];
    snprintf(avatarstr, sizeof(avatarstr), "/avatar \"%s\"", user_settings->avatar_path);
    execute(prompt->chatwin->history, prompt, m, avatarstr, GLOBAL_COMMAND_MODE);

    time_t last_save = get_unix_time();

    while (true) {
        do_toxic(m);

        time_t cur_time = get_unix_time();

        if (timed_out(last_save, AUTOSAVE_FREQ)) {
            pthread_mutex_lock(&Winthread.lock);

            if (store_data(m, DATA_FILE) != 0)
                line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, RED, "WARNING: Failed to save to data file");

            pthread_mutex_unlock(&Winthread.lock);

            last_save = cur_time;
        }

        usleep(tox_iteration_interval(m) * 1000);
    }

    return 0;
}
コード例 #6
0
ファイル: autocomplete.c プロジェクト: Encrypt/toxic
/* looks for all instances in list that begin with the last entered word in line according to pos,
   then fills line with the complete word. e.g. "Hello jo" would complete the line
   with "Hello john". If multiple matches, prints out all the matches and semi-completes line.

   list is a pointer to the list of strings being compared, n_items is the number of items
   in the list, and size is the size of each item in the list.

   Returns the difference between the old len and new len of line on success, -1 if error */
int complete_line(ToxWindow *self, const void *list, int n_items, int size)
{
    ChatContext *ctx = self->chatwin;

    if (ctx->pos <= 0 || ctx->len <= 0 || ctx->pos > ctx->len || ctx->len >= MAX_STR_SIZE || size > MAX_STR_SIZE)
        return -1;

    const char *L = (char *) list;
    const char *endchrs = " ";
    char ubuf[MAX_STR_SIZE];

    /* work with multibyte string copy of buf for simplicity */
    if (wcs_to_mbs_buf(ubuf, ctx->line, sizeof(ubuf)) == -1)
        return -1;

    /* TODO: generalize this */
    bool dir_search =    !strncmp(ubuf, "/sendfile", strlen("/sendfile"))
                      || !strncmp(ubuf, "/avatar", strlen("/avatar"));

    /* isolate substring from space behind pos to pos */
    char tmp[MAX_STR_SIZE];
    snprintf(tmp, sizeof(tmp), "%s", ubuf);
    tmp[ctx->pos] = '\0';

    const char *s = dir_search ? strchr(tmp, '\"') : strrchr(tmp, ' ');
    char *sub = calloc(1, strlen(ubuf) + 1);

    if (sub == NULL)
        exit_toxic_err("failed in complete_line", FATALERR_MEMORY);

    if (!s && !dir_search) {
        strcpy(sub, tmp);

        if (sub[0] != '/')
            endchrs = ": ";
    } else if (s) {
        strcpy(sub, &s[1]);

        if (dir_search) {
            int sub_len = strlen(sub);
            int si = char_rfind(sub, '/', sub_len);

            if (si || *sub == '/')
                memmove(sub, &sub[si + 1], sub_len - si);
        }
    }

    if (!sub[0]) {
        free(sub);
        return -1;
    }

    int s_len = strlen(sub);
    int n_matches = 0;
    char matches[n_items][MAX_STR_SIZE];
    int i = 0;

    /* put all list matches in matches array */
    for (i = 0; i < n_items; ++i) {
        char str[MAX_CMDNAME_SIZE + 1];
        snprintf(str, sizeof(str), "%s", &L[i * size]);

        if (strncasecmp(str, sub, s_len) == 0)
            strcpy(matches[n_matches++], str);
    }

    free(sub);

    if (!n_matches)
        return -1;

    if (!dir_search && n_matches > 1)
        print_matches(self, NULL, matches, n_matches, MAX_STR_SIZE);

    char match[MAX_STR_SIZE];
    size_t match_len = get_str_match(self, match, sizeof(match), matches, n_matches);

    if (match_len == 0) {
        return 0;
    }

    if (dir_search) {
        if (n_matches == 1)
            endchrs = char_rfind(match, '.', match_len) ? "\"" : "/";
        else
            endchrs = "";
    } else if (n_matches > 1) {
        endchrs = "";
    }

    /* put match in correct spot in buf and append endchars */
    int n_endchrs = strlen(endchrs);
    int strt = ctx->pos - s_len;
    int diff = match_len - s_len + n_endchrs;
    if (ctx->len + diff >= MAX_STR_SIZE)
        return -1;

    char tmpend[MAX_STR_SIZE];
    snprintf(tmpend, sizeof(tmpend), "%s", &ubuf[ctx->pos]);

    if (match_len + n_endchrs + strlen(tmpend) >= sizeof(ubuf)) {
        return -1;
    }

    strcpy(&ubuf[strt], match);
    strcpy(&ubuf[strt + match_len], endchrs);
    strcpy(&ubuf[strt + match_len + n_endchrs], tmpend);

    /* convert to widechar and copy back to original buf */
    wchar_t newbuf[MAX_STR_SIZE];

    if (mbs_to_wcs_buf(newbuf, ubuf, sizeof(newbuf) / sizeof(wchar_t)) == -1) {
        return -1;
    }

    wcscpy(ctx->line, newbuf);

    ctx->len += diff;
    ctx->pos += diff;

    return diff;
}
コード例 #7
0
ファイル: line_info.c プロジェクト: chu888chu888/toxic
/* creates new line_info line and puts it in the queue. 
   SYS_MSG lines may contain an arbitrary number of arguments for string formatting */
void line_info_add(ToxWindow *self, char *tmstmp, char *name1, char *name2, uint8_t type, uint8_t bold, 
                   uint8_t colour, const char *msg, ...)
{
    struct history *hst = self->chatwin->hst;
    struct line_info *new_line = calloc(1, sizeof(struct line_info));

    if (new_line == NULL)
        exit_toxic_err("failed in line_info_add", FATALERR_MEMORY);

    char frmt_msg[MAX_STR_SIZE] = {0};

    va_list args;
    va_start(args, msg);
    vsnprintf(frmt_msg, sizeof(frmt_msg), msg, args);
    va_end(args);

    int len = 1;     /* there will always be a newline */

    /* for type-specific formatting in print function */
    switch (type) {
        case ACTION:
        case CONNECTION:
            len += 3;
            break;

        case SYS_MSG:
            break;

        case PROMPT:
            ++len;
            break;

        default:
            len += 2;
            break;
    }

    if (frmt_msg[0]) {
        snprintf(new_line->msg, sizeof(new_line->msg), "%s", frmt_msg);
        len += strlen(new_line->msg);

        int i;

        for (i = 0; frmt_msg[i]; ++i) {
            if (frmt_msg[i] == '\n')
                ++new_line->newlines;
        }
    }

    if (tmstmp) {
        snprintf(new_line->timestamp, sizeof(new_line->timestamp), "%s", tmstmp);
        len += strlen(new_line->timestamp);
    }

    if (name1) {
        snprintf(new_line->name1, sizeof(new_line->name1), "%s", name1);
        len += strlen(new_line->name1);
    }

    if (name2) {
        snprintf(new_line->name2, sizeof(new_line->name2), "%s", name2);
        len += strlen(new_line->name2);
    }

    new_line->len = len;
    new_line->type = type;
    new_line->bold = bold;
    new_line->colour = colour;

    line_info_add_queue(hst, new_line);
}
コード例 #8
0
ファイル: chat.c プロジェクト: prodigeni/toxic
ToxWindow new_chat(Tox *m, int32_t friendnum)
{
    ToxWindow ret;
    memset(&ret, 0, sizeof(ret));

    ret.active = true;
    ret.is_chat = true;

    ret.onKey = &chat_onKey;
    ret.onDraw = &chat_onDraw;
    ret.onInit = &chat_onInit;
    ret.onMessage = &chat_onMessage;
    ret.onConnectionChange = &chat_onConnectionChange;
    ret.onTypingChange = & chat_onTypingChange;
    ret.onGroupInvite = &chat_onGroupInvite;
    ret.onNickChange = &chat_onNickChange;
    ret.onStatusChange = &chat_onStatusChange;
    ret.onStatusMessageChange = &chat_onStatusMessageChange;
    ret.onAction = &chat_onAction;
    ret.onFileSendRequest = &chat_onFileSendRequest;
    ret.onFileControl = &chat_onFileControl;
    ret.onFileData = &chat_onFileData;

#ifdef _AUDIO
    ret.onInvite = &chat_onInvite;
    ret.onRinging = &chat_onRinging;
    ret.onStarting = &chat_onStarting;
    ret.onEnding = &chat_onEnding;
    ret.onError = &chat_onError;
    ret.onStart = &chat_onStart;
    ret.onCancel = &chat_onCancel;
    ret.onReject = &chat_onReject;
    ret.onEnd = &chat_onEnd;
    ret.onRequestTimeout = &chat_onRequestTimeout;
    ret.onPeerTimeout = &chat_onPeerTimeout;
    
    ret.call_idx = -1;
    ret.device_selection[0] = ret.device_selection[1] = -1;
#endif /* _AUDIO */
    
#ifdef _SOUND_NOTIFY
    ret.active_sound = -1;
#endif /* _SOUND_NOTIFY */
    
    char nick[TOX_MAX_NAME_LENGTH];
    int n_len = get_nick_truncate(m, nick, friendnum);
    chat_set_window_name(&ret, nick, n_len);

    ChatContext *chatwin = calloc(1, sizeof(ChatContext));
    StatusBar *stb = calloc(1, sizeof(StatusBar));
    Help *help = calloc(1, sizeof(Help));

    if (stb == NULL || chatwin == NULL || help == NULL)
        exit_toxic_err("failed in new_chat", FATALERR_MEMORY);

    ret.chatwin = chatwin;
    ret.stb = stb;
    ret.help = help;

    ret.num = friendnum;

    return ret;
}
コード例 #9
0
ファイル: friendlist.c プロジェクト: prodigeni/toxic
int load_blocklist(char *path)
{
    if (path == NULL)
        return -1;

    FILE *fp = fopen(path, "rb");

    if (fp == NULL)
        return -1;

    fseek(fp, 0, SEEK_END);
    int len = ftell(fp);
    fseek(fp, 0, SEEK_SET);

    char *data = malloc(len);

    if (data == NULL) {            
        fclose(fp);
        exit_toxic_err("Failed in load_blocklist", FATALERR_MEMORY);
    }

    if (fread(data, len, 1, fp) != 1) {
        fclose(fp);
        free(data);
        return -1;
    }

    if (len % sizeof(BlockedFriend) != 0) {
        fclose(fp);
        free(data);
        return -1;
    }

    int num = len / sizeof(BlockedFriend);
    int i;

    for (i = 0; i < num; ++i) {
        BlockedFriend tmp;
        memcpy(&tmp, data + i * sizeof(BlockedFriend), sizeof(BlockedFriend));
        Blocked_Contacts.list[i].active = true;
        Blocked_Contacts.list[i].num = i;
        Blocked_Contacts.list[i].namelength = ntohs(tmp.namelength);
        memcpy(Blocked_Contacts.list[i].name, tmp.name, Blocked_Contacts.list[i].namelength + 1);
        memcpy(Blocked_Contacts.list[i].pub_key, tmp.pub_key, TOX_CLIENT_ID_SIZE);

        uint8_t lastonline[sizeof(uint64_t)];
        memcpy(lastonline, &tmp.last_on, sizeof(uint64_t));
        net_to_host(lastonline, sizeof(uint64_t));
        memcpy(&Blocked_Contacts.list[i].last_on, lastonline, sizeof(uint64_t));

        ++Blocked_Contacts.num_blocked;
    }

    Blocked_Contacts.max_index = i + 1;

    free(data);
    fclose(fp);
    sort_blocklist_index();

    return 0;
}
コード例 #10
0
ファイル: global_commands.c プロジェクト: selukov/toxic
void cmd_avatar(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{
    if (argc < 2) {
        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: No file path supplied.");
        return;
    }

    /* turns the avatar off */
    if (strlen(argv[1]) < 3) {
        tox_unset_avatar(m);
        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No avatar set.");
        return;
    }

    if (argv[1][0] != '\"') {
        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Path must be enclosed in quotes.");
        return;
    }

    /* remove opening and closing quotes */
    char path[MAX_STR_SIZE];
    snprintf(path, sizeof(path), "%s", &argv[1][1]);
    int len = strlen(path) - 1;
    path[len] = '\0';

    off_t sz = file_size(path);

    if (sz <= 8) {
        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: Invalid file.");
        return;
    }

    if (sz > TOX_AVATAR_MAX_DATA_LENGTH) {
        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: File is too large.");
        return;
    }

    FILE *fp = fopen(path, "rb");

    if (fp == NULL) {
        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: Could not open file.");
        return;
    }

    char PNG_signature[8] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};

    if (check_file_signature(PNG_signature, sizeof(PNG_signature), fp) != 0) {
        fclose(fp);
        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: File type not supported.");
        return;
    }

    char *avatar = malloc(sz);

    if (avatar == NULL)
        exit_toxic_err("Failed in set_avatar", FATALERR_MEMORY);

    if (fread(avatar, sz, 1, fp) != 1) {
        fclose(fp);
        free(avatar);
        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: Read fail.");
        return;
    }

    if (tox_set_avatar(m, TOX_AVATAR_FORMAT_PNG, (const uint8_t *) avatar, (uint32_t) sz) == -1)
        line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: Core error.");

    char filename[MAX_STR_SIZE];
    get_file_name(filename, sizeof(filename), path);
    line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Avatar set to '%s'", filename);

    fclose(fp);
    free(avatar);
}