Need to change web.server.host property during runtime - liferay

Please help me in below problem
I have single liferay instance and it has single site on it. This single site is serving multiple clients and they access the site using their dedicated domain name
xxx.mysite.com -> domain name for the client xxx
yyy.mysite.com -> domain name for the client yyy
These domain names are configured in apache web server which is sitting infront of liferay instance. I used property in portal-ext.properties web.server.host to configure the webserver information in liferay. Liferay uses this property to generate all the links on the page(if this property is not mentioned it uses the servername to generate the urls). But using this I can only define one site at a time. I can not achieve above functionality. I went to the liferay code and in PortalImpl.java it has following code
public String getPortalURL(
String serverName, int serverPort, boolean secure) {
StringBundler sb = new StringBundler();
if (secure || Http.HTTPS.equals(PropsValues.WEB_SERVER_PROTOCOL)) {
sb.append(Http.HTTPS_WITH_SLASH);
}
else {
sb.append(Http.HTTP_WITH_SLASH);
}
if (Validator.isNull(PropsValues.WEB_SERVER_HOST)) {
sb.append(serverName);
}
else {
sb.append(PropsValues.WEB_SERVER_HOST);
}
if (!secure) {
if (PropsValues.WEB_SERVER_HTTP_PORT == -1) {
if ((serverPort != Http.HTTP_PORT) &&
(serverPort != Http.HTTPS_PORT)) {
sb.append(StringPool.COLON);
sb.append(serverPort);
}
}
else {
if (PropsValues.WEB_SERVER_HTTP_PORT != Http.HTTP_PORT) {
sb.append(StringPool.COLON);
sb.append(PropsValues.WEB_SERVER_HTTP_PORT);
}
}
}
if (secure) {
if (PropsValues.WEB_SERVER_HTTPS_PORT == -1) {
if ((serverPort != Http.HTTP_PORT) &&
(serverPort != Http.HTTPS_PORT)) {
sb.append(StringPool.COLON);
sb.append(serverPort);
}
}
else {
if (PropsValues.WEB_SERVER_HTTPS_PORT != Http.HTTPS_PORT) {
sb.append(StringPool.COLON);
sb.append(PropsValues.WEB_SERVER_HTTPS_PORT);
}
}
}
return sb.toString();
}
In above method it uses the web.server.host property defined in poratal-ext.properties and constructs the URLs. Now I need to overwrite this method to determine the web server host during runtime.
my question are.
How to overwrite this function in PoralImpl.java? Do I need use extension to achieve this?
Is anyother way(betterway) to achieve this functionality.
I am using liferay 6.1.0 GA-1/tomcat bundle

Yes, the only way to override Liferay's core functionality (= code that exists in "portal-impl.jar") is to use ext plugin, http://www.liferay.com/community/wiki/-/wiki/Main/Ext+Plugin

Related

How will you block access of Drupal admin login page from untrusted IPs without using nginx.conf?

Recently I was going through this task and did a lot of Rnd. Everyone suggested me to use location block in nginx like:
location = /user {
include /path/to/trusted-ips.txt;
deny all;
}
But due to some nginx rewrite rules it is not working. I have implemented another solution using drupal form hook and sharing with you.
function hook_form_alter (&$form, &$form_state, $form_id) {
if($form_id == 'user_login') {
$forbidden = "<head><title>403 Forbidden</title></head><body><center><h1>403 Forbidden</h1></center><hr><center>nginx</center></body>";
$allowed_ip_file = '/path/to/trusted-ips.txt';
$allowed_ip_file = fopen($allowed_ip_file, "r") or die("Unable to open file!");
$allowd_ip_arr = array();
while(! feof($allowed_ip_file)) {
$line = fgets($allowed_ip_file);
if (preg_match('/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/', $line, $ip_match)) {
$allowd_ip_arr[] = $ip_match[0];
}
}
fclose($allowed_ip_file);
if(!in_array($_SERVER['REMOTE_ADDR'], $allowd_ip_arr)) {
http_response_code(403);
echo $forbidden; exit();
}
}
}
Try to use Restrict IP Drupal module
This module allows administrators to restrict access to the site to an administrator defined set of IP addresses.

SharePoint 2010: Disable / Hide references to SPSDisco.aspx

