Code

git: remove $Id$ svn cruft
[fusedav.git] / src / session.c
1 /***
2   Copyright (c) 2004-2006 Lennart Poettering
4   Permission is hereby granted, free of charge, to any person
5   obtaining a copy of this software and associated documentation files
6   (the "Software"), to deal in the Software without restriction,
7   including without limitation the rights to use, copy, modify, merge,
8   publish, distribute, sublicense, and/or sell copies of the Software,
9   and to permit persons to whom the Software is furnished to do so,
10   subject to the following conditions:
12   The above copyright notice and this permission notice shall be
13   included in all copies or substantial portions of the Software.
15   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19   BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20   ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22   SOFTWARE.
23 ***/
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
29 #include <stdio.h>
30 #include <assert.h>
31 #include <pthread.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <termios.h>
35 #include <unistd.h>
37 #include <ne_uri.h>
38 #include <ne_request.h>
39 #include <ne_basic.h>
40 #include <ne_props.h>
41 #include <ne_utils.h>
42 #include <ne_socket.h>
43 #include <ne_auth.h>
44 #include <ne_dates.h>
45 #include <ne_redirect.h>
47 #include "session.h"
48 #include "fusedav.h"
50 static pthread_once_t session_once = PTHREAD_ONCE_INIT;
51 static pthread_key_t session_tsd_key;
53 ne_uri uri;
54 static int b_uri = 0;
56 char *username = NULL;
57 static char *password = NULL;
58 char *base_directory = NULL;
60 static pthread_mutex_t credential_mutex = PTHREAD_MUTEX_INITIALIZER;
62 static char* ask_user(const char *p, int hidden) {
63     char q[256], *r;
64     struct termios t;
65     int c = 0, l;
67     if (hidden) {
68         if (!isatty(fileno(stdin)))
69             hidden = 0;
70         else {
71             if (tcgetattr(fileno(stdin),  &t) < 0)
72                 hidden = 0;
73             else {
74                 c = t.c_lflag;
75                 t.c_lflag &= ~ECHO;
76                 if (tcsetattr(fileno(stdin), TCSANOW, &t) < 0)
77                     hidden = 0;
78             }
79         }
80     }
82     fprintf(stderr, "%s: ", p);
83     r = fgets(q, sizeof(q), stdin);
84     l = strlen(q);
85     if (l && q[l-1] == '\n')
86         q[l-1] = 0;
88     if (hidden) {
89         t.c_lflag = c;
90         tcsetattr(fileno(stdin), TCSANOW, &t);
91         fprintf(stderr, "\n");
92     }
94     return r ? strdup(r) : NULL;
95 }
97 static int ssl_verify_cb(__unused void *userdata, __unused int failures, __unused const ne_ssl_certificate *cert) {
98     return 0;
99 }
101 static int ne_auth_creds_cb(__unused void *userdata, const char *realm, int attempt, char *u, char *p) {
102     int r = -1;
104     pthread_mutex_lock(&credential_mutex);
106     if (attempt) {
107         fprintf(stderr, "Authentication failure!\n");
108         free((void*) username);
109         free((void*) password);
110         username = password = NULL;
111     }
113     if (!username || !password)
114         fprintf(stderr, "Realm '%s' requires authentication.\n", realm);
116     if (!username)
117         username = ask_user("Username", 0);
119     if (username && !password)
120         password = ask_user("Password", 1);
122     if (username && password) {
123         snprintf(u, NE_ABUFSIZ, "%s", username);
124         snprintf(p, NE_ABUFSIZ, "%s", password);
125         r  = 0;
126     }
128     pthread_mutex_unlock(&credential_mutex);
129     return r;
132 static ne_session *session_open(int with_lock) {
133     const char *scheme = NULL;
134     ne_session *session;
136     extern ne_lock_store *lock_store;
138     if (!b_uri)
139         return NULL;
141     scheme = uri.scheme ? uri.scheme : "http";
143     if (!(session = ne_session_create(scheme, uri.host, uri.port ? uri.port : ne_uri_defaultport(scheme)))) {
144         fprintf(stderr, "Failed to create session\n");
145         return NULL;
146     }
148     ne_ssl_set_verify(session, ssl_verify_cb, NULL);
149     ne_set_server_auth(session, ne_auth_creds_cb, NULL);
150     ne_redirect_register(session);
152     if (with_lock && lock_store)
153         ne_lockstore_register(lock_store, session);
155     return session;
158 static void session_destroy(void *s) {
159     ne_session *session = s;
160     assert(s);
161     ne_session_destroy(session);
164 static void session_tsd_key_init(void) {
165     pthread_key_create(&session_tsd_key, session_destroy);
168 ne_session *session_get(int with_lock) {
169     ne_session *session;
171     pthread_once(&session_once, session_tsd_key_init);
173     if ((session = pthread_getspecific(session_tsd_key)))
174         return session;
176     session = session_open(with_lock);
177     pthread_setspecific(session_tsd_key, session);
179     return session;
182 int session_set_uri(const char *s, const char *u, const char *p) {
183     int l;
185     assert(!b_uri);
186     assert(!username);
187     assert(!password);
189     if (ne_uri_parse(s, &uri)) {
190         fprintf(stderr, "Invalid URI <%s>\n", s);
191         goto finish;
192     }
194     b_uri = 1;
196     if (!uri.host) {
197         fprintf(stderr, "Missing host part in URI <%s>\n", s);
198         goto finish;
199     }
201     base_directory = strdup(uri.path);
202     l = strlen(base_directory);
203     if (base_directory[l-1] == '/')
204         ((char*) base_directory)[l-1] = 0;
206     if (u)
207         username = strdup(u);
209     if (p)
210         password = strdup(p);
212     return 0;
214 finish:
216     if (b_uri) {
217         ne_uri_free(&uri);
218         b_uri = 0;
219     }
221     return -1;
225 void session_free(void) {
226     if (b_uri) {
227         ne_uri_free(&uri);
228         b_uri = 0;
229     }
231     free((char*) username);
232     free((char*) password);
233     free((char*) base_directory);
235     username = password = base_directory = NULL;
238 int session_is_local(const ne_uri *u) {
239     assert(u);
240     assert(b_uri);
242     return
243         strcmp(u->scheme, uri.scheme) == 0 &&
244         strcmp(u->host, uri.host) == 0 &&
245         u->port == uri.port;