1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
|
//
// Monodoc server
//
// Author:
// Miguel de Icaza (miguel@ximian.com)
//
using System;
using System.Collections;
using System.IO;
using System.Web.Mail;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Data;
using ByteFX.Data.MySqlClient;
using System.Xml;
namespace Monodoc {
[WebServiceAttribute (Description="Web service for the MonoDoc contribution system")]
public class Contributions : System.Web.Services.WebService
{
const string basedir = "/home/contributions/";
//const string basedir = "/tmp/contributions/";
static string connection_string;
static Contributions ()
{
using (StreamReader sr = new StreamReader (File.OpenRead ("connection.string"))){
connection_string = sr.ReadLine ();
Console.WriteLine ("Connection: " + connection_string);
}
}
private IDbConnection GetConnection()
{
return new MySqlConnection(connection_string);
}
private MySqlParameter CreateParameter(string name, object value)
{
return new MySqlParameter (name, value);
}
static void mail (string recipient, string body)
{
MailMessage m = new MailMessage ();
m.From = "mono-docs-list@ximian.com";
m.To = recipient;
m.Subject = "Your Monodoc passkey";
m.Body = String.Format ("\n\nWelcome to the Mono Documentation Effort,\n\n" +
"This is your passkey for contributing to the Mono Documentation effort:\n " +
" {0}\n\n" +
"The Mono Documentation Team (mono-docs-list@ximian.com)", body);
SmtpMail.SmtpServer = "localhost";
SmtpMail.Send (m);
}
//
// 0 => OK to send contributions.
// -1 => Invalid version
//
[WebMethod(Description="Check the client/server version; 0 means that the server can consume your data")]
public int CheckVersion (int version)
{
if (version == 1)
return 0;
return -1;
}
//
// Return codes:
// -3 invalid characters in login
// -2 Login already registered, password resent.
// -1 Generic error
// 0 password mailed
//
[WebMethod(Description="Requests a registration for a login")]
public int Register (string login)
{
if (login.IndexOf ("'") != -1)
return -3;
IDbConnection conn = GetConnection();
conn.Open();
try
{
IDbCommand cmd = conn.CreateCommand();
cmd.CommandText = "select password from person where name=@login";
cmd.Parameters.Add( CreateParameter("@login", login));
IDataReader reader = cmd.ExecuteReader ();
if (reader.Read ()){
string password = (string) reader ["password"];
mail (login, password);
reader.Close ();
return -2;
}
reader.Close ();
Random rnd = new Random ();
int pass = rnd.Next ();
cmd.CommandText = "INSERT INTO person (name, password, last_serial) VALUES " +
"(@name, @password, 0)";
cmd.Parameters.Add( CreateParameter("@name",login));
cmd.Parameters.Add( CreateParameter("@password",pass));
cmd.ExecuteNonQuery ();
mail (login, pass.ToString ());
return 0;
} catch (Exception e) {
Console.Error.WriteLine (e);
} finally {
conn.Close ();
}
return -1;
}
[WebMethod (Description="Returns the latest serial number used for a change on the server")]
public int GetSerial (string login, string password)
{
IDbConnection conn = GetConnection();
conn.Open();
try
{
IDbCommand cmd = conn.CreateCommand();
cmd.CommandText = "select last_serial from person where name=@login and password=@password";
cmd.Parameters.Add( CreateParameter("@login", login));
cmd.Parameters.Add( CreateParameter("@password", password));
object r = cmd.ExecuteScalar();
if (r != null){
Console.Error.WriteLine (r);
return (int) r;
}
return -1;
} catch (Exception e){
Console.Error.WriteLine ("Exception" + e);
} finally {
conn.Close();
}
return -1;
}
// -1 Generic error.
// -2 Erroneous XML
int a=1;
[WebMethod (Description="Submits a GlobalChangeSet as a contribution")]
public int Submit (string login, string password, XmlNode node)
{
IDbConnection conn = GetConnection();
conn.Open();
try {
IDbCommand cmd = conn.CreateCommand();
cmd.CommandText = "select * from person where name=@login and password=@password";
cmd.Parameters.Add( CreateParameter("@login", login));
cmd.Parameters.Add( CreateParameter("@password", password));
IDataReader reader = cmd.ExecuteReader ();
int ret_val = -1;
if (reader.Read()){
int id = (int)reader["person_id"];
int serial = (int)reader["last_serial"];
reader.Close ();
//
// Validate the XML
//
XmlDocument d = new XmlDocument ();
d.AppendChild (d.ImportNode (node, true));
XmlNodeReader r = new XmlNodeReader (d);
try {
object rr = GlobalChangeset.serializer.Deserialize (r);
} catch {
return -2;
}
string dudebase = basedir + id;
Directory.CreateDirectory (dudebase);
d.Save (dudebase + "/" + serial + ".xml");
IDbTransaction txn = conn.BeginTransaction();
try {
cmd.CommandText = "UPDATE person SET last_serial=@last_serial WHERE name=@name AND password=@pwd";
cmd.Parameters.Add( CreateParameter("@last_serial", serial+1));
cmd.Parameters.Add( CreateParameter("@name", login));
cmd.Parameters.Add( CreateParameter("@pwd", password));
cmd.ExecuteNonQuery ();
cmd.CommandText = "INSERT INTO status (person_id, serial, status) VALUES (@id, @serial, 0)";
cmd.Parameters.Add( CreateParameter("@id",id));
cmd.Parameters.Add( CreateParameter("@serial",serial));
cmd.ExecuteNonQuery ();
txn.Commit();
} catch (Exception e) {
Console.Error.WriteLine ("E: " + e);
}
ret_val = serial+1;
return ret_val;
}
Console.Error.WriteLine ("Error, going: 4");
return -4;
} catch (Exception e) {
Console.Error.WriteLine ("Failure in Submit: " + e);
return -3;
} finally {
conn.Close ();
}
}
bool IsAdmin (IDbConnection conn, string login, string password)
{
IDbCommand cmd = conn.CreateCommand();
cmd.CommandText = "select person_id,is_admin from person where name=@name and password=@pass";
cmd.Parameters.Add( CreateParameter("@name",login));
cmd.Parameters.Add( CreateParameter("@pass",password));
int person_id = -1;
bool is_admin = false;
using (IDataReader reader = cmd.ExecuteReader ()){
if (reader.Read ()){
person_id = (int) reader ["person_id"];
is_admin = ((int) reader ["is_admin"]) == 1;
} else
return false;
}
if (person_id == -1 || is_admin == false)
return false;
return true;
}
[WebMethod (Description="Obtains the list of pending contributions")]
public PendingChange [] GetPendingChanges (string login, string password)
{
IDbConnection conn = GetConnection();
conn.Open ();
try {
if (!IsAdmin (conn, login, password)){
return new PendingChange [0];
}
IDbCommand cmd = conn.CreateCommand();
ArrayList results = new ArrayList ();
cmd.CommandText = "select status.person_id, serial, person.name from status, person where status=0 and person.person_id = status.person_id";
using (IDataReader reader = cmd.ExecuteReader ()){
while (reader.Read ()){
results.Add (new PendingChange ((string) reader ["name"], (int) reader ["person_id"], (int) reader ["serial"]));
}
}
PendingChange [] ret = new PendingChange [results.Count];
results.CopyTo (ret);
return ret;
} catch (Exception e){
Console.Error.WriteLine (e);
return null;
} finally {
conn.Close ();
}
}
[WebMethod (Description="Obtains a change set for a user")]
public XmlNode FetchContribution (string login, string password, int person_id, int serial)
{
IDbConnection conn = GetConnection ();
conn.Open ();
try {
if (!IsAdmin (conn, login, password))
return null;
XmlDocument d = new XmlDocument ();
string fname = basedir + person_id + "/" + serial + ".xml";
d.Load (fname);
return d.FirstChild;
} finally {
conn.Close ();
}
}
[WebMethod (Description="ADMIN: Obtains the number of pending commits")]
public Status GetStatus (string login, string password)
{
IDbConnection conn = GetConnection ();
conn.Open ();
try {
IDbCommand cmd = conn.CreateCommand();
cmd.CommandText = "select * from person where name=@name and password=@pass";
cmd.Parameters.Add( CreateParameter("@name",login));
cmd.Parameters.Add( CreateParameter("@pass",password));
IDataReader reader = cmd.ExecuteReader ();
int id = -1;
if (reader.Read())
id = (int)reader["person_id"];
reader.Close ();
if (id == -1)
return null;
Status s = new Status ();
cmd.CommandText = String.Format ("select count(*) from status where person_id='{0}'", id);
s.Contributions = (int) cmd.ExecuteScalar ();
cmd.CommandText = String.Format ("select count(*) from status where person_id='{0}' and status='0'", id);
s.Pending = (int) cmd.ExecuteScalar ();
cmd.CommandText = String.Format ("select count(*) from status where person_id='{0}' and status='1'", id);
s.Commited = (int) cmd.ExecuteScalar ();
return s;
} finally {
conn.Close ();
}
}
[WebMethod (Description="ADMIN: Updates the status of a contribution")]
public void UpdateStatus (string login, string password, int person_id, int contrib_id, int status)
{
IDbConnection conn = GetConnection();
conn.Open ();
try {
if (!IsAdmin (conn, login, password))
return;
IDbCommand cmd = conn.CreateCommand();
cmd.CommandText = "update status set status=@status WHERE person_id=@PID AND serial=@ser";
cmd.Parameters.Add (CreateParameter ("@status", status));
cmd.Parameters.Add (CreateParameter ("@PID", person_id));
cmd.Parameters.Add (CreateParameter ("@ser", contrib_id));
cmd.ExecuteNonQuery ();
} finally {
conn.Close ();
}
}
}
public class Status {
public int Contributions;
public int Commited;
public int Pending;
}
public class PendingChange {
public string Login;
public int ID;
public int Serial;
public PendingChange (string login, int person_id, int serial)
{
Login = login;
ID = person_id;
Serial = serial;
}
public PendingChange ()
{
}
}
}
|