Added the remote web enhancement developed by Prince Samuel.
3 This Source Code Form is subject to the terms of the Mozilla Public
4 License, v. 2.0. If a copy of the MPL was not distributed with this
5 file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 Copyright (C) 2012 Prince Samuel <prince.samuel@gmail.com>
12 using System.Collections.Generic;
15 using System.Threading;
17 using OpenHardwareMonitor.GUI;
18 using OpenHardwareMonitor.Hardware;
19 using System.Reflection;
21 using System.Drawing.Imaging;
23 namespace OpenHardwareMonitor.Utilities
25 public class HttpServer
27 private HttpListener listener;
28 private int listenerPort, nodeCount;
29 private Thread listenerThread;
32 public HttpServer(Node r, int p)
38 listener = new HttpListener();
41 public Boolean startHTTPListener()
45 if (listener.IsListening)
48 string prefix = "http://+:" + listenerPort + "/";
49 listener.Prefixes.Clear();
50 listener.Prefixes.Add(prefix);
53 if (listenerThread == null)
55 listenerThread = new Thread(HandleRequests);
56 listenerThread.Start();
67 public Boolean stopHTTPListener()
71 listenerThread.Abort();
73 listenerThread = null;
75 catch (System.Net.HttpListenerException e)
78 catch (System.Threading.ThreadAbortException e)
81 catch (System.NullReferenceException e)
90 public void HandleRequests()
93 while (listener.IsListening)
95 var context = listener.BeginGetContext(new AsyncCallback(ListenerCallback), listener);
96 context.AsyncWaitHandle.WaitOne();
100 public void ListenerCallback(IAsyncResult result)
102 HttpListener listener = (HttpListener)result.AsyncState;
103 if (listener == null || !listener.IsListening)
105 // Call EndGetContext to complete the asynchronous operation.
106 HttpListenerContext context = listener.EndGetContext(result);
107 HttpListenerRequest request = context.Request;
109 var requestedFile = request.RawUrl.Substring(1);
110 if (requestedFile == "data.json")
116 if (requestedFile.Contains("images_icon"))
118 serveResourceImage(context, requestedFile.Replace("images_icon/", ""));
122 //default file to be served
123 if (string.IsNullOrEmpty(requestedFile))
124 requestedFile = "index.html";
126 string[] splits = requestedFile.Split('.');
127 string ext = splits[splits.Length - 1];
128 serveResourceFile(context, "Web." + requestedFile.Replace('/', '.'), ext);
131 private void serveResourceFile(HttpListenerContext context ,string name, string ext) {
133 //hack! resource names do not support the hyphen
134 name = "OpenHardwareMonitor.Resources." + name.Replace("custom-theme", "custom_theme");
137 Assembly.GetExecutingAssembly().GetManifestResourceNames();
138 for (int i = 0; i < names.Length; i++) {
139 if (names[i].Replace('\\', '.') == name) {
140 using (Stream stream = Assembly.GetExecutingAssembly().
141 GetManifestResourceStream(names[i])) {
142 context.Response.ContentType = getcontentType("." + ext);
143 context.Response.ContentLength64 = stream.Length;
144 byte[] buffer = new byte[512 * 1024];
146 while ((len = stream.Read(buffer, 0, buffer.Length)) > 0)
148 context.Response.OutputStream.Write(buffer, 0, len);
150 context.Response.OutputStream.Close();
155 context.Response.OutputStream.Close();
156 context.Response.StatusCode = 404;
157 context.Response.Close();
160 private void serveResourceImage(HttpListenerContext context ,string name) {
161 name = "OpenHardwareMonitor.Resources." + name;
164 Assembly.GetExecutingAssembly().GetManifestResourceNames();
165 for (int i = 0; i < names.Length; i++) {
166 if (names[i].Replace('\\', '.') == name) {
167 using (Stream stream = Assembly.GetExecutingAssembly().
168 GetManifestResourceStream(names[i])) {
170 Image image = Image.FromStream(stream);
171 context.Response.ContentType = "image/png";
172 using (MemoryStream ms = new MemoryStream())
174 image.Save(ms, ImageFormat.Png);
175 ms.WriteTo(context.Response.OutputStream);
177 context.Response.OutputStream.Close();
183 context.Response.OutputStream.Close();
184 context.Response.StatusCode = 404;
185 context.Response.Close();
188 private void sendJSON(HttpListenerContext context)
191 string JSON = "{\"id\": 0, \"Text\": \"Sensor\", \"Children\": [";
193 JSON += generateJSON(root);
195 JSON += ", \"Min\": \"Min\"";
196 JSON += ", \"Value\": \"Value\"";
197 JSON += ", \"Max\": \"Max\"";
198 JSON += ", \"ImageURL\": \"\"";
201 var responseContent = JSON;
202 byte[] buffer = Encoding.UTF8.GetBytes(responseContent);
204 context.Response.ContentLength64 = buffer.Length;
205 context.Response.ContentType = "application/json";
207 Stream outputStream = context.Response.OutputStream;
208 outputStream.Write(buffer, 0, buffer.Length);
209 outputStream.Close();
213 private string generateJSON(Node n)
215 string JSON = "{\"id\": " + nodeCount + ", \"Text\": \"" + n.Text + "\", \"Children\": [";
218 foreach (Node child in n.Nodes)
219 JSON += generateJSON(child) + ", ";
220 if (JSON.EndsWith(", "))
221 JSON = JSON.Remove(JSON.LastIndexOf(","));
226 JSON += ", \"Min\": \"" + ((SensorNode)n).Min + "\"";
227 JSON += ", \"Value\": \"" + ((SensorNode)n).Value + "\"";
228 JSON += ", \"Max\": \"" + ((SensorNode)n).Max + "\"";
229 JSON += ", \"ImageURL\": \"images/transparent.png\"";
231 else if (n is HardwareNode)
233 JSON += ", \"Min\": \"\"";
234 JSON += ", \"Value\": \"\"";
235 JSON += ", \"Max\": \"\"";
236 JSON += ", \"ImageURL\": \"images_icon/" + getHardwareImageFile((HardwareNode)n) + "\"";
238 else if (n is TypeNode)
240 JSON += ", \"Min\": \"\"";
241 JSON += ", \"Value\": \"\"";
242 JSON += ", \"Max\": \"\"";
243 JSON += ", \"ImageURL\": \"images_icon/" + getTypeImageFile((TypeNode)n) + "\"";
247 JSON += ", \"Min\": \"\"";
248 JSON += ", \"Value\": \"\"";
249 JSON += ", \"Max\": \"\"";
250 JSON += ", \"ImageURL\": \"images_icon/computer.png\"";
257 private static void returnFile(HttpListenerContext context, string filePath)
259 context.Response.ContentType = getcontentType(Path.GetExtension(filePath));
260 const int bufferSize = 1024 * 512; //512KB
261 var buffer = new byte[bufferSize];
262 using (var fs = File.OpenRead(filePath))
265 context.Response.ContentLength64 = fs.Length;
267 while ((read = fs.Read(buffer, 0, buffer.Length)) > 0)
268 context.Response.OutputStream.Write(buffer, 0, read);
271 context.Response.OutputStream.Close();
274 private static string getcontentType(string extension)
278 case ".avi": return "video/x-msvideo";
279 case ".css": return "text/css";
280 case ".doc": return "application/msword";
281 case ".gif": return "image/gif";
283 case ".html": return "text/html";
285 case ".jpeg": return "image/jpeg";
286 case ".js": return "application/x-javascript";
287 case ".mp3": return "audio/mpeg";
288 case ".png": return "image/png";
289 case ".pdf": return "application/pdf";
290 case ".ppt": return "application/vnd.ms-powerpoint";
291 case ".zip": return "application/zip";
292 case ".txt": return "text/plain";
293 default: return "application/octet-stream";
297 private static string getHardwareImageFile(HardwareNode hn)
300 switch (hn.Hardware.HardwareType)
302 case HardwareType.CPU:
304 case HardwareType.GpuNvidia:
306 case HardwareType.GpuAti:
308 case HardwareType.HDD:
310 case HardwareType.Heatmaster:
312 case HardwareType.Mainboard:
313 return "mainboard.png";
314 case HardwareType.SuperIO:
316 case HardwareType.TBalancer:
324 private static string getTypeImageFile(TypeNode tn)
327 switch (tn.SensorType)
329 case SensorType.Voltage:
330 return "voltage.png";
331 case SensorType.Clock:
333 case SensorType.Load:
335 case SensorType.Temperature:
336 return "temperature.png";
339 case SensorType.Flow:
341 case SensorType.Control:
342 return "control.png";
343 case SensorType.Level:
345 case SensorType.Power:
353 public int ListenerPort
355 get { return listenerPort; }
356 set { listenerPort = value; }