Commit | Line | Data |
---|---|---|
92f3b0d7 FT |
1 | # Dolda Connect - Modular multiuser Direct Connect-style client |
2 | # Copyright (C) 2007 Fredrik Tolf <fredrik@dolda2000.com> | |
3 | # | |
4 | # This program is free software; you can redistribute it and/or modify | |
5 | # it under the terms of the GNU General Public License as published by | |
6 | # the Free Software Foundation; either version 2 of the License, or | |
7 | # (at your option) any later version. | |
8 | # | |
9 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. | |
13 | # | |
14 | # You should have received a copy of the GNU General Public License | |
15 | # along with this program; if not, write to the Free Software | |
16 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
17 | ||
fbe30a6d | 18 | from dolmod import * |
c5de778c | 19 | import os |
fbe30a6d | 20 | |
21 | def login(useauthless = True, **kw): | |
ff076c0a | 22 | """A convenience function for loginasync. |
23 | ||
24 | This function will initiate an asynchronous login per the | |
25 | loginasync command, and then run a select loop while waiting for | |
26 | it to complete. It will return a tuple (res, reason), where res is | |
27 | the result code, and reason is an explanatory text for any error. | |
28 | ||
29 | res can be any of the following: | |
30 | * success: Login completed successfully | |
31 | * nologin: No authentication mechanism could be negotiated | |
32 | * server: An error occurred on the server | |
33 | * user: An error occurred in the library | |
34 | * conv: The password conversation mechanism failed | |
35 | * authfail: The server refused the login (due to e.g. bad credentials) | |
36 | """ | |
fbe30a6d | 37 | result = [None] |
38 | def mycb(*v): | |
39 | result[0] = v | |
40 | loginasync(mycb, useauthless, **kw) | |
41 | while result[0] is None: | |
42 | select() | |
43 | return result[0] | |
44 | ||
9cbeb60c | 45 | def mustconnect(host, revision = latest): |
ff076c0a | 46 | """A convenience function for connect. |
47 | ||
48 | This function will connect to the given host, perform a select | |
49 | loop, and ensure that the server approves of the connection. If | |
50 | any of these steps fail, an exception is raised. If successful, | |
51 | the file descriptor for the server connection is returned. | |
52 | """ | |
2ce95e0e FT |
53 | if host is None: |
54 | fd = connect() | |
55 | else: | |
56 | fd = connect(host) | |
fbe30a6d | 57 | while True: |
58 | resp = getresp() | |
59 | if resp is not None and resp.getcmd() == u".connect": | |
60 | break | |
61 | select() | |
9cbeb60c | 62 | if resp.getcode() != 201: |
fbe30a6d | 63 | raise RuntimeError, resp.intresp()[0][0] |
9cbeb60c | 64 | if not checkproto(resp, revision): |
65 | raise RuntimeError, resp | |
00ea2039 | 66 | return fd |
fbe30a6d | 67 | |
9cbeb60c | 68 | def cnl(host = None, useauthless = True, revision = latest, **kw): |
ff076c0a | 69 | """A convenience function for connect and loginasync. |
70 | ||
2ce95e0e FT |
71 | This function will connect to the given server, or try the default |
72 | servers if none given, and authenticate to the server. If any of | |
73 | the steps fail, an exception is raised. | |
ff076c0a | 74 | """ |
9cbeb60c | 75 | fd = mustconnect(host, revision) |
fbe30a6d | 76 | err, reason = login(useauthless, **kw) |
77 | if err != "success": | |
78 | raise RuntimeError, (err, reason) | |
00ea2039 | 79 | return fd |
fbe30a6d | 80 | |
81 | def ecmd(*args): | |
ff076c0a | 82 | """A convenience function for qcmd. |
83 | ||
84 | This function will queue the given command, and then wait in a | |
85 | select loop until the command has been carried out. The return | |
86 | value is a Response object, corresponding to the reponse from the | |
87 | server. | |
88 | """ | |
fbe30a6d | 89 | tag = qcmd(*args) |
90 | while True: | |
91 | resp = getresp(tag) | |
92 | if resp is not None: | |
93 | break; | |
94 | select() | |
95 | return resp | |
96 | ||
97 | def ecmda(code, *args): | |
ff076c0a | 98 | """A convenience function for ecmd. |
99 | ||
100 | This function does essentially the same as ecmd, but it will also | |
101 | check so that the response has the given numerical code. If not, | |
102 | an exception is raised. | |
103 | """ | |
fbe30a6d | 104 | resp = ecmd(*args) |
105 | if resp.getcode() != code: | |
106 | raise ValueError, resp.getcode() | |
107 | return resp | |
194d48ea | 108 | |
109 | def ecmds(*args): | |
110 | """Another convenience function for ecmd. | |
111 | ||
112 | Like ecmda, but will fail on all 5xx codes, and succeed on all | |
113 | others. | |
114 | """ | |
115 | resp = ecmd(*args) | |
116 | if resp.getcode() >= 500 and resp.getcode() < 600: | |
f04b2c3c | 117 | raise ValueError, tuple(resp.extract()[0]) |
194d48ea | 118 | return resp |
54b4a861 | 119 | |
120 | def getresps(): | |
121 | """A generator function which will iterate over all responses from | |
122 | getresp. | |
123 | """ | |
124 | while True: | |
125 | resp = getresp() | |
126 | if resp is None: | |
127 | break | |
128 | else: | |
129 | yield resp |