mirror of
https://github.com/znc/znc.git
synced 2026-08-06 00:43:19 +02:00
Merge pull request #485 from uu1101/uriprefix
Allow serving the web interface under a subpath Fix #480 Fix #138
This commit is contained in:
@@ -25,8 +25,8 @@ class CModule;
|
||||
|
||||
class CHTTPSock : public CSocket {
|
||||
public:
|
||||
CHTTPSock(CModule *pMod);
|
||||
CHTTPSock(CModule *pMod, const CString& sHostname, unsigned short uPort, int iTimeout = 60);
|
||||
CHTTPSock(CModule *pMod, const CString& sURIPrefix);
|
||||
CHTTPSock(CModule *pMod, const CString& sURIPrefix, const CString& sHostname, unsigned short uPort, int iTimeout = 60);
|
||||
virtual ~CHTTPSock();
|
||||
|
||||
// Csocket derived members
|
||||
@@ -76,6 +76,7 @@ public:
|
||||
const CString& GetPass() const;
|
||||
const CString& GetParamString() const;
|
||||
const CString& GetContentType() const;
|
||||
const CString& GetURIPrefix() const;
|
||||
bool IsPost() const;
|
||||
// !Getters
|
||||
|
||||
@@ -121,6 +122,7 @@ protected:
|
||||
bool m_bAcceptGzip;
|
||||
MCString m_msRequestCookies;
|
||||
MCString m_msResponseCookies;
|
||||
CString m_sURIPrefix;
|
||||
};
|
||||
|
||||
#endif // !_HTTPSOCK_H
|
||||
|
||||
@@ -32,11 +32,12 @@ public:
|
||||
ACCEPT_ALL
|
||||
} EAcceptType;
|
||||
|
||||
CListener(unsigned short uPort, const CString& sBindHost, bool bSSL, EAddrType eAddr, EAcceptType eAccept) {
|
||||
CListener(unsigned short uPort, const CString& sBindHost, const CString& sURIPrefix, bool bSSL, EAddrType eAddr, EAcceptType eAccept) {
|
||||
m_uPort = uPort;
|
||||
m_sBindHost = sBindHost;
|
||||
m_bSSL = bSSL;
|
||||
m_eAddr = eAddr;
|
||||
m_sURIPrefix = sURIPrefix;
|
||||
m_pListener = NULL;
|
||||
m_eAcceptType = eAccept;
|
||||
}
|
||||
@@ -49,6 +50,7 @@ public:
|
||||
unsigned short GetPort() const { return m_uPort; }
|
||||
const CString& GetBindHost() const { return m_sBindHost; }
|
||||
CRealListener* GetRealListener() const { return m_pListener; }
|
||||
const CString& GetURIPrefix() const { return m_sURIPrefix; }
|
||||
EAcceptType GetAcceptType() const { return m_eAcceptType; }
|
||||
// !Getters
|
||||
|
||||
@@ -65,13 +67,14 @@ protected:
|
||||
EAddrType m_eAddr;
|
||||
unsigned short m_uPort;
|
||||
CString m_sBindHost;
|
||||
CString m_sURIPrefix;
|
||||
CRealListener* m_pListener;
|
||||
EAcceptType m_eAcceptType;
|
||||
};
|
||||
|
||||
class CRealListener : public CZNCSock {
|
||||
public:
|
||||
CRealListener(CListener *pParent) : CZNCSock(), m_pParent(pParent) {}
|
||||
CRealListener(CListener& listener) : CZNCSock(), m_Listener(listener) {}
|
||||
virtual ~CRealListener();
|
||||
|
||||
virtual bool ConnectionFrom(const CString& sHost, unsigned short uPort);
|
||||
@@ -79,18 +82,19 @@ public:
|
||||
virtual void SockError(int iErrno, const CString& sDescription);
|
||||
|
||||
private:
|
||||
CListener* m_pParent;
|
||||
CListener& m_Listener;
|
||||
};
|
||||
|
||||
class CIncomingConnection : public CZNCSock {
|
||||
public:
|
||||
CIncomingConnection(const CString& sHostname, unsigned short uPort, CListener::EAcceptType eAcceptType);
|
||||
CIncomingConnection(const CString& sHostname, unsigned short uPort, CListener::EAcceptType eAcceptType, const CString& sURIPrefix);
|
||||
virtual ~CIncomingConnection() {}
|
||||
virtual void ReadLine(const CString& sData);
|
||||
virtual void ReachedMaxBuffer();
|
||||
|
||||
private:
|
||||
CListener::EAcceptType m_eAcceptType;
|
||||
const CString m_sURIPrefix;
|
||||
};
|
||||
|
||||
#endif // !_LISTENER_H
|
||||
|
||||
@@ -117,7 +117,7 @@ public:
|
||||
PAGE_DONE // all stuff has been done
|
||||
};
|
||||
|
||||
CWebSock();
|
||||
CWebSock(const CString& sURIPrefix);
|
||||
virtual ~CWebSock();
|
||||
|
||||
virtual bool ForceLogin();
|
||||
|
||||
@@ -478,6 +478,17 @@ public:
|
||||
*/
|
||||
CString TrimSuffix_n(const CString& sSuffix) const;
|
||||
|
||||
/** Check whether the string starts with a given prefix.
|
||||
* @param sPrefix The prefix.
|
||||
* @return True if the string starts with prefix, false otherwise.
|
||||
*/
|
||||
bool StartsWith(const CString& sPrefix) const;
|
||||
/** Check whether the string ends with a given suffix.
|
||||
* @param sSuffix The suffix.
|
||||
* @return True if the string ends with suffix, false otherwise.
|
||||
*/
|
||||
bool EndsWith(const CString& sSuffix) const;
|
||||
|
||||
/** Remove characters from the beginning of this string.
|
||||
* @param uLen The number of characters to remove.
|
||||
* @return true if this string was modified.
|
||||
|
||||
+2
-1
@@ -154,7 +154,8 @@ public:
|
||||
// Listener yummy
|
||||
CListener* FindListener(u_short uPort, const CString& BindHost, EAddrType eAddr);
|
||||
bool AddListener(CListener*);
|
||||
bool AddListener(unsigned short uPort, const CString& sBindHost, bool bSSL,
|
||||
bool AddListener(unsigned short uPort, const CString& sBindHost,
|
||||
const CString& sURIPrefix, bool bSSL,
|
||||
EAddrType eAddr, CListener::EAcceptType eAccept, CString& sError);
|
||||
bool DelListener(CListener*);
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<? INC Header.tmpl ?>
|
||||
|
||||
<? IF Cert ?>
|
||||
<p>You already have a certificate set, use the form below to overwrite the current certificate. Alternatively click <a href="<? VAR ModPath ?>delete">here</a> to <a href="<? VAR ModPath ?>delete">delete</a> your certificate.</p>
|
||||
<p>You already have a certificate set, use the form below to overwrite the current certificate. Alternatively click <a href="<? VAR URIPrefix TOP ?><? VAR ModPath ?>delete">here</a> to <a href="<? VAR URIPrefix TOP ?><? VAR ModPath ?>delete">delete</a> your certificate.</p>
|
||||
<? ELSE ?>
|
||||
<p>You do not have a cert.</p>
|
||||
<? ENDIF ?>
|
||||
|
||||
<form method="post" action="<? VAR ModPath ?>update">
|
||||
<form method="post" action="<? VAR URIPrefix TOP ?><? VAR ModPath ?>update">
|
||||
<? INC _csrf_check.tmpl ?>
|
||||
<div class="section">
|
||||
<h3>Certificate</h3>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<? INC Header.tmpl ?>
|
||||
|
||||
<form method="post" action="<? VAR ModPath ?>add">
|
||||
<form method="post" action="<? VAR URIPrefix TOP ?><? VAR ModPath ?>add">
|
||||
<? INC _csrf_check.tmpl ?>
|
||||
<div class="section">
|
||||
<h3>Add A Note</h3>
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
<td><? VAR LastSeen DEFAULT="- unknown -" ?></td>
|
||||
<td><? VAR Info ?></td>
|
||||
<? IF WebAdminLoaded TOP ?><td><span class="nowrap">
|
||||
[<a href="/mods/global/webadmin/edituser?user=<?VAR Username ESC=URL?>">Edit</a>]
|
||||
<? IF !IsSelf ?>[<a href="/mods/global/webadmin/deluser?user=<?VAR Username ESC=URL?>">Delete</a>]<? ENDIF ?>
|
||||
[<a href="<? VAR URIPrefix TOP ?>/mods/global/webadmin/edituser?user=<?VAR Username ESC=URL?>">Edit</a>]
|
||||
<? IF !IsSelf ?>[<a href="<? VAR URIPrefix TOP ?>/mods/global/webadmin/deluser?user=<?VAR Username ESC=URL?>">Delete</a>]<? ENDIF ?>
|
||||
</span></td><? ENDIF ?>
|
||||
</tr>
|
||||
<? ENDLOOP ?>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<? INC Header.tmpl ?>
|
||||
|
||||
<form method="post" action="<? VAR ModPath ?>addnote">
|
||||
<form method="post" action="<? VAR URIPrefix TOP ?><? VAR ModPath ?>addnote">
|
||||
<? INC _csrf_check.tmpl ?>
|
||||
<div class="section">
|
||||
<h3>Add A Note</h3>
|
||||
@@ -37,7 +37,7 @@
|
||||
<tbody>
|
||||
<? LOOP NotesLoop ?>
|
||||
<tr class="<? IF __EVEN__ ?>evenrow<? ELSE ?>oddrow<? ENDIF ?>">
|
||||
<td><a href="<? VAR ModPath TOP ?>delnote?key=<? VAR Key ESC=URL,HTML ?>"><img src="<? VAR ModFilesPath TOP ?>trash.gif" alt="[del]" /></a></td>
|
||||
<td><a href="<? VAR URIPrefix TOP ?><? VAR ModPath TOP ?>delnote?key=<? VAR Key ESC=URL,HTML ?>"><img src="<? VAR URIPrefix TOP ?><? VAR ModFilesPath TOP ?>trash.gif" alt="[del]" /></a></td>
|
||||
<td><? VAR Key ?></td>
|
||||
<td><? VAR Note ?></td>
|
||||
</tr>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<? INC Header.tmpl ?>
|
||||
|
||||
<form method="post" action="<? VAR ModPath ?>">
|
||||
<form method="post" action="<? VAR URIPrefix TOP ?><? VAR ModPath ?>">
|
||||
<? INC _csrf_check.tmpl ?>
|
||||
<div class="section">
|
||||
<h3>Perform</h3>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<? ADDROW JSLoop HREF=/modfiles/user/send_raw/select.js ?>
|
||||
<? INC Header.tmpl ?>
|
||||
|
||||
<form method="post" action="<? VAR ModPath ?>">
|
||||
<form method="post" action="<? VAR URIPrefix TOP ?><? VAR ModPath ?>">
|
||||
<? INC _csrf_check.tmpl ?>
|
||||
|
||||
<div class="section">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<? INC Header.tmpl ?>
|
||||
|
||||
<form action="" method="post">
|
||||
<form method="post" action="<? VAR URIPrefix TOP ?><? VAR ModPath TOP ?>">
|
||||
<? INC _csrf_check.tmpl ?>
|
||||
<table class="data">
|
||||
<thead>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<? INC Header.tmpl ?>
|
||||
|
||||
<form action="<? IF Edit ?>editchan<? ELSE ?>addchan<? ENDIF ?>" method="post">
|
||||
<form action="<? VAR URIPrefix TOP ?><? VAR ModPath TOP ?><? IF Edit ?>editchan<? ELSE ?>addchan<? ENDIF ?>" method="post">
|
||||
<? INC _csrf_check.tmpl ?>
|
||||
<div class="section">
|
||||
<input type="hidden" name="submitted" value="1" />
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<p>To connect to this network from your IRC client, you can set the server password field as follows: <code><? VAR Username ?>/<? IF Edit ?><? VAR Name ?><? ELSE ?><network><? ENDIF ?>:<password></code> or username field as <code><? VAR Username ?>/<? IF Edit ?><? VAR Name ?><? ELSE ?><network><? ENDIF ?></code></p>
|
||||
</div>
|
||||
|
||||
<form action="<? IF Edit ?>editnetwork<? ELSE ?>addnetwork<? ENDIF ?>" method="post">
|
||||
<form action="<? VAR URIPrefix TOP ?><? VAR ModPath TOP ?><? IF Edit ?>editnetwork<? ELSE ?>addnetwork<? ENDIF ?>" method="post">
|
||||
<? INC _csrf_check.tmpl ?>
|
||||
<div class="section">
|
||||
<input type="hidden" name="submitted" value="1" />
|
||||
@@ -116,7 +116,7 @@
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<td>[<a href="addchan?user=<? VAR Username ESC=URL ?>&network=<? VAR Name ESC=URL ?>">Add</a>]</td>
|
||||
<td>[<a href="<? VAR URIPrefix TOP ?><? VAR ModPath TOP ?>addchan?user=<? VAR Username ESC=URL ?>&network=<? VAR Name ESC=URL ?>">Add</a>]</td>
|
||||
<? IF ChannelLoop ?>
|
||||
<td>Save</td>
|
||||
<td>Name</td>
|
||||
@@ -135,7 +135,7 @@
|
||||
<tr class="<? IF __EVEN__ ?>evenrow<? ELSE ?>oddrow<? ENDIF ?>">
|
||||
<td>
|
||||
<input type="hidden" name="channel" value="<? VAR Name ?>" />
|
||||
[<a href="editchan?user=<? VAR Username ESC=URL ?>&network=<? VAR Network ESC=URL ?>&name=<? VAR Name ESC=URL ?>">Edit</a>] [<a href="delchan?user=<? VAR Username ESC=URL ?>&network=<? VAR Network ESC=URL ?>&name=<? VAR Name ESC=URL ?>">Del</a>]
|
||||
[<a href="<? VAR URIPrefix TOP ?><? VAR ModPath TOP ?>editchan?user=<? VAR Username ESC=URL ?>&network=<? VAR Network ESC=URL ?>&name=<? VAR Name ESC=URL ?>">Edit</a>] [<a href="<? VAR URIPrefix TOP ?><? VAR ModPath TOP ?>delchan?user=<? VAR Username ESC=URL ?>&network=<? VAR Network ESC=URL ?>&name=<? VAR Name ESC=URL ?>">Del</a>]
|
||||
</td>
|
||||
<td><input type="checkbox" name="save_<? VAR Name ?>"<? IF InConfig ?> checked="checked"<? ENDIF ?> /></td>
|
||||
<td><? VAR Name ?></td>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<? INC Header.tmpl ?>
|
||||
|
||||
<form action="<? IF Edit ?>edituser<? ELSE ?>adduser<? ENDIF ?>" method="post">
|
||||
<form action="<? VAR URIPrefix TOP ?><? VAR ModPath TOP ?><? IF Edit ?>edituser<? ELSE ?>adduser<? ENDIF ?>" method="post">
|
||||
<? INC _csrf_check.tmpl ?>
|
||||
<div class="section">
|
||||
<input type="hidden" name="submitted" value="1" />
|
||||
@@ -128,7 +128,7 @@
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<td>[<a href="addnetwork?user=<? VAR Username ESC=URL ?>">Add</a>]</td>
|
||||
<td>[<a href="<? VAR URIPrefix TOP ?><? VAR ModPath TOP ?>addnetwork?user=<? VAR Username ESC=URL ?>">Add</a>]</td>
|
||||
<? IF NetworkLoop ?>
|
||||
<td>Name</td>
|
||||
<td>Clients</td>
|
||||
@@ -145,7 +145,7 @@
|
||||
<tr class="<? IF __EVEN__ ?>evenrow<? ELSE ?>oddrow<? ENDIF ?>">
|
||||
<td>
|
||||
<input type="hidden" name="network" value="<? VAR Name ?>" />
|
||||
[<a href="editnetwork?user=<? VAR Username ESC=URL ?>&network=<? VAR Name ESC=URL ?>">Edit</a>] [<a href="delnetwork?user=<? VAR Username ESC=URL ?>&name=<? VAR Name ESC=URL ?>">Del</a>]
|
||||
[<a href="<? VAR URIPrefix TOP ?><? VAR ModPath TOP ?>editnetwork?user=<? VAR Username ESC=URL ?>&network=<? VAR Name ESC=URL ?>">Edit</a>] [<a href="<? VAR URIPrefix TOP ?><? VAR ModPath TOP ?>delnetwork?user=<? VAR Username ESC=URL ?>&name=<? VAR Name ESC=URL ?>">Del</a>]
|
||||
</td>
|
||||
<td><? VAR Name ?></td>
|
||||
<td><? VAR Clients ?></td>
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
<div class="sectionbody">
|
||||
<div class="subsection">
|
||||
Are you sure you want to delete "<? VAR Username ?>/<? VAR Network ?>"?
|
||||
<form action="delnetwork" method="post">
|
||||
<form action="<? VAR URIPrefix TOP ?><? VAR ModPath TOP ?>delnetwork" method="post">
|
||||
<? INC _csrf_check.tmpl ?>
|
||||
<input type="hidden" name="user" value="<? VAR Username ?>" />
|
||||
<input type="hidden" name="name" value="<? VAR Network ?>" />
|
||||
<div class="yesnobutton"><input type="submit" value="Yes" /></div>
|
||||
</form>
|
||||
<form action="listusers" method="get">
|
||||
<form action="<? VAR URIPrefix TOP ?><? VAR ModPath TOP ?>listusers" method="get">
|
||||
<div class="yesnobutton"><input type="submit" value="No" /></div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
<div class="sectionbody">
|
||||
<div class="subsection">
|
||||
Are you sure you want to delete "<? VAR Username ?>"?
|
||||
<form action="deluser" method="post">
|
||||
<form action="<? VAR URIPrefix TOP ?><? VAR ModPath TOP ?>deluser" method="post">
|
||||
<? INC _csrf_check.tmpl ?>
|
||||
<input type="hidden" name="submitted" value="1" />
|
||||
<input type="hidden" name="user" value="<? VAR Username ?>" />
|
||||
<div class="yesnobutton"><input type="submit" value="Yes" /></div>
|
||||
</form>
|
||||
<form action="listusers" method="get">
|
||||
<form action="<? VAR URIPrefix TOP ?><? VAR ModPath TOP ?>listusers" method="get">
|
||||
<div class="yesnobutton"><input type="submit" value="No" /></div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<?IF !UserLoop?>
|
||||
<div class="textsection">
|
||||
There are no users defined. Click <a href="adduser">here</a> if you would like to add one.
|
||||
There are no users defined. Click <a href="<? VAR URIPrefix TOP ?><? VAR ModPath TOP ?>adduser">here</a> if you would like to add one.
|
||||
</div>
|
||||
<?ELSE?>
|
||||
<div class="toptable">
|
||||
@@ -21,9 +21,9 @@
|
||||
<tr class="<?IF __EVEN__?>evenrow<?ELSE?>oddrow<?ENDIF?>">
|
||||
<td>
|
||||
<span class="nowrap">
|
||||
[<a href="edituser?user=<?VAR Username ESC=URL?>">Edit</a>]
|
||||
[<a href="adduser?clone=<? VAR Username ESC=URL ?>" alt="Clone <? VAR Username ESC=URL ?>">Clone</a>]
|
||||
<? IF !IsSelf ?>[<a href="deluser?user=<?VAR Username ESC=URL?>">Delete</a>]<? ENDIF ?>
|
||||
[<a href="<? VAR URIPrefix TOP ?><? VAR ModPath TOP ?>edituser?user=<?VAR Username ESC=URL?>">Edit</a>]
|
||||
[<a href="<? VAR URIPrefix TOP ?><? VAR ModPath TOP ?>adduser?clone=<? VAR Username ESC=URL ?>" alt="Clone <? VAR Username ESC=URL ?>">Clone</a>]
|
||||
<? IF !IsSelf ?>[<a href="<? VAR URIPrefix TOP ?><? VAR ModPath TOP ?>deluser?user=<?VAR Username ESC=URL?>">Delete</a>]<? ENDIF ?>
|
||||
</span>
|
||||
</td>
|
||||
<td><? VAR Username ?></td>
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
<td>IPv6</td>
|
||||
<td>IRC</td>
|
||||
<td>Web</td>
|
||||
<td>URIPrefix</td>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
@@ -38,9 +39,10 @@
|
||||
<td>
|
||||
<div class="checkbox"><input type="checkbox" disabled="disabled" <? IF IsWeb ?>checked="checked"<? ENDIF ?>/></div>
|
||||
</td>
|
||||
<td><? VAR URIPrefix ?></td>
|
||||
<td>
|
||||
<? IF SuggestDeletion ?>
|
||||
<form action="del_listener" method="post">
|
||||
<form action="<? VAR URIPrefix TOP ?><? VAR ModPath TOP ?>del_listener" method="post">
|
||||
<? INC _csrf_check.tmpl ?>
|
||||
<input name="host" type="hidden" value="<? VAR BindHost ?>"/>
|
||||
<input name="port" type="hidden" value="<? VAR Port ?>"/>
|
||||
@@ -53,15 +55,16 @@
|
||||
</tr>
|
||||
<? ENDLOOP ?>
|
||||
<tr>
|
||||
<form action="add_listener" method="post">
|
||||
<form action="<? VAR URIPrefix TOP ?><? VAR ModPath TOP ?>add_listener" method="post">
|
||||
<? INC _csrf_check.tmpl ?>
|
||||
<td><input name="port" type="number" min="1" max="65535" class="number"/></td>
|
||||
<td><input name="host" type="text" value="*" class="third"/></td>
|
||||
<td><input name="host" type="text" value="*" class="sixth"/></td>
|
||||
<td><div class="checkbox"><input name="ssl" type="checkbox"/></div></td>
|
||||
<td><div class="checkbox"><input name="ipv4" type="checkbox" checked="checked"/></div></td>
|
||||
<td><div class="checkbox"><input name="ipv6" type="checkbox" checked="checked"/></div></td>
|
||||
<td><div class="checkbox"><input name="irc" type="checkbox" checked="checked"/></div></td>
|
||||
<td><div class="checkbox"><input name="web" type="checkbox" checked="checked"/></div></td>
|
||||
<td><input name="uriprefix" type="text" value="" class="sixth"/></td>
|
||||
<td><input type="submit" value="Add"/></td>
|
||||
</form>
|
||||
</tr>
|
||||
@@ -71,7 +74,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form action="settings" method="post">
|
||||
<form action="<? VAR URIPrefix TOP ?><? VAR ModPath TOP ?>settings" method="post">
|
||||
<? INC _csrf_check.tmpl ?>
|
||||
<input type="hidden" name="submitted" value="1" />
|
||||
|
||||
|
||||
+14
-10
@@ -101,6 +101,7 @@ public:
|
||||
CString sArgs(sArgStr);
|
||||
CString sPort;
|
||||
CString sListenHost;
|
||||
CString sURIPrefix;
|
||||
|
||||
while (sArgs.Left(1) == "-") {
|
||||
CString sOpt = sArgs.Token(0);
|
||||
@@ -150,7 +151,7 @@ public:
|
||||
}
|
||||
|
||||
// Now turn that into a listener instance
|
||||
CListener *pListener = new CListener(uPort, sListenHost, bSSL,
|
||||
CListener *pListener = new CListener(uPort, sListenHost, sURIPrefix, bSSL,
|
||||
(!bIPv6 ? ADDR_IPV4ONLY : ADDR_ALL), CListener::ACCEPT_HTTP);
|
||||
|
||||
if (!pListener->Listen()) {
|
||||
@@ -542,7 +543,7 @@ public:
|
||||
WebSock.PrintErrorPage("Please don't delete yourself, suicide is not the answer!");
|
||||
return true;
|
||||
} else if (CZNC::Get().DeleteUser(sUser)) {
|
||||
WebSock.Redirect("listusers");
|
||||
WebSock.Redirect(GetWebPath() + "listusers");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -710,7 +711,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
WebSock.Redirect("editnetwork?user=" + pUser->GetUserName().Escape_n(CString::EURL) + "&network=" + pNetwork->GetName().Escape_n(CString::EURL));
|
||||
WebSock.Redirect(GetWebPath() + "editnetwork?user=" + pUser->GetUserName().Escape_n(CString::EURL) + "&network=" + pNetwork->GetName().Escape_n(CString::EURL));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -984,7 +985,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
WebSock.Redirect("edituser?user=" + pUser->GetUserName().Escape_n(CString::EURL));
|
||||
WebSock.Redirect(GetWebPath() + "edituser?user=" + pUser->GetUserName().Escape_n(CString::EURL));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1020,7 +1021,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
WebSock.Redirect("edituser?user=" + pUser->GetUserName().Escape_n(CString::EURL));
|
||||
WebSock.Redirect(GetWebPath() + "edituser?user=" + pUser->GetUserName().Escape_n(CString::EURL));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1040,7 +1041,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
WebSock.Redirect("editnetwork?user=" + pNetwork->GetUser()->GetUserName().Escape_n(CString::EURL) + "&network=" + pNetwork->GetName().Escape_n(CString::EURL));
|
||||
WebSock.Redirect(GetWebPath() + "editnetwork?user=" + pNetwork->GetUser()->GetUserName().Escape_n(CString::EURL) + "&network=" + pNetwork->GetName().Escape_n(CString::EURL));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1320,9 +1321,9 @@ public:
|
||||
}
|
||||
|
||||
if (!spSession->IsAdmin()) {
|
||||
WebSock.Redirect("edituser");
|
||||
WebSock.Redirect(GetWebPath() + "edituser");
|
||||
} else {
|
||||
WebSock.Redirect("listusers");
|
||||
WebSock.Redirect(GetWebPath() + "listusers");
|
||||
}
|
||||
|
||||
/* we don't want the template to be printed while we redirect */
|
||||
@@ -1420,6 +1421,7 @@ public:
|
||||
bool AddListener(CWebSock& WebSock, CTemplate& Tmpl) {
|
||||
unsigned short uPort = WebSock.GetParam("port").ToUShort();
|
||||
CString sHost = WebSock.GetParam("host");
|
||||
CString sURIPrefix = WebSock.GetParam("uriprefix");
|
||||
if (sHost == "*") sHost = "";
|
||||
bool bSSL = WebSock.GetParam("ssl").ToBool();
|
||||
bool bIPv4 = WebSock.GetParam("ipv4").ToBool();
|
||||
@@ -1460,7 +1462,7 @@ public:
|
||||
}
|
||||
|
||||
CString sMessage;
|
||||
if (CZNC::Get().AddListener(uPort, sHost, bSSL, eAddr, eAccept, sMessage)) {
|
||||
if (CZNC::Get().AddListener(uPort, sHost, sURIPrefix, bSSL, eAddr, eAccept, sMessage)) {
|
||||
if (!sMessage.empty()) {
|
||||
WebSock.GetSession()->AddSuccess(sMessage);
|
||||
}
|
||||
@@ -1545,6 +1547,8 @@ public:
|
||||
l["IsWeb"] = CString(pListener->GetAcceptType() != CListener::ACCEPT_IRC);
|
||||
l["IsIRC"] = CString(pListener->GetAcceptType() != CListener::ACCEPT_HTTP);
|
||||
|
||||
l["URIPrefix"] = pListener->GetURIPrefix() + "/";
|
||||
|
||||
// simple protection for user from shooting his own foot
|
||||
// TODO check also for hosts/families
|
||||
// such check is only here, user still can forge HTTP request to delete web port
|
||||
@@ -1688,7 +1692,7 @@ public:
|
||||
WebSock.GetSession()->AddError("Settings changed, but config was not written");
|
||||
}
|
||||
|
||||
WebSock.Redirect("settings");
|
||||
WebSock.Redirect(GetWebPath() + "settings");
|
||||
/* we don't want the template to be printed while we redirect */
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1430,6 +1430,7 @@ void CClient::UserPortCommand(CString& sLine) {
|
||||
Table.AddColumn("SSL");
|
||||
Table.AddColumn("Proto");
|
||||
Table.AddColumn("IRC/Web");
|
||||
Table.AddColumn("URIPrefix");
|
||||
|
||||
vector<CListener*>::const_iterator it;
|
||||
const vector<CListener*>& vpListeners = CZNC::Get().GetListeners();
|
||||
@@ -1445,6 +1446,7 @@ void CClient::UserPortCommand(CString& sLine) {
|
||||
|
||||
CListener::EAcceptType eAccept = (*it)->GetAcceptType();
|
||||
Table.SetCell("IRC/Web", (eAccept == CListener::ACCEPT_ALL ? "All" : (eAccept == CListener::ACCEPT_IRC ? "IRC" : "Web")));
|
||||
Table.SetCell("URIPrefix", (*it)->GetURIPrefix() + "/");
|
||||
}
|
||||
|
||||
PutStatus(Table);
|
||||
@@ -1483,12 +1485,13 @@ void CClient::UserPortCommand(CString& sLine) {
|
||||
}
|
||||
|
||||
if (sPort.empty() || sAddr.empty() || sAccept.empty()) {
|
||||
PutStatus("Usage: AddPort <[+]port> <ipv4|ipv6|all> <web|irc|all> [bindhost]");
|
||||
PutStatus("Usage: AddPort <[+]port> <ipv4|ipv6|all> <web|irc|all> [bindhost [uriprefix]]");
|
||||
} else {
|
||||
bool bSSL = (sPort.Left(1).Equals("+"));
|
||||
const CString sBindHost = sLine.Token(4);
|
||||
const CString sURIPrefix = sLine.Token(5);
|
||||
|
||||
CListener* pListener = new CListener(uPort, sBindHost, bSSL, eAddr, eAccept);
|
||||
CListener* pListener = new CListener(uPort, sBindHost, sURIPrefix, bSSL, eAddr, eAccept);
|
||||
|
||||
if (!pListener->Listen()) {
|
||||
delete pListener;
|
||||
|
||||
+28
-9
@@ -28,11 +28,11 @@ using std::set;
|
||||
|
||||
#define MAX_POST_SIZE 1024 * 1024
|
||||
|
||||
CHTTPSock::CHTTPSock(CModule *pMod) : CSocket(pMod) {
|
||||
CHTTPSock::CHTTPSock(CModule *pMod, const CString& sURIPrefix) : CSocket(pMod), m_sURIPrefix(sURIPrefix) {
|
||||
Init();
|
||||
}
|
||||
|
||||
CHTTPSock::CHTTPSock(CModule *pMod, const CString& sHostname, unsigned short uPort, int iTimeout) : CSocket(pMod, sHostname, uPort, iTimeout) {
|
||||
CHTTPSock::CHTTPSock(CModule *pMod, const CString& sURIPrefix, const CString& sHostname, unsigned short uPort, int iTimeout) : CSocket(pMod, sHostname, uPort, iTimeout), m_sURIPrefix(sURIPrefix) {
|
||||
Init();
|
||||
}
|
||||
|
||||
@@ -214,7 +214,16 @@ CString CHTTPSock::GetDate(time_t stamp) {
|
||||
void CHTTPSock::GetPage() {
|
||||
DEBUG("Page Request [" << m_sURI << "] ");
|
||||
|
||||
OnPageRequest(m_sURI);
|
||||
// Check that the requested path starts with the prefix. Strip it if so.
|
||||
if (!m_sURI.TrimPrefix(m_sURIPrefix)) {
|
||||
DEBUG("INVALID path => Does not start with prefix [" + m_sURIPrefix + "]");
|
||||
DEBUG("Expected prefix: " << m_sURIPrefix);
|
||||
DEBUG("Requested path: " << m_sURI);
|
||||
Redirect(m_sURI);
|
||||
} else {
|
||||
OnPageRequest(m_sURI);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef HAVE_ZLIB
|
||||
@@ -495,6 +504,10 @@ const CString& CHTTPSock::GetParamString() const {
|
||||
return m_sPostData;
|
||||
}
|
||||
|
||||
const CString& CHTTPSock::GetURIPrefix() const {
|
||||
return m_sURIPrefix;
|
||||
}
|
||||
|
||||
bool CHTTPSock::HasParam(const CString& sName, bool bPost) const {
|
||||
if (bPost)
|
||||
return (m_msvsPOSTParams.find(sName) != m_msvsPOSTParams.end());
|
||||
@@ -712,13 +725,19 @@ bool CHTTPSock::Redirect(const CString& sURL) {
|
||||
if (SentHeader()) {
|
||||
DEBUG("Redirect() - Header was already sent");
|
||||
return false;
|
||||
} else if(!sURL.StartsWith("/")) {
|
||||
// HTTP/1.1 only admits absolute URIs for the Location header.
|
||||
DEBUG("Redirect to relative URI [" + sURL + "] is not allowed.");
|
||||
return false;
|
||||
} else {
|
||||
CString location = m_sURIPrefix + sURL;
|
||||
|
||||
DEBUG("- Redirect to [" << location << "] with prefix [" + m_sURIPrefix + "]");
|
||||
AddHeader("Location", location);
|
||||
PrintErrorPage(302, "Found", "The document has moved <a href=\"" + location.Escape_n(CString::EHTML) + "\">here</a>.");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
DEBUG("- Redirect to [" << sURL << "]");
|
||||
AddHeader("Location", sURL);
|
||||
PrintErrorPage(302, "Found", "The document has moved <a href=\"" + sURL.Escape_n(CString::EHTML) + "\">here</a>.");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CHTTPSock::Connected() {
|
||||
|
||||
+7
-5
@@ -27,7 +27,7 @@ bool CListener::Listen() {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_pListener = new CRealListener(this);
|
||||
m_pListener = new CRealListener(*this);
|
||||
|
||||
bool bSSL = false;
|
||||
#ifdef HAVE_LIBSSL
|
||||
@@ -50,7 +50,7 @@ void CListener::ResetRealListener() {
|
||||
}
|
||||
|
||||
CRealListener::~CRealListener() {
|
||||
m_pParent->ResetRealListener();
|
||||
m_Listener.ResetRealListener();
|
||||
}
|
||||
|
||||
bool CRealListener::ConnectionFrom(const CString& sHost, unsigned short uPort) {
|
||||
@@ -60,7 +60,9 @@ bool CRealListener::ConnectionFrom(const CString& sHost, unsigned short uPort) {
|
||||
}
|
||||
|
||||
Csock* CRealListener::GetSockObj(const CString& sHost, unsigned short uPort) {
|
||||
CIncomingConnection *pClient = new CIncomingConnection(sHost, uPort, m_pParent->GetAcceptType());
|
||||
CIncomingConnection *pClient = new CIncomingConnection(sHost, uPort,
|
||||
m_Listener.GetAcceptType(),
|
||||
m_Listener.GetURIPrefix());
|
||||
if (CZNC::Get().AllowConnectionFrom(sHost)) {
|
||||
GLOBALMODULECALL(OnClientConnect(pClient, sHost, uPort), NOTHING);
|
||||
} else {
|
||||
@@ -83,7 +85,7 @@ void CRealListener::SockError(int iErrno, const CString& sDescription) {
|
||||
}
|
||||
}
|
||||
|
||||
CIncomingConnection::CIncomingConnection(const CString& sHostname, unsigned short uPort, CListener::EAcceptType eAcceptType) : CZNCSock(sHostname, uPort) {
|
||||
CIncomingConnection::CIncomingConnection(const CString& sHostname, unsigned short uPort, CListener::EAcceptType eAcceptType, const CString& sURIPrefix) : CZNCSock(sHostname, uPort), m_sURIPrefix(sURIPrefix) {
|
||||
m_eAcceptType = eAcceptType;
|
||||
// The socket will time out in 120 secs, no matter what.
|
||||
// This has to be fixed up later, if desired.
|
||||
@@ -141,7 +143,7 @@ void CIncomingConnection::ReadLine(const CString& sLine) {
|
||||
return;
|
||||
}
|
||||
|
||||
pSock = new CWebSock();
|
||||
pSock = new CWebSock(m_sURIPrefix);
|
||||
CZNC::Get().GetManager().SwapSockByAddr(pSock, this);
|
||||
|
||||
// And don't forget to give it some sane name / timeout
|
||||
|
||||
+3
-1
@@ -185,7 +185,7 @@ void CWebAuth::Invalidate() {
|
||||
m_pWebSock = NULL;
|
||||
}
|
||||
|
||||
CWebSock::CWebSock() : CHTTPSock(NULL) {
|
||||
CWebSock::CWebSock(const CString& sURIPrefix) : CHTTPSock(NULL, sURIPrefix) {
|
||||
m_bPathsSet = false;
|
||||
|
||||
m_Template.AddTagHandler(new CZNCTagHandler(*this));
|
||||
@@ -325,6 +325,7 @@ void CWebSock::SetVars() {
|
||||
m_Template["Version"] = CZNC::GetVersion();
|
||||
m_Template["SkinName"] = GetSkinName();
|
||||
m_Template["_CSRF_Check"] = GetCSRFCheck();
|
||||
m_Template["URIPrefix"] = GetURIPrefix();
|
||||
|
||||
if (GetSession()->IsAdmin()) {
|
||||
m_Template["IsAdmin"] = "true";
|
||||
@@ -473,6 +474,7 @@ CWebSock::EPageReqResult CWebSock::PrintStaticFile(const CString& sPath, CString
|
||||
|
||||
CWebSock::EPageReqResult CWebSock::PrintTemplate(const CString& sPageName, CString& sPageRet, CModule* pModule) {
|
||||
SetVars();
|
||||
|
||||
m_Template["PageName"] = sPageName;
|
||||
|
||||
if (pModule) {
|
||||
|
||||
@@ -1092,6 +1092,14 @@ bool CString::TrimSuffix(const CString& sSuffix) {
|
||||
}
|
||||
}
|
||||
|
||||
bool CString::StartsWith(const CString& sPrefix) const {
|
||||
return Left(sPrefix.length()).Equals(sPrefix);
|
||||
}
|
||||
|
||||
bool CString::EndsWith(const CString& sSuffix) const {
|
||||
return Right(sSuffix.length()).Equals(sSuffix);
|
||||
}
|
||||
|
||||
|
||||
CString CString::TrimPrefix_n(const CString& sPrefix) const {
|
||||
CString sRet = *this;
|
||||
|
||||
+24
-6
@@ -450,6 +450,7 @@ bool CZNC::WriteConfig() {
|
||||
CConfig listenerConfig;
|
||||
|
||||
listenerConfig.AddKeyValuePair("Host", pListener->GetBindHost());
|
||||
listenerConfig.AddKeyValuePair("URIPrefix", pListener->GetURIPrefix() + "/");
|
||||
listenerConfig.AddKeyValuePair("Port", CString(pListener->GetPort()));
|
||||
|
||||
listenerConfig.AddKeyValuePair("IPv4", CString(pListener->GetAddrType() != ADDR_IPV6ONLY));
|
||||
@@ -578,6 +579,7 @@ bool CZNC::WriteNewConfig(const CString& sConfigFile) {
|
||||
bool b6 = false;
|
||||
#endif
|
||||
CString sListenHost;
|
||||
CString sURIPrefix;
|
||||
bool bListenSSL = false;
|
||||
unsigned int uListenPort = 0;
|
||||
bool bSuccess;
|
||||
@@ -606,7 +608,7 @@ bool CZNC::WriteNewConfig(const CString& sConfigFile) {
|
||||
CUtils::GetInput("Listen Host", sListenHost, sListenHost, "Blank for all ips");
|
||||
|
||||
CUtils::PrintAction("Verifying the listener");
|
||||
CListener* pListener = new CListener((unsigned short int)uListenPort, sListenHost, bListenSSL,
|
||||
CListener* pListener = new CListener((unsigned short int)uListenPort, sListenHost, sURIPrefix, bListenSSL,
|
||||
b6 ? ADDR_ALL : ADDR_IPV4ONLY, CListener::ACCEPT_ALL);
|
||||
if (!pListener->Listen()) {
|
||||
CUtils::PrintStatus(false, FormatBindError());
|
||||
@@ -1689,12 +1691,15 @@ bool CZNC::AddListener(const CString& sLine, CString& sError) {
|
||||
bSSL = true;
|
||||
}
|
||||
|
||||
// No support for URIPrefix for old-style configs.
|
||||
CString sURIPrefix;
|
||||
unsigned short uPort = sPort.ToUShort();
|
||||
return AddListener(uPort, sBindHost, bSSL, eAddr, eAccept, sError);
|
||||
return AddListener(uPort, sBindHost, sURIPrefix, bSSL, eAddr, eAccept, sError);
|
||||
}
|
||||
|
||||
bool CZNC::AddListener(unsigned short uPort, const CString& sBindHost, bool bSSL,
|
||||
EAddrType eAddr, CListener::EAcceptType eAccept, CString& sError) {
|
||||
bool CZNC::AddListener(unsigned short uPort, const CString& sBindHost,
|
||||
const CString& sURIPrefixRaw, bool bSSL,
|
||||
EAddrType eAddr, CListener::EAcceptType eAccept, CString& sError) {
|
||||
CString sHostComment;
|
||||
|
||||
if (!sBindHost.empty()) {
|
||||
@@ -1755,7 +1760,18 @@ bool CZNC::AddListener(unsigned short uPort, const CString& sBindHost, bool bSSL
|
||||
return false;
|
||||
}
|
||||
|
||||
CListener* pListener = new CListener(uPort, sBindHost, bSSL, eAddr, eAccept);
|
||||
// URIPrefix must start with a slash and end without one.
|
||||
CString sURIPrefix = CString(sURIPrefixRaw);
|
||||
if(!sURIPrefix.empty()) {
|
||||
if (!sURIPrefix.StartsWith("/")) {
|
||||
sURIPrefix = "/" + sURIPrefix;
|
||||
}
|
||||
if (sURIPrefix.EndsWith("/")) {
|
||||
sURIPrefix.TrimRight("/");
|
||||
}
|
||||
}
|
||||
|
||||
CListener* pListener = new CListener(uPort, sBindHost, sURIPrefix, bSSL, eAddr, eAccept);
|
||||
|
||||
if (!pListener->Listen()) {
|
||||
sError = FormatBindError();
|
||||
@@ -1772,6 +1788,7 @@ bool CZNC::AddListener(unsigned short uPort, const CString& sBindHost, bool bSSL
|
||||
|
||||
bool CZNC::AddListener(CConfig* pConfig, CString& sError) {
|
||||
CString sBindHost;
|
||||
CString sURIPrefix;
|
||||
bool bSSL;
|
||||
bool b4;
|
||||
#ifdef HAVE_IPV6
|
||||
@@ -1793,6 +1810,7 @@ bool CZNC::AddListener(CConfig* pConfig, CString& sError) {
|
||||
pConfig->FindBoolEntry("ipv6", b6, b6);
|
||||
pConfig->FindBoolEntry("allowirc", bIRC, true);
|
||||
pConfig->FindBoolEntry("allowweb", bWeb, true);
|
||||
pConfig->FindStringEntry("uriprefix", sURIPrefix);
|
||||
|
||||
EAddrType eAddr;
|
||||
if (b4 && b6) {
|
||||
@@ -1820,7 +1838,7 @@ bool CZNC::AddListener(CConfig* pConfig, CString& sError) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return AddListener(uPort, sBindHost, bSSL, eAddr, eAccept, sError);
|
||||
return AddListener(uPort, sBindHost, sURIPrefix, bSSL, eAddr, eAccept, sError);
|
||||
}
|
||||
|
||||
bool CZNC::AddListener(CListener* pListener) {
|
||||
|
||||
@@ -247,6 +247,11 @@ input.third, textarea.third,
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
input.sixth, textarea.sixth,
|
||||
.sixth input, .sixth textarea {
|
||||
width: 75px;
|
||||
}
|
||||
|
||||
input.number {
|
||||
width: 40px;
|
||||
}
|
||||
@@ -299,7 +304,7 @@ tr.evenrow td {
|
||||
|
||||
.subsection input, .subsection select, .subsection textarea {
|
||||
margin: 5px 0 5px 0;
|
||||
min-width: 100px;
|
||||
min-width: 75px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,12 +5,13 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>ZNC - <? VAR Title DEFAULT="Web Frontend" ?></title>
|
||||
<link rel="shortcut icon" href="<? VAR URIPrefix TOP ?>/favicon.ico" type="image/x-icon" />
|
||||
<? LOOP CSSLoop ?>
|
||||
<?IF HREF?><link rel="stylesheet" type="text/css" href="<? VAR HREF ?>" /><?ENDIF?>
|
||||
<?IF HREF?><link rel="stylesheet" type="text/css" href="<? VAR URIPrefix TOP ?><? VAR HREF ?>" /><?ENDIF?>
|
||||
<?ENDLOOP?>
|
||||
|
||||
<? LOOP JSLoop ?>
|
||||
<?IF HREF?><script type="text/javascript" src="<? VAR HREF ?>"></script><?ENDIF?>
|
||||
<?IF HREF?><script type="text/javascript" src="<? VAR URIPrefix TOP ?><? VAR HREF ?>"></script><?ENDIF?>
|
||||
<?ENDLOOP?>
|
||||
|
||||
<? INC ExtraHeader.tmpl ?>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<? IF LoggedIn ?>
|
||||
<span class="logoutbox"><a href="/logout">Logout</a></span>
|
||||
<span class="logoutbox"><a href="<? VAR URIPrefix TOP ?>/logout">Logout</a></span>
|
||||
<? ELSE IF !ModName && PageName == "login" ?>
|
||||
<span class="logoutbox"> </span>
|
||||
<? ELSE ?>
|
||||
<form action="/login" method="post">
|
||||
<form action="<? VAR URIPrefix TOP ?>/login" method="post">
|
||||
<div class="loginbox">
|
||||
<input type="hidden" name="submitted" value="1" />
|
||||
User:<input type="text" name="user" />
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<div id="menu">
|
||||
<ul class="nav">
|
||||
<li class="topitem<? IF !ModName && PageName == "index" ?> active<? ENDIF ?>"><a href="/">Home</a></li>
|
||||
<li class="topitem<? IF !ModName && PageName == "index" ?> active<? ENDIF ?>"><a href="<? VAR URIPrefix TOP ?>/">Home</a></li>
|
||||
|
||||
<? IF GlobalModLoop ?>
|
||||
<li class="topitem parent"><span class="title">Global Modules</span>
|
||||
<ul>
|
||||
<? LOOP GlobalModLoop SORTASC=ModName ?>
|
||||
<li class="modtitle<? IF Active ?> active<? ENDIF ?>"><a href="<? VAR ModPath ?>"><? VAR Title ?></a></li>
|
||||
<li class="modtitle<? IF Active ?> active<? ENDIF ?>"><a href="<? VAR URIPrefix TOP ?><? VAR ModPath ?>"><? VAR Title ?></a></li>
|
||||
<? LOOP SubPageLoop ?>
|
||||
<li class="subitem<? IF Active ?> active<? ENDIF ?>"><a href="<? VAR ModPath ?><? VAR PageName ?><? IF Params ?>?<? VAR Params ?><? ENDIF ?>"><? VAR Title ?></a></li>
|
||||
<li class="subitem<? IF Active ?> active<? ENDIF ?>"><a href="<? VAR URIPrefix TOP ?><? VAR ModPath ?><? VAR PageName ?><? IF Params ?>?<? VAR Params ?><? ENDIF ?>"><? VAR Title ?></a></li>
|
||||
<? ENDLOOP ?>
|
||||
<? ENDLOOP ?>
|
||||
</ul>
|
||||
@@ -19,9 +19,9 @@
|
||||
<li class="topitem parent"><span class="title">User Modules</span>
|
||||
<ul>
|
||||
<? LOOP UserModLoop SORTASC=ModName ?>
|
||||
<li class="modtitle<? IF Active ?> active<? ENDIF ?>"><a href="<? VAR ModPath ?>"><? VAR Title ?></a></li>
|
||||
<li class="modtitle<? IF Active ?> active<? ENDIF ?>"><a href="<? VAR URIPrefix TOP ?><? VAR ModPath ?>"><? VAR Title ?></a></li>
|
||||
<? LOOP SubPageLoop ?>
|
||||
<li class="subitem<? IF Active ?> active<? ENDIF ?>"><a href="<? VAR ModPath ?><? VAR PageName ?><? IF Params ?>?<? VAR Params ?><? ENDIF ?>"><? VAR Title ?></a></li>
|
||||
<li class="subitem<? IF Active ?> active<? ENDIF ?>"><a href="<? VAR URIPrefix TOP ?><? VAR ModPath ?><? VAR PageName ?><? IF Params ?>?<? VAR Params ?><? ENDIF ?>"><? VAR Title ?></a></li>
|
||||
<? ENDLOOP ?>
|
||||
<? ENDLOOP ?>
|
||||
</ul>
|
||||
@@ -34,9 +34,9 @@
|
||||
<li class="topitem parent"><span class="title">Network Modules (<? VAR NetworkName ?>)</span>
|
||||
<ul>
|
||||
<? LOOP ModLoop SORTASC=ModName ?>
|
||||
<li class="modtitle<? IF Active ?> active<? ENDIF ?>"><a href="<? VAR ModPath ?>"><? VAR Title ?></a></li>
|
||||
<li class="modtitle<? IF Active ?> active<? ENDIF ?>"><a href="<? VAR URIPrefix TOP ?><? VAR ModPath ?>"><? VAR Title ?></a></li>
|
||||
<? LOOP SubPageLoop ?>
|
||||
<li class="subitem<? IF Active ?> active<? ENDIF ?>"><a href="<? VAR ModPath ?><? VAR PageName ?><? IF Params ?>?<? VAR Params ?><? ENDIF ?>"><? VAR Title ?></a></li>
|
||||
<li class="subitem<? IF Active ?> active<? ENDIF ?>"><a href="<? VAR URIPrefix TOP ?><? VAR ModPath ?><? VAR PageName ?><? IF Params ?>?<? VAR Params ?><? ENDIF ?>"><? VAR Title ?></a></li>
|
||||
<? ENDLOOP ?>
|
||||
<? ENDLOOP ?>
|
||||
</ul>
|
||||
|
||||
@@ -167,6 +167,11 @@ input.third, textarea.third,
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
input.sixth, textarea.sixth,
|
||||
.sixth input, .sixth textarea {
|
||||
width: 50px;
|
||||
}
|
||||
|
||||
.checkboxandlabel {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@@ -141,6 +141,11 @@ input.third, textarea.third,
|
||||
width: 125px;
|
||||
}
|
||||
|
||||
input.sixth, textarea.sixth,
|
||||
.sixth input, .sixth textarea {
|
||||
width: 62px;
|
||||
}
|
||||
|
||||
.subsection div.checkbox {
|
||||
padding: 9px 0 0 3px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user