After upgrading some of our external websites running on SharePoint 2007 to 2010, we ran a link checker to find problems. We noticed the log showed requests for a file called spsdisco.aspx. Indeed, when examining the source of our web pages, SharePoint is adding the following link element to the page HEAD:
<link href="_vti_bin/spsdisco.aspx" rel="alternate" type="text/xml" />
This is a web service discovery file listing out the names and locations of all of SharePoint's web service endpoints. Even worse, this file is starting to show up in search indexes. At best it is embarrassing; at worst it's a potential vulnerability (these are external websites). Because it's a virtual file, it shows up under every site and subsite, so a manual approach to "hiding" each one is difficult and clumsy.
I can't seem to find any actual documentation about it -- a few references on updating it to include a custom web service, but that's about it. How might we approach a reliable, top-down approach to disabling access to these pages? I think we can find a way to suppress the LINK element in the page, but that's just obscuring the problem.
Is there a location in SharePoint (Site or Central Admin) to turn it off? Would you just add some request filtering to IIS to disallow access to SPSdisco.aspx and the ASMX files?
Update: On Kev's suggestion, I've cross-posted to sharepoint.stackexchange.com.
Update 2: See, I hadn't abandoned this question. We finally had time to get some MS guidance and build a deployable SharePoint solution to address the issue.
As a quick fix I would add a request filtering rule to deny access to SPSDisco.aspx.
But you might want to ask on the new SharePoint Stack Exchange site about a more robust fix:
https://sharepoint.stackexchange.com/
Here is the solution that we arrived at. It was in part based on recommendations by our Microsoft representative, so you might consider this an unofficial, "official" approach.
First, we need keep SharePoint from advertising the disco file to the world (i.e. Google). Simply remove the following line in your master pages:
<SharePoint:SoapDiscoveryLink runat="server"/>
This will suppress the <link href="/_vti_bin/spsdisco.aspx" rel="alternate" type="text/xml"> reference in the HEAD of your pages.
Next, we want to make sure that unauthorized users don't have access to the web services described by the disco file, or anything in _vti_bin for that matter. If your site only runs internal to your firewall (an intranet, for example), then this isn't as important. But if you've got anonymous endpoints that can be accessed externally, you want them locked down.
This is an excellent application for an HttpModule. We'll build one that intercepts any request containing _vti_bin in the path, and if the current user is unauthorized will return a 404 NOT FOUND status code. I chose to return a 404 rather than a 401 UNAUTHORIZED because I don't just want to lock those paths down, I want to hide the fact that anything even exists at those paths.
Our HttpModule looks like this:
using System;
using System.Web;
namespace Custom.SharePoint.HttpModule.SpSecureVtiBin {
public class SpSecureVtiBinModule : IHttpModule {
#region IHttpModule Members
public void Dispose() { }
public void Init( HttpApplication context ) {
context.AuthorizeRequest += new EventHandler( context_AuthorizeRequest );
}
protected virtual void context_AuthorizeRequest( object sender, EventArgs e ) {
HttpApplication app = (HttpApplication)sender;
string requestedPath = app.Request.Path;
if ( requestedPath.ToLowerInvariant().Contains( "_vti_bin" ) ) {
if ( !app.Request.IsAuthenticated ) {
app.Response.StatusCode = 404;
app.Response.StatusDescription = "Not Found";
app.Response.Write( "404 NOT FOUND" );
app.Response.End();
}
}
}
#endregion
}
}
Simple enough. To use the HttpModule, it needs to be registered in the site's web.config file with an entry under \configuration\system.webServer\modules:
<add name="SpSecureVtiBinModule" type="Custom.SharePoint.HttpModule.SpSecureVtiBin.SpSecureVtiBinModule, Custom.SharePoint.HttpModule.SpSecureVtiBin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=[your_public_key_token]" />
Of course, we don't want to modify a SharePoint application's web.config file manually. We'll create an SPFeatureReceiver to do the job:
using System.Collections.ObjectModel;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
namespace Custom.SharePoint.HttpModule.SpSecureVtiBin {
public class ModuleFeatureReceiver : SPFeatureReceiver {
private static string _owner = "SpSecureVtiBinModule";
public override void FeatureActivated( SPFeatureReceiverProperties properties ) {
SPWebApplication app = (SPWebApplication)properties.Feature.Parent;
app.WebConfigModifications.Add( GetModificationForSystemWebServer() );
app.WebService.ApplyWebConfigModifications();
app.Update();
}
public override void FeatureDeactivating( SPFeatureReceiverProperties properties ) {
SPWebApplication app = (SPWebApplication)properties.Feature.Parent;
Collection<SPWebConfigModification> mods = app.WebConfigModifications;
int modCount = mods.Count;
bool modRemoved = false;
for ( int i = modCount - 1; i >= 0; i-- ) {
SPWebConfigModification mod = mods[i];
if ( mod.Owner.Equals( _owner ) || mod.Owner.Equals( "CHK.SharePoint.HttpModule.SpSecureVtiBin.SpSecureVtiBinModule" ) ) {
app.WebConfigModifications.Remove( mod );
modRemoved = true;
}
}
if ( modRemoved ) {
app.WebService.ApplyWebConfigModifications();
app.Update();
}
}
private SPWebConfigModification GetModificationForSystemWebServer() {
return new SPWebConfigModification {
Name = "add[#name='SpSecureVtiBinModule']",
Owner = _owner,
Path = "configuration/system.webServer/modules",
Value = #"<add name=""SpSecureVtiBinModule"" type=""Custom.SharePoint.HttpModule.SpSecureVtiBin.SpSecureVtiBinModule, Custom.SharePoint.HttpModule.SpSecureVtiBin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=[your_public_key_token]"" />",
Sequence = 0
};
}
}
}
Now all that's left is to package up the HttpModule. You'll need to define a Feature in the package and reference the SPFeatureReceiver class. This will cause the web.config entry to be added when the Feature is activated, and the entry to be removed when the Feature is deactivated. Target the Feature for a WebApplication and the assembly deployment target to GlobalAssemblyCache.

