/// <summary> /// Formの値をValueに取り込む /// </summary> /// <remarks> /// <para> /// テンプレートHTML内で Name= を指定している場合、正しい値を読み取る /// ことができません。(Fetchをする時点ではテンプレートをパースしてい /// ないため。) /// </para> /// </remarks> public virtual void Fetch(HttpPage page, object defaultValue = null) { string val = page.Fetch(Name, null); if (val == null) { Value = defaultValue; } else if (defaultValue is int) { Value = StringUtil.ToInt(val); } else if (defaultValue is double) { Value = StringUtil.ToDouble(val); } else if (defaultValue is bool) { Value = StringUtil.ToBool(val); } else { Value = val; } }
public override void Fetch(HttpPage page, object defaultValue = null) { if (defaultValue == null) { defaultValue = ""; } Value = StringUtil.ToBool(page.Fetch(Name, defaultValue.ToString())); }
public override void Fetch(HttpPage page, object defaultValue = null) { foreach (string val in page.Fetch(Name, "").Split(",".ToCharArray())) { if (val == Value.ToString()) { Checked = true; return; } } Checked = false; }
public override void Fetch(HttpPage page, object defaultValue = null) { T val; if (Enum.TryParse <T>(page.Fetch(Name, ""), out val)) { Value = val; } else { Value = defaultValue; } }
public override void Fetch(HttpPage page, object defaultValue = null) { int d, hh, mm; if (defaultValue == null) { d = 0; } else if (defaultValue is int) { d = (int)defaultValue; } else { d = StringUtil.ToInt(defaultValue.ToString()); } hh = d / 60; mm = d % 60; Value = page.Fetch(Name + "Hour", hh) * 60 + page.Fetch(Name + "Minute", mm); }
public override void Fetch(HttpPage page, object defaultValue = null) { int yy, mm, dd; if (defaultValue is DateTime) { DateTime d = (DateTime)defaultValue; yy = d.Year; mm = d.Month; dd = d.Day; } else { yy = 0; mm = 0; dd = 0; } Value = StringUtil.ToDateTime(String.Format("{0}/{1}/{2}", page.Fetch(Name + "Year", yy), page.Fetch(Name + "Month", mm), page.Fetch(Name + "Day", dd))); }
private void OnConnect(WorkerContext wc) { wc.Timer.Reset(); wc.Timer.Start(); wc.Count++; HttpListenerContext context = wc.Context; string requestmemo = string.Format("{0} {1} from {2}", context.Request.HttpMethod, context.Request.RawUrl, context.Request.RemoteEndPoint); LOG_DEBUG("Requested " + requestmemo); // 古いセッションを破棄 PurgeSession(); context.Response.KeepAlive = false; context.Response.AddHeader("Server", "MACS HttpServer"); string path = context.Request.Url.AbsolutePath; int status = 0; try { // デフォルトページ? if ((path == "/") && (m_defaultpage != null)) { using (HttpPage page = new HttpPage()){ page.SetLogger(this.Logger); page.SetServerContext(this, context, path); page.Redirect(m_defaultpage); status = 200; } } // 静的ページを探す if (status == 0) { foreach (KeyValuePair <string, HttpStaticPage> kv in m_staticpagelist) { if (path.StartsWith(kv.Key) && (path.Length > kv.Key.Length) && (path[kv.Key.Length] == '/')) { if (context.Request.HttpMethod == "GET") { lock (kv.Value){ kv.Value.SetLogger(this.Logger); kv.Value.SetServerContext(this, context, path); kv.Value.PageLoad(path.Substring(kv.Key.Length)); } status = 200; } else { status = 405; } break; } } } if (status == 0) { // アプリケーションページを探す foreach (KeyValuePair <string, Type> kv in m_pagelist) { if (path.StartsWith(kv.Key) && ((path.Length == kv.Key.Length) || (path[kv.Key.Length] == '/'))) { // 動的ページにマッチした Type pageClass = kv.Value; // 動的ページは同時にMaxActivePages個しかレンダリングしない lock (m_activepages_mutex) { if (++m_activepages > m_maxactivepages) { // オーバーした時は強制的にEmergencyPageでレンダリングする LOG_NOTICE("Number of active pages exceeds MaxActivePages({0}), use {1}", m_maxactivepages, m_emergencypage.Name); pageClass = m_emergencypage; } } int timeout = 0; // ページレンダリングタイムアウト try { if ((context.Request.HttpMethod == "GET") || (context.Request.HttpMethod == "POST")) { // セッション変数をクッキー管理する。 Cookie sessid = context.Request.Cookies[m_servername + "-SID"]; ObjectDictionary sess; lock (m_sessiondict){ if ((sessid != null) && m_sessiondict.ContainsKey(sessid.Value)) { sess = m_sessiondict[sessid.Value]; } else { sessid = new Cookie(m_servername + "-SID", m_rand.Next(9999999).ToString() + m_rand.Next(9999999).ToString()); sess = new ObjectDictionary(); m_sessiondict[sessid.Value] = sess; } m_sessiontime[sessid.Value] = DateTime.Now; } sessid.Version = 1; sessid.Path = "/"; if (UseCookieExpires && (SessionTimeout > 0)) { sessid.Expires = DateTime.Now.AddSeconds(SessionTimeout); //context.Response.AppendCookie(sessid); // なぜか正しいSet-Cookieヘッダを生成してくれないので、自力でヘッダを作る。 context.Response.AppendHeader("Set-Cookie", string.Format("{0}={1}; expires={2}; path={3}", sessid.Name, sessid.Value, sessid.Expires.ToString("r"), sessid.Path)); } else { context.Response.AppendHeader("Set-Cookie", string.Format("{0}={1}; path={2}", sessid.Name, sessid.Value, sessid.Path)); } // ページレンダラの呼び出し using (HttpPage page = (HttpPage)(pageClass.GetConstructor(Type.EmptyTypes).Invoke(null))){ page.SetLogger(this.Logger); page.SetServerContext(this, context, kv.Key.Substring(1)); // ページレンダリングタイムアウトの設定 timeout = page.Timeout; if (timeout < 0) { timeout = DefaultTimeout; } if (timeout > 0) { NThread.Watchdog(timeout, NThread.WatchdogMode.Abort); } // セッション変数アクセスの排他を行なうと、同一端末からのアクセスの処理はシリアライズされる。 if (page.UseSession) { lock (sess) { page.SetSession(sess, m_appl); page.PageLoad(path.Substring(kv.Key.Length)); } } else { page.SetSession(sess, m_appl); page.PageLoad(path.Substring(kv.Key.Length)); } status = 200; } } else { status = 405; } break; } finally { if (timeout > 0) { NThread.SuspendWatchdog(); } lock (m_activepages_mutex) { if (m_activepages > 0) { m_activepages--; } } } } } } if (status == 0) { // ルート静的ページを探す if (m_staticpagelist.ContainsKey("/")) { HttpStaticPage pg = m_staticpagelist["/"]; if (context.Request.HttpMethod == "GET") { lock (pg){ pg.SetLogger(this.Logger); pg.SetServerContext(this, context, path); pg.PageLoad(path); } status = 200; } else { status = 405; } } } if (status == 0) { // 該当ページが無い。 status = 404; } } catch (PageRedirectException e) { using (HttpPage page = new HttpPage()){ page.SetLogger(this.Logger); page.SetServerContext(this, context, path); page.Redirect(e.m_pagename); status = 200; } } catch (HttpListenerException) { // コンテンツ送信失敗。きっとクライアント側が切ったのだろう。 status = 200; // とりあえず、こちら側の処理は成功したことにする。 LOG_ERR("Client closed socket while sending contents."); } catch (IOException e) { // コンテンツ送信中にソケットが切れた(?) status = 200; // とりあえず、こちら側の処理は成功したことにする。 LOG_DEBUG("IOError while sending contents: " + e.Message); } catch (ThreadInterruptedException) { using (HttpPage page = new HttpPage()){ page.SetLogger(this.Logger); page.SetServerContext(this, context, "error"); page.PageLoad("503"); } } catch (ThreadAbortException ex) { bool isTimeout = (ex.ExceptionState != null) && (ex.ExceptionState is TimeoutException); if (isTimeout) { LOG_ERR("{0} is aborted due to timeout", path); } else { LOG_ERR("{0} is aborted", path); } LOG_EXCEPTION(ex); using (HttpPage page = new HttpPage()){ page.SetLogger(this.Logger); page.SetServerContext(this, context, "error"); page.PageLoad(isTimeout?"408":"500"); } } catch (Exception e) { LOG_CRIT(String.Format("{0}: {1} in {2}", e.GetType().Name, e.Message, e.TargetSite)); LOG_EXCEPTION(e); if (ShowStackTrace) { using (HttpStackTracePage page = new HttpStackTracePage(e)) { try { page.SetLogger(this.Logger); page.SetServerContext(this, context, "StackTrace"); page.PageLoad(e.Message); } catch (Exception) { // I can't do any more. } } status = 200; } else { status = 500; } } if (status != 200) { LOG_WARNING(string.Format("Failed to dispatch {0} (code={1})", requestmemo, status)); using (HttpPage page = new HttpPage()){ try { page.SetLogger(this.Logger); page.SetServerContext(this, context, "error"); page.PageLoad(status.ToString()); } catch (Exception) { // contextがもう使えない状態にあるらしい。きっとクライアント側が切ったのだろう。 // 無視。 } } } //context.Response.OutputStream.Close(); // 念のため。 // 上の行は、なぜかDebian版monoでは戻ってこない。 try { context.Response.Close(); } catch (Exception) { // Close失敗は無視する。 } wc.Timer.Stop(); long elapsed = wc.Timer.ElapsedMilliseconds; if (elapsed > wc.MaxElapsed) { wc.MaxElapsed = elapsed; } wc.TotalElapsed += elapsed; LOG_DEBUG(string.Format("Finished {0} ({1}msec)", requestmemo, elapsed)); }