User:John Ericson/AutoWikiBrowserHttpAuthAndSslToCustomProjects.patch
Adds features:
- Add HTTP AUTH support for Wiki sites that are protected with for example a .htaccess file. A login dialog is displayed for entering username and password if the webserver returnes a HTTP 401 Unauthorized status code.
- Also added SSL support to CustomProjects which allowes you to visit https:// sites. This is done by checking the "Use secure server" setting in Preferences.
Works with latest trunk of AutoWikiBrowser.
Index: AWB/AutoWikiBrowser.csproj
===================================================================
--- AWB/AutoWikiBrowser.csproj (revision 7941)
+++ AWB/AutoWikiBrowser.csproj (working copy)
@@ -100,6 +100,12 @@
<Compile Include="ExitQuestion.Designer.cs">
<DependentUpon>ExitQuestion.cs</DependentUpon>
</Compile>
+ <Compile Include="Login.cs">
+ <SubType>Form</SubType>
+ </Compile>
+ <Compile Include="Login.Designer.cs">
+ <DependentUpon>Login.cs</DependentUpon>
+ </Compile>
<Compile Include="TalkMessage.cs">
<SubType>Form</SubType>
</Compile>
@@ -184,6 +190,9 @@
<SubType>Designer</SubType>
<DependentUpon>CustomModule.cs</DependentUpon>
</EmbeddedResource>
+ <EmbeddedResource Include="Login.resx">
+ <DependentUpon>Login.cs</DependentUpon>
+ </EmbeddedResource>
<EmbeddedResource Include="TalkMessage.resx">
<SubType>Designer</SubType>
<DependentUpon>TalkMessage.cs</DependentUpon>
Index: AWB/Login.cs
===================================================================
--- AWB/Login.cs (revision 0)
+++ AWB/Login.cs (revision 0)
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+using WikiFunctions;
+
+namespace AutoWikiBrowser
+{
+ internal sealed partial class Login : Form
+ {
+ public Login()
+ {
+ InitializeComponent();
+ }
+
+ private void FormOnKeyUp(object sender, KeyEventArgs e)
+ {
+ if (e.KeyCode == Keys.Enter) {
+ CloseForm();
+ }
+ }
+
+ private void label1_Click(object sender, EventArgs e)
+ {
+
+ }
+
+ private void label2_Click(object sender, EventArgs e)
+ {
+
+ }
+
+ private void btnLogin_Click(object sender, EventArgs e)
+ {
+ CloseForm();
+ }
+
+ private void CloseForm() {
+ Variables.HttpAuthUsername = txtUsername.Text;
+ Variables.HttpAuthPassword = txtPassword.Text;
+ Close();
+ }
+
+ private void Login_Load(object sender, EventArgs e) {
+
+ }
+ }
+}
Index: AWB/Login.Designer.cs
===================================================================
--- AWB/Login.Designer.cs (revision 0)
+++ AWB/Login.Designer.cs (revision 0)
@@ -0,0 +1,127 @@
+namespace AutoWikiBrowser
+{
+ partial class Login
+ {
+ /// <summary>
+ /// Required designer variable.
+ /// </summary>
+ private System.ComponentModel.IContainer components = null;
+
+ /// <summary>
+ /// Clean up any resources being used.
+ /// </summary>
+ /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ /// <summary>
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ /// </summary>
+ private void InitializeComponent()
+ {
+ this.txtUsername = new System.Windows.Forms.TextBox();
+ this.lblDescription = new System.Windows.Forms.Label();
+ this.lblUsername = new System.Windows.Forms.Label();
+ this.lblPassword = new System.Windows.Forms.Label();
+ this.txtPassword = new System.Windows.Forms.TextBox();
+ this.btnLogin = new System.Windows.Forms.Button();
+ this.SuspendLayout();
+ //
+ // txtUsername
+ //
+ this.txtUsername.Location = new System.Drawing.Point(93, 62);
+ this.txtUsername.Name = "txtUsername";
+ this.txtUsername.Size = new System.Drawing.Size(152, 20);
+ this.txtUsername.TabIndex = 0;
+ this.txtUsername.KeyUp += new System.Windows.Forms.KeyEventHandler(this.FormOnKeyUp);
+ //
+ // lblDescription
+ //
+ this.lblDescription.Location = new System.Drawing.Point(12, 9);
+ this.lblDescription.Name = "lblDescription";
+ this.lblDescription.Size = new System.Drawing.Size(260, 39);
+ this.lblDescription.TabIndex = 1;
+ this.lblDescription.Text = "This wiki is protected using HTTP AUTH. Please login to proceed.";
+ this.lblDescription.Click += new System.EventHandler(this.label1_Click);
+ //
+ // lblUsername
+ //
+ this.lblUsername.AutoSize = true;
+ this.lblUsername.Location = new System.Drawing.Point(23, 62);
+ this.lblUsername.Name = "lblUsername";
+ this.lblUsername.Size = new System.Drawing.Size(58, 13);
+ this.lblUsername.TabIndex = 2;
+ this.lblUsername.Text = "Username:";
+ this.lblUsername.Click += new System.EventHandler(this.label2_Click);
+ //
+ // lblPassword
+ //
+ this.lblPassword.AutoSize = true;
+ this.lblPassword.Location = new System.Drawing.Point(23, 95);
+ this.lblPassword.Name = "lblPassword";
+ this.lblPassword.Size = new System.Drawing.Size(56, 13);
+ this.lblPassword.TabIndex = 4;
+ this.lblPassword.Text = "Password:";
+ //
+ // txtPassword
+ //
+ this.txtPassword.Location = new System.Drawing.Point(93, 95);
+ this.txtPassword.Name = "txtPassword";
+ this.txtPassword.PasswordChar = '*';
+ this.txtPassword.Size = new System.Drawing.Size(153, 20);
+ this.txtPassword.TabIndex = 3;
+ this.txtPassword.KeyUp += new System.Windows.Forms.KeyEventHandler(this.FormOnKeyUp);
+ //
+ // btnLogin
+ //
+ this.btnLogin.Location = new System.Drawing.Point(170, 140);
+ this.btnLogin.Name = "btnLogin";
+ this.btnLogin.Size = new System.Drawing.Size(75, 23);
+ this.btnLogin.TabIndex = 5;
+ this.btnLogin.Text = "Login";
+ this.btnLogin.UseVisualStyleBackColor = true;
+ this.btnLogin.Click += new System.EventHandler(this.btnLogin_Click);
+ //
+ // Login
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(259, 175);
+ this.Controls.Add(this.btnLogin);
+ this.Controls.Add(this.lblPassword);
+ this.Controls.Add(this.txtPassword);
+ this.Controls.Add(this.lblUsername);
+ this.Controls.Add(this.lblDescription);
+ this.Controls.Add(this.txtUsername);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "Login";
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+ this.Text = "Login";
+ this.Load += new System.EventHandler(this.Login_Load);
+ this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.FormOnKeyUp);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.TextBox txtUsername;
+ private System.Windows.Forms.Label lblDescription;
+ private System.Windows.Forms.Label lblUsername;
+ private System.Windows.Forms.Label lblPassword;
+ private System.Windows.Forms.TextBox txtPassword;
+ private System.Windows.Forms.Button btnLogin;
+ }
+}
\ No newline at end of file
Index: AWB/Login.resx
===================================================================
--- AWB/Login.resx (revision 0)
+++ AWB/Login.resx (revision 0)
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root>
\ No newline at end of file
Index: AWB/Main.cs
===================================================================
--- AWB/Main.cs (revision 7941)
+++ AWB/Main.cs (working copy)
@@ -44,6 +44,7 @@
using WikiFunctions.Controls.Lists;
using AutoWikiBrowser.Plugins;
using System.Web;
+using System.Net;
namespace AutoWikiBrowser
{
@@ -2863,9 +2864,29 @@
SplashScreen.SetProgress(81);
try
{
- //set namespaces
- Variables.SetProject(code, project, customProject, usingSecure);
+ try
+ {
+ //set namespaces
+ Variables.SetProject(code, project, customProject, usingSecure);
+ }
+ catch (WebException ex) {
+ // Check for HTTP 401 error.
+ var resp = (HttpWebResponse)ex.Response;
+ if (resp == null) throw;
+ switch (resp.StatusCode) {
+ case HttpStatusCode.Unauthorized /*401*/:
+ ShowLogin();
+
+ // Reload project.
+ Variables.SetProject(code, project, customProject, usingSecure);
+ break;
+ }
+ }
+ catch (Exception) {
+ throw;
+ }
+
if (Variables.TryLoadingAgainAfterLogin)
{
MessageBox.Show(
@@ -4716,6 +4737,12 @@
chkMinor.Checked = markAllAsMinorToolStripMenuItem.Checked;
}
+ private void ShowLogin()
+ {
+ Login login = new Login();
+ login.ShowDialog(this);
+ }
+
#region Shutdown
private void chkShutdown_CheckedChanged(object sender, EventArgs e)
{
Index: AWB/Preferences.cs
===================================================================
--- AWB/Preferences.cs (revision 7941)
+++ AWB/Preferences.cs (working copy)
@@ -63,6 +63,7 @@
cmboCustomProject.Text = customproj;
PrefUsingSecure = usingSecure;
+ chkUsingSecure.Enabled = (cmboProject.Text != "wikia" ? true : false);
PrefPHP5 = usePHP5;
@@ -187,8 +188,13 @@
cmboCustomProjectChanged(null, null);
chkSupressAWB.Enabled = true;
- chkUsingSecure.Enabled = chkUsingSecure.Checked = false;
+ // Custom server can be SSL enabled.
+ if (prj == ProjectEnum.wikia)
+ {
+ chkUsingSecure.Enabled = chkUsingSecure.Checked = false;
+ }
+
chkPHP5Ext.Enabled = (prj == ProjectEnum.custom);
return;
Index: WikiFunctions/API/ApiEdit.cs
===================================================================
--- WikiFunctions/API/ApiEdit.cs (revision 7941)
+++ WikiFunctions/API/ApiEdit.cs (working copy)
@@ -25,6 +25,7 @@
using System.Xml;
using System.Threading;
using System.Text.RegularExpressions;
+using System.Security.Cryptography.X509Certificates;
namespace WikiFunctions.API
{
@@ -70,7 +71,7 @@
: this()
{
if (string.IsNullOrEmpty(url)) throw new ArgumentException("Invalid URL specified", "url");
- if (!url.StartsWith("http://")) throw new NotSupportedException("Only editing via HTTP is currently supported");
+ //if (!url.StartsWith("http://")) throw new NotSupportedException("Only editing via HTTP is currently supported");
URL = url;
PHP5 = usePHP5;
@@ -317,6 +318,14 @@
Environment.OSVersion.VersionString,
Environment.Version);
+
+ private static bool customXertificateValidation(object sender, X509Certificate cert, X509Chain chain, System.Net.Security.SslPolicyErrors error)
+ {
+ // TODO: Implement better validation. JOE 20110722
+ return true;
+ }
+
+
/// <summary>
///
/// </summary>
@@ -327,6 +336,7 @@
if (Globals.UnitTestMode) throw new Exception("You shouldn't access Wikipedia from unit tests");
ServicePointManager.Expect100Continue = false;
+ ServicePointManager.ServerCertificateValidationCallback += new System.Net.Security.RemoteCertificateValidationCallback(customXertificateValidation);
HttpWebRequest res = (HttpWebRequest)WebRequest.Create(url);
res.ServicePoint.Expect100Continue = false;
res.Expect = "";
@@ -356,6 +366,17 @@
{
Request = req;
+ NetworkCredential login = new NetworkCredential();
+ login.UserName = Variables.HttpAuthUsername;
+ login.Password = Variables.HttpAuthPassword;
+ //login.Domain = "";
+
+ CredentialCache myCache = new CredentialCache();
+ myCache.Add(new Uri(URL), "Basic", login);
+ req.Credentials = myCache;
+
+ req = (HttpWebRequest)SetBasicAuthHeader(req, login.UserName, login.Password);
+
try
{
using (WebResponse resp = req.GetResponse())
@@ -372,7 +393,10 @@
if (resp == null) throw;
switch (resp.StatusCode)
{
- case HttpStatusCode.NotFound /*404*/:
+ case HttpStatusCode.Unauthorized: // 401
+ break;
+
+ case HttpStatusCode.NotFound: // 404
return ""; // emulate the behaviour of Tools.HttpGet()
}
@@ -395,6 +419,14 @@
private string[,] lastPostParameters;
private string lastGetUrl;
+ // Source: http://blog.kowalczyk.info/article/Forcing-basic-http-authentication-for-HttpWebReq.html
+ protected WebRequest SetBasicAuthHeader(WebRequest req, String userName, String userPassword) {
+ string authInfo = userName + ":" + userPassword;
+ authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
+ req.Headers["Authorization"] = "Basic " + authInfo;
+ return req;
+ }
+
/// <summary>
///
/// </summary>
Index: WikiFunctions/Session.cs
===================================================================
--- WikiFunctions/Session.cs (revision 7941)
+++ WikiFunctions/Session.cs (working copy)
@@ -22,6 +22,8 @@
using System.Text.RegularExpressions;
using System.Windows.Forms;
using WikiFunctions.API;
+using System.Net;
+using System.Security.Authentication;
namespace WikiFunctions
{
@@ -192,8 +194,20 @@
{
throw;
}
- catch
+ catch (WebException ex)
{
+ // Check for HTTP 401 error.
+ var resp = (HttpWebResponse)ex.Response;
+ if (resp == null) throw;
+ switch (resp.StatusCode)
+ {
+ case HttpStatusCode.Unauthorized /*401*/:
+ throw;
+ }
+ return false;
+ }
+ catch (Exception)
+ {
Editor = CreateEditor("http://en.wikipedia.org/w/", false);
return false;
}
@@ -407,14 +421,71 @@
{
throw;
}
+ catch (WebException ex)
+ {
+ string message = "";
+
+ if (ex.InnerException != null)
+ {
+ if (ex.InnerException is AuthenticationException)
+ {
+
+ if (message.Equals(""))
+ {
+ message = ex.Message;
+ }
+ else
+ {
+ message += " " + ex.Message;
+ }
+ }
+
+ if (message.Equals(""))
+ {
+ message = ex.InnerException.Message;
+ }
+ else
+ {
+ message += " " + ex.InnerException.Message;
+ }
+ }
+ else
+ {
+ var resp = (HttpWebResponse)ex.Response;
+ if (resp == null) throw;
+
+ // Check for HTTP 401 error.
+ switch (resp.StatusCode)
+ {
+ case HttpStatusCode.Unauthorized: // 401
+ throw;
+ }
+
+ message = ex.Message;
+ }
+
+ MessageBox.Show(message, "Error connecting to wiki", MessageBoxButtons.OK, MessageBoxIcon.Error);
+
+ throw ex;
+ }
catch (Exception ex)
{
//TODO:Better error handling
- string message = ex is WikiUrlException && ex.InnerException != null
- ? ex.InnerException.Message
- : ex.Message;
+ string message = "";
+ if (ex is WikiUrlException)
+ {
+ if (ex.InnerException != null)
+ {
+ message = ex.InnerException.Message;
+ }
+ }
+ else
+ {
+ message = ex.Message;
+ }
+
MessageBox.Show("An error occured while connecting to the server or loading project information from it. " +
"Please make sure that your internet connection works and such combination of project/language exist." +
"\r\nEnter the URL in the format \"en.wikipedia.org/w/\" (including path where index.php and api.php reside)." +
Index: WikiFunctions/SiteInfo.cs
===================================================================
--- WikiFunctions/SiteInfo.cs (revision 7941)
+++ WikiFunctions/SiteInfo.cs (working copy)
@@ -20,6 +20,7 @@
using System.Collections.Generic;
using System.Xml;
using System.Xml.Serialization;
+using System.Net;
using WikiFunctions.API;
namespace WikiFunctions
@@ -71,6 +72,10 @@
{
throw;
}
+ catch (WebException)
+ {
+ throw;
+ }
catch (Exception ex)
{
throw new WikiUrlException(ex);
@@ -289,16 +294,20 @@
#region Helpers
public void OpenPageInBrowser(string title)
{
- if (!Variables.UsingSecure && ArticleUrl.Contains("$1"))
+ if (Variables.IsCustomProject && ArticleUrl.Contains("$1"))
{
string url = ArticleUrl.Replace("$1", Tools.WikiEncode(title));
Tools.OpenURLInBrowser(url);
}
- else
- {
- Tools.OpenArticleInBrowser(title);
- }
+ else if (!Variables.UsingSecure && ArticleUrl.Contains("$1")) {
+ string url = ArticleUrl.Replace("$1", Tools.WikiEncode(title));
+
+ Tools.OpenURLInBrowser(url);
+ }
+ else {
+ Tools.OpenArticleInBrowser(title);
+ }
}
public void OpenPageHistoryInBrowser(string title)
Index: WikiFunctions/Variables.cs
===================================================================
--- WikiFunctions/Variables.cs (revision 7941)
+++ WikiFunctions/Variables.cs (working copy)
@@ -156,7 +156,7 @@
/// Gets a Index URL of the site, e.g. "http://en.wikipedia.org/w/index.php"
/// </summary>
public static string URLIndex
- { get { return (UsingSecure ? URLSecure + URLEnd : URLLong) + IndexPHP; } }
+ { get { return (UsingSecure && !IsCustomProject ? URLSecure + URLEnd : URLLong) + IndexPHP; } }
/// <summary>
/// Gets a Index URL of the site, e.g. "http://en.wikipedia.org/w/api.php"
@@ -164,6 +164,16 @@
public static string URLApi
{ get { return URLLong + ApiPHP; } }
+ public static string HttpAuthUsername {
+ get;
+ set;
+ }
+
+ public static string HttpAuthPassword {
+ get;
+ set;
+ }
+
/// <summary>
/// true if current wiki uses right-to-left writing system
/// </summary>
@@ -505,6 +515,7 @@
if (IsCustomProject)
{
LangCode = "en";
+ URLEnd = "";
int x = customProject.IndexOf('/');
if (x > 0)
@@ -513,7 +524,8 @@
CustomProject = customProject.Substring(0, x);
}
- URL = "http://" + CustomProject;
+ URL = (usingSecure ? "https://" : "http://") + CustomProject;
+
}
else
{
@@ -683,7 +695,10 @@
URLEnd = "/";
break;
case ProjectEnum.custom:
- //URLEnd = "";
+ // Make sure URL ends with / so ApiURL won't become www.customwiki.comapi.php.
+ if (!URL.EndsWith("/")) {
+ URLEnd = "/";
+ }
break;
}
@@ -693,27 +708,26 @@
//HACK:HACK:HACK:HACK:HACK:
if (MainForm != null && MainForm.TheSession != null)
{
- try
- {
- if (!MainForm.TheSession.UpdateProject(false))
- {
- LangCode = "en";
- Project = ProjectEnum.wikipedia;
- SetToEnglish();
- }
- }
- catch (ReadApiDeniedException)
- {
- TryLoadingAgainAfterLogin = true;
- ReloadProjectSettings = new ProjectHoldArea
- {
- projectName = projectName,
- customProject = customProject,
- langCode = langCode,
- usingSecure = usingSecure
- };
- return;
- }
+ try {
+ if (!MainForm.TheSession.UpdateProject(false)) {
+ LangCode = "en";
+ Project = ProjectEnum.wikipedia;
+ SetToEnglish();
+ }
+ }
+ catch (ReadApiDeniedException) {
+ TryLoadingAgainAfterLogin = true;
+ ReloadProjectSettings = new ProjectHoldArea {
+ projectName = projectName,
+ customProject = customProject,
+ langCode = langCode,
+ usingSecure = usingSecure
+ };
+ return;
+ }
+ catch (Exception ex) {
+ throw ex;
+ }
}
RegenerateRegexes();