MapPath or equivalent to use in an installation application

I need to check a .config file in an installation application (iis custom action in a WIX project). The user picks a website and enters a virtual directory name. I can't do a http read to retrieve the config file as ASP.NET does not serve config files.
How can I find the local disk path of the selected website and virtual directory?
After further searching, I ended up using DirectoryServices. I'm posting my solution here for others.
If there is a better way, please still post it.
static string FindVirtualDirectoryPath(string virtualDirectoryName)
{
return FindVirtualDirectoryPath(null, virtualDirectoryName);
}
static string FindVirtualDirectoryPath(string siteName, string virtualDirectoryName)
{
DirectoryEntry iis = new DirectoryEntry("IIS://localhost/W3SVC");
foreach (DirectoryEntry index in iis.Children)
{
if (index.SchemaClassName == "IIsWebServer")
{
int id = Convert.ToInt32(index.Name);
DirectoryEntry site = new DirectoryEntry(string.Concat("IIS://localhost/W3SVC/", id));
string iSiteName = site.Properties["ServerComment"].Value.ToString();
if (iSiteName == siteName || (string.IsNullOrEmpty(siteName) && id == 1))
{
DirectoryEntry rootVDir = new DirectoryEntry(string.Concat("IIS://localhost/W3SVC/", id, "/Root"));
foreach (DirectoryEntry vDir in rootVDir.Children)
{
if (vDir.SchemaClassName == "IIsWebVirtualDir" && vDir.Name.ToLower() == virtualDirectoryName.ToLower())
{
return vDir.Properties["Path"].Value.ToString();
}
}
}
}
}
return null;
}
Have you tried using the standard WiX IIsExtension for this? Just capture the user input in a property, and then use standard elements like iis:WebSite and iis:WebVirtualDir to create a virtual directory in appropriate web site.

Web Part connections in site definitions

