.htaccess editor: start / stop ape debugger

This commit is contained in:
Ruslan Keba 2013-03-26 18:06:40 +02:00
parent 19b52f025c
commit 7cc5207bfb
6 changed files with 255 additions and 142 deletions

View file

@ -1369,20 +1369,11 @@ UL.ActionButtons LI
width:100px; width:100px;
} }
table#toolbar
{
width: 100%;
display: none;
}
.pnlControl input.NormalTextBox .pnlControl input.NormalTextBox
{ {
width: 300px; width: 300px;
} }
.toolbar-space
{
width: 80%;
}
.disabled .disabled
{ {
width:20px; width:20px;
@ -1391,12 +1382,6 @@ table#toolbar
border:medium none; border:medium none;
} }
.toolbar-button
{
padding: 0 1px;
cursor: pointer;
white-space: nowrap;
}
.enabled .enabled
{ {
width:20px; width:20px;
@ -1405,10 +1390,14 @@ table#toolbar
border:medium none; border:medium none;
} }
p.warningText {font-size:14px; color:Red; text-align:center;} p.warningText {
font-size:14px;
color:Red;
text-align:center;
}
.Hidden .Hidden
{ {
display: none; display: none;
} }

View file

@ -117,8 +117,11 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="btnApeDebugger.Text" xml:space="preserve"> <data name="btnApeDebuggerStart.Text" xml:space="preserve">
<value>Start Debug</value> <value>Start Debugging</value>
</data>
<data name="btnApeDebuggerStop.Text" xml:space="preserve">
<value>Stop Debugging</value>
</data> </data>
<data name="btnCancel.Text" xml:space="preserve"> <data name="btnCancel.Text" xml:space="preserve">
<value>Cancel</value> <value>Cancel</value>
@ -130,6 +133,6 @@
<value>Update</value> <value>Update</value>
</data> </data>
<data name="lblFolderName.Text" xml:space="preserve"> <data name="lblFolderName.Text" xml:space="preserve">
<value>Folder Path:</value> <value>.htaccess path: </value>
</data> </data>
</root> </root>

View file

