// vim: tabstop=4 shiftwidth=4 noexpandtab #include #include #include #include // important for getopt #include #include #include #define DEFAULT_PROFILE_PATH_APPENDIX "/.config/xbot/profile.ini" struct xmpp_job_t { char *message; char *recipient_jid; char *sender_jid; char *sender_pwd; xmpp_ctx_t *ctx; uint8_t log_level; }; void parse_cli_args(int argc, char **argv, struct xmpp_job_t *job, char **cfg_path); void read_xmpp_profile(char *cfg_path, struct xmpp_job_t *job); void send_message(struct xmpp_job_t *job); void conn_handler( xmpp_conn_t *const conn, const xmpp_conn_event_t status, const int error, xmpp_stream_error_t *const stream_error, void *const userdata ); int main(int argc, char **argv) { // create some pointers struct xmpp_job_t job; job.log_level = 0; char *profile_path = NULL; // parse CLI args, read profile and execute message sending parse_cli_args(argc, argv, &job, &profile_path); read_xmpp_profile(profile_path, &job); send_message(&job); // free memory if(job.message != NULL)free(job.message); if(job.recipient_jid != NULL)free(job.recipient_jid); if(job.sender_jid != NULL)free(job.sender_jid); if(job.sender_pwd != NULL)free(job.sender_pwd); if(profile_path != NULL)free(profile_path); return 0; } void parse_cli_args(int argc, char **argv, struct xmpp_job_t *job, char **cfg_path) { int option; while((option=getopt(argc, argv, "m:j:p:d")) != -1) { switch(option) { case 'm': job->message = (char *) malloc((strlen(optarg) + 1)*sizeof(char)); strcpy(job->message, optarg); break; case 'j': job->recipient_jid = (char *) malloc((strlen(optarg) + 1)*sizeof(char)); strcpy(job->recipient_jid, optarg); break; case 'p': *cfg_path = (char *) malloc((strlen(optarg) + 1)*sizeof(char)); strcpy(*cfg_path, optarg); break; case 'd': job->log_level = 1; break; } } if(job->message == NULL || job->recipient_jid == NULL) { printf("You have to provide a message with the '-m' option and a target jid with the '-j' option!\n"); exit(1); } if(*cfg_path == NULL) { char *homedir = getenv("HOME"); *cfg_path = malloc((strlen(homedir) + strlen(DEFAULT_PROFILE_PATH_APPENDIX) + 1)*sizeof(char)); strcpy(*cfg_path, homedir); strcat(*cfg_path, DEFAULT_PROFILE_PATH_APPENDIX); } if (job->log_level) { printf("message = '%s'\ntarget_jid = '%s'\nprofile_path = '%s'\nlog_level = '%i'\n", job->message, job->recipient_jid, *cfg_path, job->log_level); } } void read_xmpp_profile(char *cfg_path, struct xmpp_job_t *job) { dictionary *profile = iniparser_load(cfg_path); if(profile == NULL) { printf("Could not parse %s\n", cfg_path); exit(1); } job->sender_jid = (char *) iniparser_getstring(profile, "xbot:my_jabber_id", NULL); job->sender_pwd = (char *) iniparser_getstring(profile, "xbot:password", NULL); if (job->sender_jid == NULL || job->sender_pwd == NULL) { printf("Profile '%s' must have section 'xbot' and keys 'my_jabber_id' and 'password' configured!\n", cfg_path); exit(1); } if (job->log_level) { printf("sender_jid = '%s'\n", job->sender_jid); printf("sender_pwd = '%s'\n", job->sender_pwd); } } void send_message(struct xmpp_job_t *job) { // setup some pointers and variables xmpp_conn_t *conn; xmpp_log_t *log; long flags = 0; flags |= XMPP_CONN_FLAG_MANDATORY_TLS; // force transport encryption xmpp_initialize(); // init libstrophe (xmpp library) if (job->log_level) { log = xmpp_get_default_logger(XMPP_LEVEL_DEBUG); // create xmpp logger with high log level } else { log = xmpp_get_default_logger(XMPP_LEVEL_ERROR); // create xmpp logger with low log level } job->ctx = xmpp_ctx_new(NULL, log); // create xmpp context // create xmpp connection, set own jabber id and password and connect conn = xmpp_conn_new(job->ctx); xmpp_conn_set_flags(conn, flags); xmpp_conn_set_jid(conn, job->sender_jid); xmpp_conn_set_pass(conn, job->sender_pwd); xmpp_connect_client(conn, NULL, 0, conn_handler, job); xmpp_run(job->ctx); // event loop - conn_handler will trigger exit xmpp_conn_release(conn); // cleanup xmpp_ctx_free(job->ctx); xmpp_shutdown(); } void conn_handler( xmpp_conn_t *const conn, const xmpp_conn_event_t status, const int error, xmpp_stream_error_t *const stream_error, void *const userdata ) { struct xmpp_job_t *job = (struct xmpp_job_t *)userdata; int secured; (void)error; (void)stream_error; if(status == XMPP_CONN_CONNECT) { if (job->log_level)fprintf(stderr, "DEBUG: connected\n"); secured = xmpp_conn_is_secured(conn); if (job->log_level)fprintf(stderr, "DEBUG: connection is %s.\n", secured ? "secured" : "NOT secured"); xmpp_stanza_t * stanza = xmpp_message_new(job->ctx, "chat", job->recipient_jid, "31757b032065e0c1a2f97253f23c2e2d1a1c8f40"); xmpp_stanza_set_from(stanza, job->sender_jid); xmpp_message_set_body(stanza, job->message); xmpp_send(conn, stanza); xmpp_stanza_release(stanza); xmpp_disconnect(conn); } else { if (job->log_level)fprintf(stderr, "DEBUG: disconnected\n"); xmpp_stop(job->ctx); } }