1 /* $Id$ */
3 /***
4 This file is part of fusedav.
6 fusedav is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 fusedav is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
16 You should have received a copy of the GNU General Public License
17 along with fusedav; if not, write to the Free Software Foundation,
18 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 ***/
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
25 #include <stdio.h>
26 #include <assert.h>
27 #include <pthread.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <termios.h>
31 #include <unistd.h>
33 #include <ne_uri.h>
34 #include <ne_request.h>
35 #include <ne_basic.h>
36 #include <ne_props.h>
37 #include <ne_utils.h>
38 #include <ne_socket.h>
39 #include <ne_auth.h>
40 #include <ne_dates.h>
42 #include "session.h"
45 static pthread_once_t session_once = PTHREAD_ONCE_INIT;
46 static pthread_key_t session_tsd_key;
48 static ne_uri uri;
49 static int b_uri = 0;
51 static const char *username = NULL, *password = NULL;
52 const char *base_directory = NULL;
54 static pthread_mutex_t credential_mutex = PTHREAD_MUTEX_INITIALIZER;
57 static char* ask_user(char *p, int hidden) {
58 char q[256], *r;
59 struct termios t;
60 int c = 0, l;
62 if (hidden) {
63 if (!isatty(fileno(stdin)))
64 hidden = 0;
65 else {
66 if (tcgetattr(fileno(stdin), &t) < 0)
67 hidden = 0;
68 else {
69 c = t.c_lflag;
70 t.c_lflag &= ~ECHO;
71 if (tcsetattr(fileno(stdin), TCSANOW, &t) < 0)
72 hidden = 0;
73 }
74 }
75 }
77 fprintf(stderr, "%s: ", p);
78 r = fgets(q, sizeof(q), stdin);
79 l = strlen(q);
80 if (l && q[l-1] == '\n')
81 q[l-1] = 0;
83 if (hidden) {
84 t.c_lflag = c;
85 tcsetattr(fileno(stdin), TCSANOW, &t);
86 fprintf(stderr, "\n");
87 }
89 return r ? strdup(r) : NULL;
90 }
92 static int ssl_verify_cb(void *userdata, int failures, const ne_ssl_certificate *cert) {
93 return 0;
94 }
96 static int ne_auth_creds_cb(void *userdata, const char *realm, int attempt, char *u, char *p) {
97 int r = -1;
100 pthread_mutex_lock(&credential_mutex);
102 if (attempt) {
103 fprintf(stderr, "Authenication failure!\n");
104 free((void*) username);
105 free((void*) password);
106 username = password = NULL;
107 }
109 if (!username)
110 username = ask_user("Username", 0);
112 if (username && !password)
113 password = ask_user("Password", 1);
115 if (username && password) {
116 snprintf(u, NE_ABUFSIZ, "%s", username);
117 snprintf(p, NE_ABUFSIZ, "%s", password);
118 r = 0;
119 }
121 pthread_mutex_unlock(&credential_mutex);
122 return r;
123 }
125 static ne_session *session_open(void) {
126 char *scheme = NULL;
127 ne_session *session;
129 if (!b_uri)
130 return NULL;
132 scheme = uri.scheme ? uri.scheme : "http";
134 if (!(session = ne_session_create(scheme, uri.host, uri.port ? uri.port : ne_uri_defaultport(scheme)))) {
135 fprintf(stderr, "Failed to create session\n");
136 return NULL;
137 }
139 ne_ssl_set_verify(session, ssl_verify_cb, NULL);
140 ne_set_server_auth(session, ne_auth_creds_cb, NULL);
141 return session;
142 }
144 static void session_destroy(void *s) {
145 ne_session *session = s;
146 assert(s);
147 ne_session_destroy(session);
148 }
150 static void session_tsd_key_init(void) {
151 pthread_key_create(&session_tsd_key, session_destroy);
152 }
154 ne_session *session_get(void) {
155 ne_session *session;
157 pthread_once(&session_once, session_tsd_key_init);
159 if ((session = pthread_getspecific(session_tsd_key)))
160 return session;
162 session = session_open();
163 pthread_setspecific(session_tsd_key, session);
165 return session;
166 }
168 int session_set_uri(const char *s, const char *u, const char *p) {
169 assert(!b_uri && !username && !password);
170 int l;
172 if (ne_uri_parse(s, &uri)) {
173 fprintf(stderr, "Invalid URI <%s>\n", s);
174 goto finish;
175 }
177 b_uri = 1;
179 if (!uri.host) {
180 fprintf(stderr, "Missing host part in URI <%s>\n", s);
181 goto finish;
182 }
184 base_directory = strdup(uri.path);
185 l = strlen(base_directory);
186 if (base_directory[l-1] == '/')
187 ((char*) base_directory)[l-1] = 0;
189 if (u)
190 username = strdup(u);
192 if (p)
193 password = strdup(p);
195 return 0;
197 finish:
199 if (b_uri) {
200 ne_uri_free(&uri);
201 b_uri = 0;
202 }
204 return -1;
205 }
208 void session_free(void) {
209 if (b_uri) {
210 ne_uri_free(&uri);
211 b_uri = 0;
212 }
214 free((char*) username);
215 free((char*) password);
216 free((char*) base_directory);
218 username = password = base_directory = NULL;
219 }