@ -5,82 +5,57 @@
<script type="text/javascript" src="/JavaScript/jquery.min.js?v=1.4.4"></script> <script type="text/javascript" src="/JavaScript/jquery.min.js?v=1.4.4"></script>
<script type="text/javascript" src="/JavaScript/codemirror/codemirror.js"></script> <script type="text/javascript" src="/JavaScript/codemirror/codemirror.js"></script>
<script type="text/javascript" src="/JavaScript/codemirror/htaccess.js"></script> <script type="text/javascript" src="/JavaScript/codemirror/htaccess.js"></script>
<script type="text/javascript"> <style type="text/css">
function pageLoad() {
$('input:hidden').each(function (index, el) {
if ($(this).attr('id').indexOf('ApeDebuggerUrl') >= 0) {
if (this.value) {
$('#toolbar-start-debug').show();
}
}
});
};
function openDebugWindow() {
$('input:hidden').each(function (index, el) {
if ($(this).attr('id').indexOf('ApeDebuggerUrl') >= 0) {
if (this.value) {
window.open(this.value);
}
}
});
return false;
}
</script>
<style>
.CodeMirror { .CodeMirror {
border: 1px solid #444; border: 1px solid #444;
padding: 2px; padding: 2px;
font-family: Consolas, monospace; font-family: Consolas, monospace;
font-size: 13px; font-size: 14px;
} }
</style> </style>
<div class="FormBody"> <div class="FormBody">
<table cellspacing="0" cellpadding="0" width="100%"> <table cellspacing="0" cellpadding="5" width="100%">
<tr> <tr>
<td> <td class="SubHead" style="white-space: nowrap;">
<table cellspacing="0" cellpadding="5" width="100%"> <asp:Label ID="lblFolderName" runat="server" meta:resourcekey="lblFolderName"></asp:Label>
<tr> </td>
<td class="SubHead"> <td class="NormalBold" style="white-space: nowrap;">
<asp:Label ID="lblFolderName" runat="server" meta:resourcekey="lblFolderName" Text="Folder Path:"></asp:Label> <asp:Label runat="server" ID="LabelWebSiteName"></asp:Label>
</td>
<td class="NormalBold"> <uc1:FileLookup id="folderPath" runat="server" Width="400">
<uc1:FileLookup id="folderPath" runat="server" Width="400"> </uc1:FileLookup>
</uc1:FileLookup> <asp:HiddenField ID="contentPath" runat="server" />
<asp:HiddenField ID="contentPath" runat="server" /> <asp:HiddenField ID="DebuggerUrlField" runat="server" />
<asp:HiddenField ID="ApeDebuggerUrl" runat="server" /> </td>
</td> <td style="width: 40%">
</tr> <asp:Button ID="ButtonDebuggerStart" runat="server" Text="Start Debug" meta:resourcekey="btnApeDebuggerStart"
<tr> CssClass="Button1" OnClick="DebugStartClick" />
<td colspan="2"> <asp:Button ID="ButtonDebuggerStop" runat="server" Text="Start Debug" meta:resourcekey="btnApeDebuggerStop"
<table id="toolbar"> CssClass="Button1" OnClick="DebugStopClick" />
<tr> </td>
<td> </tr>
<asp:Button ID="btnApeDebug" runat="server" Text="Start Debug" meta:resourcekey="btnApeDebugger" </table>
CssClass="toolbar-button" OnClick="btnApeDebug_Click" /> <table id="toolbar" width="100%">
</td> <tr>
<td> <td>
<button id="toolbar-start-debug" cssclass="toolbar-button" style="display: none;"
onclick="return openDebugWindow();"> </td>
Open&nbsp;Debug&nbsp;window</button> <td style="width: 90%">
</td> <asp:Label runat="server" ID="ContainerLinkDebuggingPage" Visible="False">
<td class="toolbar-space">&nbsp;</td> Open debugging page: <asp:HyperLink runat="server" ID="LinkDebuggingPage" Target="ape-debugging-page"></asp:HyperLink>
</tr> </asp:Label>
</table> </td>
</td> </tr>
</tr> </table>
<tr>
<td colspan="2"> <asp:Panel runat="server" ID="DebuggerFramePanel" Visible="False">
<asp:TextBox ID="htaccessContent" runat="server" TextMode="MultiLine" class="CodeEditor"></asp:TextBox> <iframe runat="server" ID="DebuggerFrame" width="100%" height="400px"></iframe>
</td> </asp:Panel>
</tr>
</table> <asp:TextBox ID="htaccessContent" runat="server" TextMode="MultiLine" class="CodeEditor"></asp:TextBox>
</td>
</tr>
</table>
</div> </div>
<div class="FormFooter"> <div class="FormFooter">
<asp:Button ID="btnUpdate" runat="server" Text="Update" meta:resourcekey="btnUpdate" <asp:Button ID="btnUpdate" runat="server" Text="Update" meta:resourcekey="btnUpdate"
CssClass="Button1" OnClick="btnUpdate_Click" /> CssClass="Button1" OnClick="btnUpdate_Click" />

View file