I have requirement of specifying web part connections in onet.xml. So when site is created using this site definition the said web parts are already connected and ready to use. Which properties I need to specify for that particular web parts in onet.xml.
I have also hit the wall on this one sometime last year! It looks like connections can no longer be specified on Web Parts in the new .webpart format as they could in the old .dwp format. I ended up including a custom feature in the site definition like kpinhack also suggests. My code for connecting the Web Parts is listed below. The method is just designed for connecting two Web Parts of different types - it does not support multiple Web Parts of the same type on the same page. But I am sure you'll catch the general idea.
private void ConnectWebParts(SPWeb web, string pageName, Type providerType, Type consumerType)
{
SPFile file = web.GetFile(pageName);
SPList list = null;
if (file.InDocumentLibrary)
{
list = file.Item.ParentList;
if (list.ForceCheckout) file.CheckOut();
}
SPLimitedWebPartManager webPartManager =
web.GetLimitedWebPartManager(
pageName,
System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared);
WebPart provider = null;
foreach (WebPart wp in webPartManager.WebParts)
{
if (wp.GetType() == providerType)
{
provider = wp;
break;
}
}
foreach (WebPart consumer in webPartManager.WebParts)
{
if (consumer.GetType() != consumerType) continue;
ProviderConnectionPointCollection providerConnections = webPartManager.GetProviderConnectionPoints(provider);
ProviderConnectionPoint providerConnection = providerConnections[0];
ConsumerConnectionPointCollection consumerConnections = webPartManager.GetConsumerConnectionPoints(consumer);
ConsumerConnectionPoint consumerConnection = consumerConnections[0];
SPWebPartConnection con = webPartManager.SPConnectWebParts(provider, providerConnection, consumer, consumerConnection);
webPartManager.SPWebPartConnections.Add(con);
}
if (list != null)
{
if (list.ForceCheckout)
{
file.CheckIn("Added Web Part Connections");
}
if (list.EnableVersioning && list.EnableMinorVersions)
{
file.Publish("Added Web Part Connections");
}
}
}
I would configure the WebParts in the SiteProvisioning-Feature, by implementing the 'OnActivated'-Eventhandler. That way the code will run when the website is created, and you can handle errors the way you like it (i.e. if the WebParts are not available when the website is created - for whatever reason)
I hope this helps!
you would need to use the < AllUsersWebPart > tag to declare your web parts, and then declare your connections within the enclosed < WebPart > elements.
example

SharePoint: How to determine a site's site directory programmatically

Is there a way to get a site's (site collection) site directory, the one which is defined within the web site collection setting of a collaboration or publishing portal?
Of course I could iterate through all the SPWebs of the site collection but I hope there's a easier way to get the directory as the information seems to be already stored somewhere.
Bye,
Flo
UPDATE
Of course I want to get the information programmatically.
The site directory path is stored in the root web property bag
The code below taken from an internal utility class SiteDirectoryUtil shows the logic of how to determine the path
internal static string GetLocalSiteDirectoryLocation(SPWeb rootWeb)
{
if (rootWeb != null)
{
if (rootWeb.AllProperties.ContainsKey("DefaultSiteDirectorySiteId"))
{
string str = rootWeb.AllProperties["DefaultSiteDirectorySiteId"] as string;
if (string.IsNullOrEmpty(str))
{
return string.Empty;
}
if (!rootWeb.AllProperties.ContainsKey("DefaultSiteDirectoryWebId"))
{
return string.Empty;
}
string str2 = rootWeb.AllProperties["DefaultSiteDirectoryWebId"] as string;
if (string.IsNullOrEmpty(str2))
{
return string.Empty;
}
try
{
using (SPSite site = new SPSite(new Guid(str), rootWeb.Site.Zone))
{
using (SPWeb web = site.OpenWeb(new Guid(str2)))
{
return web.ServerRelativeUrl;
}
}
}
catch (FileNotFoundException)
{
return string.Empty;
}
}
else
{
return string.Empty;
}
}
return string.Empty;
}
Are you referring to the site directory that is under the Site Content and Structure?
If so, you can browse to http://sitename/_layouts/sitemanager.aspx to see site directory (assuming you have sufficient privileges to the site).
For what it's worth, if you have access to the WSS database(s) you can either leverage off existing SPs or create your own. I wanted to return things like 'RequestAccessEmail' and incorporate that into our own site maps (handy to know who the site owner is sometimes). Our SP at it's most basic...
CREATE PROCEDURE [dbo].[my_sitemap](
#PartialUrl nvarchar(260)
)
AS
SELECT ID, FullUrl, Title, RequestAccessEmail
FROM Webs
WHERE FullUrl LIKE #PartialUrl + '%'
ORDER BY FullUrl
GO
Worked very well for me. Hope this helps.

Resources