ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/repos/CCSFinger/CCSFinger.cs
Revision: 724
Committed: 2006-03-30T21:33:30-08:00 (19 years, 2 months ago) by douglas
File size: 8445 byte(s)
Log Message:
Oops!

File Contents

# Content
1 // Douglas Thrift
2 //
3 // CCS Computer Science
4 //
5 // Windows Finger Daemon
6
7 using System;
8 using System.Collections.Generic;
9 using System.IO;
10 using System.Net;
11 using System.Net.Sockets;
12 using System.ServiceProcess;
13 using System.Text;
14 using System.Threading;
15
16 public class CCSFinger : ServiceBase
17 {
18 private class Finger
19 {
20 private class Login
21 {
22 private Net.USER_INFO_11 info;
23 private uint id;
24 private string session;
25 private string client;
26 private Wts.WTS_PROTOCOL_TYPE protocol;
27 private Wts.WTS_CONNECTSTATE_CLASS status;
28 private DateTime logon = DateTime.MinValue;
29
30 public Login(string login)
31 {
32 Net.UserGetInfo(null, login, 11, out info);
33
34 this.id = uint.MaxValue;
35 }
36
37 public Login(string login, uint id, string session, string client, Wts.WTS_PROTOCOL_TYPE protocol, Wts.WTS_CONNECTSTATE_CLASS status)
38 {
39 Net.UserGetInfo(null, login, 11, out info);
40
41 this.id = id;
42 this.session = session;
43 this.client = client;
44 this.protocol = protocol;
45 this.status = status;
46 }
47
48 public string Client
49 {
50 get { return protocol == Wts.WTS_PROTOCOL_TYPE.WTS_PROTOCOL_TYPE_CONSOLE ? "the Console" : client; }
51 }
52
53 public string Directory
54 {
55 get { return @"\\Zweihander\" + info.usri11_name; }
56 }
57
58 public uint Id
59 {
60 get { return id; }
61 }
62
63 public DateTime LastLogon
64 {
65 get
66 {
67 if (logon == DateTime.MinValue)
68 logon = new DateTime(1970, 1, 1) + new TimeSpan((long)info.usri11_last_logon * 10000000);
69
70 return logon;
71 }
72 }
73
74 public string Name
75 {
76 get { return info.usri11_full_name; }
77 }
78
79 public string Session
80 {
81 get { return session; }
82 }
83
84 public string Status
85 {
86 get { return status.ToString().Substring(3); }
87 }
88 }
89
90 private StreamWriter writer;
91 private SortedDictionary<string, List<Login>> logins = new SortedDictionary<string, List<Login>>();
92 private bool forward = false;
93 private List<string> nots = new List<string>();
94
95 private void Full()
96 {
97 if (forward)
98 writer.Write("finger: forwarding service denied\r\n");
99
100 foreach (string not in nots)
101 writer.Write("finger: {0}: no such user\r\n", not);
102
103 bool first = true;
104
105 foreach (KeyValuePair<string, List<Login>> login in logins)
106 {
107 if (first)
108 first = false;
109 else
110 writer.Write("\r\n");
111
112 writer.Write("Login: {0,-32} Name: {1}\r\nDirectory: {2}\r\n", login.Key, login.Value[0].Name, login.Value[0].Directory);
113
114 foreach (Login login_ in login.Value)
115 if (login_.Id != uint.MaxValue)
116 writer.Write("{0} on {1}, from {2}\r\n", login_.Status, login_.Id, login_.Client);
117
118 if (login.Value[0].LastLogon != new DateTime(1970, 1, 1))
119 writer.Write("Last login {0:ddd MMM dd HH:mm} ({1})\r\n", login.Value[0].LastLogon.ToLocalTime(), login.Value[0].LastLogon.ToLocalTime().IsDaylightSavingTime() ? "PDT" : "PST");
120 else
121 writer.Write("Never logged in.\r\n");
122
123 writer.Write("No Mail.\r\n");
124
125 string[] files = { ".project", ".plan" };
126
127 foreach (string file in files)
128 try
129 {
130 StreamReader reader = new StreamReader(new FileStream(Directory.GetFiles(login.Value[0].Directory, file)[0], FileMode.Open, FileAccess.Read));
131
132 switch (file)
133 {
134 case ".project":
135 writer.Write("Project:\r\n");
136 break;
137 case ".plan":
138 writer.Write("Plan:\r\n");
139 break;
140 }
141
142 writer.Write("{0}", reader.ReadToEnd());
143 }
144 catch (Exception)
145 {
146 if (file == ".plan")
147 writer.Write("No Plan.\r\n");
148 }
149 }
150 }
151
152 private void Sessions(IDictionary<string, List<Login>> logins)
153 {
154 Wts.WTS_SESSION_INFO[] sessions;
155 uint count;
156
157 Wts.EnumerateSessions(IntPtr.Zero, 0, 1, out sessions, out count);
158
159 for (uint index = 0; index != count; ++index)
160 {
161 string name;
162 uint size;
163
164 Wts.QuerySessionInformation(IntPtr.Zero, sessions[index].SessionId, Wts.WTS_INFO_CLASS.WTSUserName, out name, out size);
165
166 if (name.Length > 0)
167 {
168 string session, client;
169 Wts.WTS_PROTOCOL_TYPE protocol;
170 Wts.WTS_CONNECTSTATE_CLASS status;
171
172 Wts.QuerySessionInformation(IntPtr.Zero, sessions[index].SessionId, Wts.WTS_INFO_CLASS.WTSWinStationName, out session, out size);
173 Wts.QuerySessionInformation(IntPtr.Zero, sessions[index].SessionId, Wts.WTS_INFO_CLASS.WTSClientName, out client, out size);
174 Wts.QuerySessionInformation(IntPtr.Zero, sessions[index].SessionId, Wts.WTS_INFO_CLASS.WTSClientProtocolType, out protocol, out size);
175 Wts.QuerySessionInformation(IntPtr.Zero, sessions[index].SessionId, Wts.WTS_INFO_CLASS.WTSConnectState, out status, out size);
176
177 if (!logins.ContainsKey(name))
178 logins.Add(string.Copy(name), new List<Login>());
179
180 logins[name].Add(new Login(name, sessions[index].SessionId, session, client, protocol, status));
181 }
182 }
183 }
184
185 public Finger(StreamWriter writer, bool full)
186 {
187 this.writer = writer;
188
189 Sessions(logins);
190
191 if (logins.Count < 1)
192 writer.Write("No one logged on.\r\n");
193 else if (full)
194 Full();
195 else
196 {
197 writer.Write("Login Name Id Session Status\r\n");
198
199 foreach (KeyValuePair<string, List<Login>> login_ in logins)
200 foreach (Login login in login_.Value)
201 writer.Write("{0,-15} {1,-20} {2,-6} {3,-13} {4}\r\n", login_.Key, login.Name.Length > 20 ? login.Name.Substring(0, 20) : login.Name, login.Id, login.Session, login.Status);
202 }
203 }
204
205 public Finger(StreamWriter writer, ICollection<string> names)
206 {
207 this.writer = writer;
208
209 uint count;
210 Net.NET_DISPLAY_USER[] users;
211
212 Net.QueryDisplayInformation(null, 1, 0, 100, uint.MaxValue, out count, out users);
213
214 Dictionary<string, List<Login>> logins_ = new Dictionary<string, List<Login>>();
215
216 Sessions(logins_);
217
218 foreach (string name in names)
219 if (name.Contains("@"))
220 forward = true;
221 else
222 {
223 bool not = true;
224
225 for (uint index = 0; index != count; ++index)
226 if (users[index].usri1_name.IndexOf(name, StringComparison.OrdinalIgnoreCase) != -1 || users[index].usri1_full_name.IndexOf(name, StringComparison.OrdinalIgnoreCase) != -1)
227 try
228 {
229 logins.Add(users[index].usri1_name, new List<Login>());
230
231 logins[users[index].usri1_name].Add(new Login(users[index].usri1_name));
232
233 if (logins_.ContainsKey(users[index].usri1_name))
234 logins[users[index].usri1_name].AddRange(logins_[users[index].usri1_name]);
235 }
236 catch (ArgumentException) {}
237 finally
238 {
239 not = false;
240 }
241
242 if (not)
243 nots.Add(name);
244 }
245
246 Full();
247 }
248 }
249
250 private static void Do()
251 {
252 TcpListener listener = null;
253
254 try
255 {
256 listener = new TcpListener(IPAddress.Any, 79);
257
258 listener.Start();
259
260 while (true)
261 {
262 Socket socket = listener.AcceptSocket();
263
264 socket.ReceiveTimeout = 60000;
265
266 Thread thread = new Thread(new ParameterizedThreadStart(Do));
267
268 thread.Start(socket);
269 }
270 }
271 catch (SocketException exception)
272 {
273 Console.Error.WriteLine(exception);
274 }
275 finally
276 {
277 listener.Stop();
278 }
279 }
280
281 private static void Do(object socket_)
282 {
283 Socket socket = (Socket)socket_;
284 NetworkStream stream = new NetworkStream(socket);
285
286 try
287 {
288 byte[] buffer = new byte[1024];
289 int size = 0, byte_;
290
291 while (size != buffer.Length && (byte_ = stream.ReadByte()) != '\r' && byte_ != '\n' && byte_ != -1)
292 buffer[size++] = (byte)byte_;
293
294 string line = Encoding.ASCII.GetString(buffer, 0, size);
295
296 Console.WriteLine("{0} [{1}]", socket.RemoteEndPoint, line);
297
298 List<string> names = new List<string>();
299 bool full = false;
300
301 foreach (string name in line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries))
302 {
303 if (name.ToUpper() == "/W")
304 full = true;
305 else
306 names.Add(name);
307 }
308
309 StreamWriter writer = new StreamWriter(stream, new UTF8Encoding(false));
310
311 Finger finger = names.Count > 0 ? new Finger(writer, names) : new Finger(writer, full);
312
313 writer.Flush();
314 }
315 catch (IOException) {}
316
317 socket.Close(60);
318 }
319
320 public static int Main(string[] args)
321 {
322 Do();
323
324 return 0;
325 }
326 }