summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--api.c130
-rw-r--r--session.c120
-rw-r--r--session.h23
-rw-r--r--util.c36
-rw-r--r--util.h39
6 files changed, 352 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..d4b6daa
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,4 @@
+LDLIBS=-lcurl -ljson-c
+CFLAGS=-g -Wall
+
+api: api.o session.o util.o
diff --git a/api.c b/api.c
new file mode 100644
index 0000000..e5b802f
--- /dev/null
+++ b/api.c
@@ -0,0 +1,130 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <curl/curl.h>
+#include <json-c/json.h>
+#include "session.h"
+#include "util.h"
+
+/* logout: return 1 if success, 0 if failed */
+int matrix_logout(matrix_session *sess)
+{
+ char requrl[1000]; /* FIXME */
+ sprintf(requrl, "%s/_matrix/client/r0/logout?access_token=%s", sess->url, sess->token);
+ CURLcode res = _curl_post(sess->curl, requrl, "", NULL);
+ if (res == CURLE_OK)
+ return 1;
+ else
+ return 0;
+}
+
+json_object * matrix_joined_rooms(matrix_session *sess)
+{
+ char requrl[1000];
+ json_object *resp;
+ sprintf(requrl, "%s/_matrix/client/r0/joined_rooms?access_token=%s",
+ sess->url, sess->token);
+ _curl_get(sess->curl, requrl, &resp);
+ return resp;
+}
+
+const char * matrix_create_room(matrix_session *sess)
+{
+ char requrl[1000];
+ json_object *resp;
+
+ sprintf(requrl, "%s/_matrix/client/r0/createRoom?access_token=%s",
+ sess->url, sess->token);
+ _curl_post(sess->curl, requrl, "{\"preset\": \"private_chat\"}", &resp);
+ if (resp != NULL) {
+ const char *roomid = json_gets(resp, "room_id");
+ if (roomid) {
+ const char *r = copy_str(roomid);
+ json_object_put(resp);
+ return r;
+ }
+ }
+ json_object_put(resp);
+ return NULL;
+}
+
+const char * matrix_resolv_alias(matrix_session *sess, const char *alias)
+{
+ char requrl[1000];
+ json_object *resp;
+ const char *_alias = alias;
+ if (alias[0] == '#')
+ _alias = curl_easy_escape(sess->curl, alias, strlen(alias));
+
+ sprintf(requrl, "%s/_matrix/client/r0/directory/room/%s", sess->url, _alias);
+ if (_alias != alias)
+ curl_free(_alias);
+
+ _curl_get(sess->curl, requrl, &resp);
+ if (resp) {
+ const char *roomid = json_gets(resp, "room_id");
+ if (roomid) {
+ const char *r = copy_str(roomid);
+ json_object_put(resp);
+ return r;
+ }
+ }
+ json_object_put(resp);
+ return NULL;
+}
+
+int main()
+{
+ curl_global_init(CURL_GLOBAL_ALL);
+ char url[1000], user[1000], passwd[1000], token[1000];
+ scanf("%s%s%s", url, user, passwd);
+ matrix_session *sess = matrix_login_pass(url, user, passwd, "Matrix C Client");
+
+ if (sess) {
+ printf("hs: %s, mxid: %s, dev: %s, token: %s\n", sess->servername,
+ sess->mxid, sess->dev_id, sess->token);
+
+ /* store access token */
+ FILE *fp = fopen("credential.txt", "w");
+ fprintf(fp, "%s %s\n", url, sess->token);
+ fclose(fp);
+ } else {
+ puts("login error!\n");
+ }
+
+ strcpy(token, sess->token);
+ matrix_session_free(sess);
+
+ // scanf("%s%s", url, token);
+ sess = matrix_access_token(url, token);
+ if (sess) {
+ printf("I'm %s\n", sess->mxid);
+ } else {
+ puts("login error!\n");
+ }
+
+ json_object *joined_rooms = matrix_joined_rooms(sess);
+ printf("%s\n", json_object_to_json_string(joined_rooms));
+
+ const char *roomid = matrix_resolv_alias(sess, "#hello:my.domain.name");
+ if (roomid == NULL)
+ puts("fail to resolv #hello:my.domain.name");
+
+ free(roomid);
+
+ /* create a room */
+ roomid = matrix_create_room(sess);
+ if (roomid == NULL)
+ puts("fail to create room!");
+ else
+ printf("create room %s\n", roomid);
+
+ free(roomid);
+
+ if (matrix_logout(sess))
+ puts("logout!");
+
+ if (matrix_whoami(sess)) {
+ puts("error: not logged out!");
+ }
+}
diff --git a/session.c b/session.c
new file mode 100644
index 0000000..bd9deb0
--- /dev/null
+++ b/session.c
@@ -0,0 +1,120 @@
+#include "session.h"
+#include "util.h"
+
+matrix_session*
+matrix_session_new(const char *url)
+{
+ matrix_session *sess = (matrix_session*)malloc(sizeof(matrix_session));
+ memset(sess, 0, sizeof(matrix_session));
+ sess->curl = curl_easy_init();
+ if (sess->curl) {
+ sess->url = copy_str(url);
+ return sess;
+ } else {
+ free(sess);
+ return NULL;
+ }
+}
+
+#define SAFE_FREE(x) if (x) free(x);
+
+void
+matrix_session_free(matrix_session *sess)
+{
+ SAFE_FREE(sess->url);
+ SAFE_FREE(sess->servername);
+ SAFE_FREE(sess->mxid);
+ SAFE_FREE(sess->token);
+ SAFE_FREE(sess->dev_id);
+
+ curl_easy_cleanup(sess->curl);
+ free(sess);
+}
+
+matrix_session*
+matrix_login_pass(const char *url, const char *user, const char *passwd, const char *devname)
+{
+ CURLcode res;
+
+ matrix_session *sess = matrix_session_new(url);
+
+ json_object *reqobj = json_object_new_object();
+ char requrl[1000]; /* FIXME */
+ json_object *resp = NULL;
+
+ sprintf(requrl, "%s%s", url, "/_matrix/client/r0/login");
+
+ json_add_string(reqobj, "type", "m.login.password");
+ json_add_string(reqobj, "user", user);
+ json_add_string(reqobj, "password", passwd);
+ if (devname != NULL)
+ json_add_string(reqobj, "initial_device_display_name", devname);
+
+ res = _curl_post(sess->curl, requrl, json_object_to_json_string(reqobj), &resp);
+ json_object_put(reqobj);
+
+ /* save mxid, token, dev_id*/
+ if (resp != NULL) {
+ const char *mxid = json_gets(resp, "user_id");
+ const char *token = json_gets(resp, "access_token");
+ const char *devid = json_gets(resp, "device_id");
+ const char *hs = json_gets(resp, "home_server");
+
+ if (mxid && token && devid && hs) {
+ sess->mxid = copy_str(mxid);
+ sess->token = copy_str(token);
+ sess->dev_id = copy_str(devid);
+ sess->servername = copy_str(hs);
+ json_object_put(resp);
+ return sess;
+ } else {
+ json_object_put(resp);
+ matrix_session_free(sess);
+ return NULL;
+ }
+ }
+ return NULL;
+}
+
+matrix_session*
+matrix_access_token(const char *url, const char *token)
+{
+ matrix_session *sess = matrix_session_new(url);
+ sess->token = copy_str(token);
+ char *mxid = matrix_whoami(sess);
+
+ if (mxid) {
+ sess->mxid = mxid;
+ return sess;
+ } else {
+ matrix_session_free(sess);
+ return NULL;
+ }
+}
+
+/* return an alloc'd string of MXID */
+char *matrix_whoami(matrix_session *sess)
+{
+ char requrl[1000]; /* FIXME */
+ char *uid;
+ CURLcode res;
+ json_object *resp = NULL;
+
+ sprintf(requrl, "%s/_matrix/client/r0/account/whoami?access_token=%s",
+ sess->url, sess->token);
+ res = _curl_get(sess->curl, requrl, &resp);
+
+ if (resp != NULL) {
+ const char *mxid = json_gets(resp, "user_id");
+ if (mxid) {
+ uid = copy_str(mxid);
+ json_object_put(resp);
+ return uid;
+ } else {
+ json_object_put(resp);
+ return NULL;
+ }
+ } else {
+ return NULL;
+ }
+}
diff --git a/session.h b/session.h
new file mode 100644
index 0000000..53c0bc7
--- /dev/null
+++ b/session.h
@@ -0,0 +1,23 @@
+#ifndef MATRIX_CURL_SESSION_H
+#define MATRIX_CURL_SESSION_H
+
+#include <curl/curl.h>
+
+typedef struct
+{
+ CURL *curl;
+ char *url;
+ char *servername;
+ char *mxid;
+ char *token;
+ char *dev_id;
+} matrix_session;
+
+char *matrix_whoami(matrix_session *sess);
+matrix_session* matrix_access_token(const char *url, const char *token);
+matrix_session* matrix_login_pass(const char *url,
+ const char *user, const char *passwd,
+ const char *devname);
+void matrix_session_free(matrix_session *sess);
+
+#endif
diff --git a/util.c b/util.c
new file mode 100644
index 0000000..3e67b9d
--- /dev/null
+++ b/util.c
@@ -0,0 +1,36 @@
+#include "util.h"
+
+static size_t get_json_callback(void *contents, size_t size, size_t nmemb, void *userp)
+{
+ size_t realsize = size * nmemb;
+
+ json_tokener *tok = json_tokener_new();
+ if (userp != NULL)
+ *((json_object **)userp) = json_tokener_parse_ex(tok, contents, realsize);
+
+ json_tokener_free(tok);
+
+ return realsize;
+}
+
+CURLcode
+_curl_get(CURL *curl, const char *url, json_object **resp)
+{
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+ curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, get_json_callback);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)resp);
+
+ return curl_easy_perform(curl);
+}
+
+CURLcode
+_curl_post(CURL *curl, const char *url, const char *postdata, json_object **resp)
+{
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postdata);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, get_json_callback);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)resp);
+
+ return curl_easy_perform(curl);
+}
diff --git a/util.h b/util.h
new file mode 100644
index 0000000..509bcb9
--- /dev/null
+++ b/util.h
@@ -0,0 +1,39 @@
+#ifndef MATRIX_CURL_UTIL_H
+#define MATRIX_CURL_UTIL_H
+
+#include <curl/curl.h>
+#include <json-c/json.h>
+#include <string.h>
+
+CURLcode _curl_get(CURL *curl, const char *url, json_object **resp);
+CURLcode _curl_post(CURL *curl, const char *url, const char *postdata,
+ json_object **resp);
+
+static inline int
+json_add_string(json_object *j, const char *k, const char *v)
+{
+ return json_object_object_add(j, k, json_object_new_string(v));
+}
+
+static inline
+const char *json_gets(json_object *j, const char *key)
+{
+ json_object *val;
+
+ if (json_object_object_get_ex(j, key, &val)) {
+ if (json_object_is_type(val, json_type_string))
+ return json_object_get_string(val);
+ }
+ return NULL;
+}
+
+static inline
+char* copy_str(const char *s)
+{
+ size_t l = strlen(s)+1;
+ char *ss = (char*)malloc(l);
+ memcpy(ss, s, l);
+ return ss;
+}
+
+#endif