@ -31,6 +31,7 @@ using System.Data;
using System.Configuration; using System.Configuration;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Web; using System.Web;
using System.Web.Security; using System.Web.Security;
@ -65,22 +66,30 @@ namespace WebsitePanel.Portal
{ {
// read httpd.conf // read httpd.conf
folder = ES.Services.WebServers.GetHeliconApeHttpdFolder(int.Parse(spaceId)); folder = ES.Services.WebServers.GetHeliconApeHttpdFolder(int.Parse(spaceId));
btnApeDebug.Visible = false; ButtonDebuggerStart.Visible = false;
ButtonDebuggerStop.Visible = false;
} }
else else
{ {
// read web site // read web site
WebSite site = ES.Services.WebServers.GetWebSite(PanelRequest.ItemID); WebSite site = GetWebSite();
if (site == null) if (site == null)
{ {
RedirectToBrowsePage(); RedirectToBrowsePage();
return; return;
} }
LabelWebSiteName.Text = site.Name;
folderPath.RootFolder = site.ContentPath; folderPath.RootFolder = site.ContentPath;
folderPath.PackageId = site.PackageId; folderPath.PackageId = site.PackageId;
htaccessContent.Text = "# Helicon Ape\n"; htaccessContent.Text = "# Helicon Ape\n";
ButtonDebuggerStart.Visible = true;
ButtonDebuggerStop.Visible = false;
if (String.IsNullOrEmpty(PanelRequest.Name)) if (String.IsNullOrEmpty(PanelRequest.Name))
return; return;
@ -102,14 +111,16 @@ namespace WebsitePanel.Portal
{ {
htaccessContent.Text = "# Helicon Ape\n"; htaccessContent.Text = "# Helicon Ape\n";
} }
ApeDebuggerUrl.Value = ""; /*
DebuggerUrlField.Value = "";
if ( RE_APE_DEBUGGER_ENABLED.IsMatch(htaccessContent.Text) ) if ( RE_APE_DEBUGGER_ENABLED.IsMatch(htaccessContent.Text) )
{ {
btnApeDebug.Text = "Stop Debug"; btnApeDebug.Text = (string)GetLocalResourceObject("btnApeDebuggerStop.Text");
GetApeDebuggerUrl(); GetDebuggerUrl();
} }
*/
} }
@ -123,19 +134,6 @@ namespace WebsitePanel.Portal
string spaceId = Request.QueryString["SpaceID"]; string spaceId = Request.QueryString["SpaceID"];
if (RE_APE_DEBUGGER_ENABLED.IsMatch(htaccessContent.Text))
{
btnApeDebug.Text = "Stop Debug";
GetApeDebuggerUrl();
}
else
if (RE_APE_DEBUGGER_DISABLED.IsMatch(htaccessContent.Text))
{
btnApeDebug.Text = "Start Debug";
GetApeDebuggerUrl();
}
try try
{ {
if (folder.Path == HtaccessFolder.HTTPD_CONF_FILE && !string.IsNullOrEmpty(spaceId)) if (folder.Path == HtaccessFolder.HTTPD_CONF_FILE && !string.IsNullOrEmpty(spaceId))
@ -177,67 +175,159 @@ namespace WebsitePanel.Portal
protected readonly Regex RE_APE_DEBUGGER_ENABLED = new Regex(@"^[ \t]*(SetEnv\s+mod_developer\s+secure-key-([\d]+))", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Multiline); protected readonly Regex RE_APE_DEBUGGER_ENABLED = new Regex(@"^[ \t]*(SetEnv\s+mod_developer\s+secure-key-([\d]+))", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Multiline);
protected readonly Regex RE_APE_DEBUGGER_DISABLED = new Regex(@"^[ \t]*#[ \t]*(SetEnv\s+mod_developer\s+secure-key-([\d]+))", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Multiline); protected readonly Regex RE_APE_DEBUGGER_DISABLED = new Regex(@"^[ \t]*#[ \t]*(SetEnv\s+mod_developer\s+secure-key-([\d]+))", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Multiline);
protected string ApeDebuggerSecureKey = "";
//protected string ApeDebuggerUrl = ""; protected string DebuggerSecureKey = "";
protected string DebuggerSessionId = "";
protected string DebuggerUrl = "";
protected string DebuggingPageUrl = "";
protected void btnApeDebug_Click(object sender, EventArgs e) protected void DebugStartClick(object sender, EventArgs e)
{ {
var code = htaccessContent.Text; var code = htaccessContent.Text;
if ( RE_APE_DEBUGGER_DISABLED.IsMatch(code) ) if ( RE_APE_DEBUGGER_DISABLED.IsMatch(code) )
{ {
// already disabled, enable it! // already disabled, enable it!
ApeDebuggerSecureKey = RE_APE_DEBUGGER_DISABLED.Match(code).Groups[2].Value; DebuggerSecureKey = RE_APE_DEBUGGER_DISABLED.Match(code).Groups[2].Value;
code = RE_APE_DEBUGGER_DISABLED.Replace(code, "$1"); code = RE_APE_DEBUGGER_DISABLED.Replace(code, "$1");
btnApeDebug.Text = "Stop Debug";
}
else if ( RE_APE_DEBUGGER_ENABLED.IsMatch(code) )
{
// alerdy enable, disable it!
ApeDebuggerSecureKey = "";
code = RE_APE_DEBUGGER_ENABLED.Replace(code, "# $1");
btnApeDebug.Text = "Start Debug";
} }
else else
{ {
ApeDebuggerSecureKey = new Random().Next(100000000, 999999999).ToString(); DebuggerSecureKey = new Random().Next(100000000, 999999999).ToString(CultureInfo.InvariantCulture);
code = code + "\nSetEnv mod_developer secure-key-" + ApeDebuggerSecureKey +"\n"; code = code + "\nSetEnv mod_developer secure-key-" + DebuggerSecureKey +"\n";
btnApeDebug.Text = "Stop Debug";
} }
htaccessContent.Text = code; htaccessContent.Text = code;
SaveFolder(); SaveFolder();
GetApeDebuggerUrl(); StartDebugger();
} }
private void GetApeDebuggerUrl() protected void DebugStopClick(object sender, EventArgs e)
{ {
if (RE_APE_DEBUGGER_ENABLED.IsMatch(htaccessContent.Text)) var code = htaccessContent.Text;
if (RE_APE_DEBUGGER_ENABLED.IsMatch(code))
{ {
// already disabled, enable it! // alerdy enable, disable it!
ApeDebuggerSecureKey = RE_APE_DEBUGGER_ENABLED.Match(htaccessContent.Text).Groups[2].Value; code = RE_APE_DEBUGGER_ENABLED.Replace(code, "# $1");
} }
ApeDebuggerUrl.Value = ""; htaccessContent.Text = code;
if ( !string.IsNullOrEmpty(ApeDebuggerSecureKey) ) SaveFolder();
StopDebugger();
}
private void GetDebuggerUrl()
{
// TODO: interactive binding selection
if ( !string.IsNullOrEmpty(DebuggerSecureKey) )
{ {
WebSite site = ES.Services.WebServers.GetWebSite(PanelRequest.ItemID); WebSite site = GetWebSite();
if ( null != site) if ( null != site)
{ {
if (site.Bindings.Length > 0) if (site.Bindings.Length > 0)
{ {
ServerBinding serverBinding = site.Bindings[0]; ServerBinding serverBinding = site.Bindings[0];
ApeDebuggerUrl.Value = string.Format("{0}://{1}:{2}{3}?ape_debug={4}", DebuggerUrl = string.Format(
serverBinding.Protocol, "{0}://{1}:{2}{3}/_ape_start_developer_session?ape_debug=secure-key-{4}_{5}",
serverBinding.Host ?? serverBinding.IP, serverBinding.Protocol,
serverBinding.Port, serverBinding.Host ?? serverBinding.IP,
folderPath.SelectedFile.Replace('\\', '/'), serverBinding.Port,
ApeDebuggerSecureKey folderPath.SelectedFile.Replace('\\', '/'),
); DebuggerSecureKey,
DebuggerSessionId
);
DebuggerUrlField.Value = DebuggerUrl;
} }
} }
} }
// TODO: throw error if debugger url is empty
}
private WebSite GetWebSite()
{
WebSite webSite = ViewState["HtaccessWebSite"] as WebSite;
if (null == webSite)
{
webSite = ES.Services.WebServers.GetWebSite(PanelRequest.ItemID);
// TODO: ViewState["HtaccessWebSite"] = webSite;
}
return webSite;
}
private void GetDebuggingPageUrl()
{
if (!string.IsNullOrEmpty(DebuggerSecureKey))
{
WebSite site = GetWebSite();
if (null != site)
{
if (site.Bindings.Length > 0)
{
ServerBinding serverBinding = site.Bindings[0];
DebuggingPageUrl = string.Format(
"{0}://{1}:{2}{3}/?ape_debug=secure-key-{4}_{5}",
serverBinding.Protocol,
serverBinding.Host ?? serverBinding.IP,
serverBinding.Port,
folderPath.SelectedFile.Replace('\\', '/'),
DebuggerSecureKey,
DebuggerSessionId
);
}
}
}
// TODO: throw error if url is empty
}
private void StartDebugger()
{
ButtonDebuggerStart.Visible = false;
ButtonDebuggerStop.Visible = true;
// session id
DebuggerSessionId = new Random().Next(100000000, 999999999).ToString(CultureInfo.InvariantCulture);
// debugger url
GetDebuggerUrl();
// debugging page url
GetDebuggingPageUrl();
// show debugger iframe
DebuggerFramePanel.Visible = true;
DebuggerFrame.Attributes["src"] = DebuggerUrl;
// debugging page link
ContainerLinkDebuggingPage.Visible = true;
LinkDebuggingPage.NavigateUrl = DebuggingPageUrl;
LinkDebuggingPage.Text = DebuggingPageUrl;
}
private void StopDebugger()
{
ButtonDebuggerStart.Visible = true;
ButtonDebuggerStop.Visible = false;
DebuggerUrl = "";
DebuggingPageUrl = "";
DebuggerSessionId = "";
// hide debugger iframe
DebuggerFramePanel.Visible = false;
// hide debugging page link
ContainerLinkDebuggingPage.Visible = false;
} }
protected void btnCancel_Click(object sender, EventArgs e) protected void btnCancel_Click(object sender, EventArgs e)

View file

@ -21,6 +21,15 @@ namespace WebsitePanel.Portal {
/// </remarks> /// </remarks>
protected global::System.Web.UI.WebControls.Label lblFolderName; protected global::System.Web.UI.WebControls.Label lblFolderName;
/// <summary>
/// LabelWebSiteName control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.Label LabelWebSiteName;
/// <summary> /// <summary>
/// folderPath control. /// folderPath control.
/// </summary> /// </summary>
@ -40,22 +49,67 @@ namespace WebsitePanel.Portal {
protected global::System.Web.UI.WebControls.HiddenField contentPath; protected global::System.Web.UI.WebControls.HiddenField contentPath;
/// <summary> /// <summary>
/// ApeDebuggerUrl control. /// DebuggerUrlField control.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// Auto-generated field. /// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file. /// To modify move field declaration from designer file to code-behind file.
/// </remarks> /// </remarks>
protected global::System.Web.UI.WebControls.HiddenField ApeDebuggerUrl; protected global::System.Web.UI.WebControls.HiddenField DebuggerUrlField;
/// <summary> /// <summary>
/// btnApeDebug control. /// ButtonDebuggerStart control.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// Auto-generated field. /// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file. /// To modify move field declaration from designer file to code-behind file.
/// </remarks> /// </remarks>
protected global::System.Web.UI.WebControls.Button btnApeDebug; protected global::System.Web.UI.WebControls.Button ButtonDebuggerStart;
/// <summary>
/// ButtonDebuggerStop control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.Button ButtonDebuggerStop;
/// <summary>
/// ContainerLinkDebuggingPage control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.Label ContainerLinkDebuggingPage;
/// <summary>
/// LinkDebuggingPage control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.HyperLink LinkDebuggingPage;
/// <summary>
/// DebuggerFramePanel control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.Panel DebuggerFramePanel;
/// <summary>
/// DebuggerFrame control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.HtmlControls.HtmlGenericControl DebuggerFrame;
/// <summary> /// <summary>
/// htaccessContent control. /// htaccessContent control.

View file

@ -4929,7 +4929,9 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Content> </Content>
<Content Include="ScheduleTaskControls\App_LocalResources\NotifyOverusedDatabases.ascx.resx" /> <Content Include="ScheduleTaskControls\App_LocalResources\NotifyOverusedDatabases.ascx.resx" />
<Content Include="App_LocalResources\WebSitesEditHeliconApeFolder.ascx.resx" /> <Content Include="App_LocalResources\WebSitesEditHeliconApeFolder.ascx.resx">
<SubType>Designer</SubType>
</Content>
<Content Include="App_LocalResources\WebSitesEditHeliconApeFolderAuth.ascx.resx" /> <Content Include="App_LocalResources\WebSitesEditHeliconApeFolderAuth.ascx.resx" />
<Content Include="App_LocalResources\WebSitesEditHeliconApeGroup.ascx.resx" /> <Content Include="App_LocalResources\WebSitesEditHeliconApeGroup.ascx.resx" />
<Content Include="App_LocalResources\WebSitesEditHeliconApeUser.ascx.resx" /> <Content Include="App_LocalResources\WebSitesEditHeliconApeUser.ascx.resx" />