BlogEngine.NET 3.3 - Prevent anonymous users from doing certain things - blogengine.net

I've re-worded this to try and get a solution.
I'm using BlogEngine.NET 3.3. I have a requirement to show 300 Characters of the posts in the blog and then the registered user will then click the post name to read the rest.
I would like to un-registered users (Anonymous users) to be able to see the 300 characters but when they try to read the full content of the post they get some text saying "Please Register to see this content".
I've scoured the net trying to find out if someone has achieved this before. I found the below code. It says to put it into the App_Code/Extensions folder as a .cs to enable it. However, in 3.3 there isn't an extensions folder in App_Code. There is one here in here BlogEngine.Core\Web\Extensions. I've tried putting the below code into the web\extensions folder and it appears to do something. It hides all of my published posts.
Could someone please help me with this?
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using BlogEngine.Core;
using BlogEngine.Core.Web.Controls;
using System.Collections.Generic;
/// <summary>
/// Summary description for PostSecurity
/// </summary>
[Extension("Checks to see if a user can see this blog post.",
"1.0", "LavaBlast.com")]
public class PostSecurity
{
static protected ExtensionSettings settings = null;
public PostSecurity()
{
Post.Serving += new EventHandler<ServingEventArgs>(Post_Serving);
ExtensionSettings s = new ExtensionSettings("PostSecurity");
s.AddParameter("Role", "Role", 50, true);
s.AddParameter("Category", "Category", 50);
// describe specific rules for entering parameters
s.Help = "Checks to see if the user has any of those roles before displaying the post. ";
s.Help += "You can associate a role with a specific category. ";
s.Help += "All posts having this category will require that the user have the role. ";
s.Help += "A parameter with only a role without a category will enable to filter all posts to this role. ";
s.AddValues(new string[] { "Registered", "" });
ExtensionManager.ImportSettings(s);
settings = ExtensionManager.GetSettings("PostSecurity");
}
protected void Post_Serving(object sender, ServingEventArgs e)
{
Post post = (Post)sender;
bool continu = false;
MembershipUser user = Membership.GetUser();
continu = user != null;
if (user != null)
{
List<string> categories = new List<string>();
foreach (Category cat in post.Categories)
categories.Add(cat.Title);
string[] r = Roles.GetRolesForUser();
List<string> roles = new List<string>(r);
DataTable table = settings.GetDataTable();
foreach (DataRow row in table.Rows)
{
if (string.IsNullOrEmpty((string)row["Category"]))
continu &= roles.Contains((string)row["Role"]);
else
{
if (categories.Contains((string)row["Category"]))
continu &= roles.Contains((string)row["Role"]);
}
}
}
e.Cancel = !continu;
}
}

Ok, so some time ago I used BlogEngine.Net, and I'll try to help you from the top of my mind, so I'm not really sure that my answer is correct, but maybe it will give you some pointers, ok?
You should not give Members the access right to view Unpublished Posts, as this is more for editors on the site, to be able to save drafts of new Posts before publishing them for public consumption.
From what I understand (?), only your friend will be writing Posts on the blog, and therefore he should be the only one with that permission.
One thing that might work, is to give everyone permission to watch Posts, if that is required to get the first page to work (I don't really remember). Then you can override/customize the control/view that shows the Posts, and there you can check to see if the user is actually registered and decide to show the Post or a message telling them to register.

This has now been resolved. rtur from BlogEngine.Net kindly assisted with this.
using BlogEngine.Core;
using BlogEngine.Core.Web.Controls;
using System.Web;
[Extension("Secure post", "1.0", "BlogEngine.NET")]
public class SecurePost
{
static SecurePost()
{
Post.Serving += Post_Serving;
}
private static void Post_Serving(object sender, ServingEventArgs e)
{
if(e.Location == ServingLocation.SinglePost)
{
if (!HttpContext.Current.User.Identity.IsAuthenticated)
{
HttpContext.Current.Response.Redirect("~/account /login.aspx");
}
}
}
}

Related

Using libVLCsharp to stream pw protected IP Camera Video but video not playing

I am trying to construct a UI for Onvif complaint devices. I've been beating my head against the wall for sometime now. I believe I have the custom URI correctly constructed. According to the ONVIF Programmers Guide we need to Get Profiles, GetStreamURI, Request Streaming. http://www.openipcam.com/files/ONVIF/ONVIF_WG-APG-Application_Programmer's_Guide.pdf
Using Wireshark I believe I see HTTP packets being sent (showing the appropriate requests), and what I believe are appropriate responses. The final GetStreamURI gets a successful response from the camera. Then when I try to call _mp.Play I see a few packets over HTTP and a few TCP packets back back from the camera. After this communication stops.
using System;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using LibVLCSharp.Shared;
using LibVLCSharp;
using System.ServiceModel.Channels;
using Lib_vlc_CSharp_Onvif.OnvifDevice;
using System.ServiceModel;
using Lib_vlc_CSharp_Onvif.OnvifMedia;
namespace Lib_vlc_CSharp_Onvif
{
public partial class Form1 : Form
{
public LibVLC _libVLC;
public LibVLCSharp.Shared.MediaPlayer _mp;
public LibVLCSharp.Shared.Media media;
//ToDO... make screen size adjustable
public System.Drawing.Size VidSize;
public System.Drawing.Size FormSize;
public System.Drawing.Point OldVidLoc;
//Create Onvif Media Profiles through service references
OnvifMedia.Media2Client Onvif_media;
OnvifMedia.MediaProfile[] profiles;
//Custom URI variable
UriBuilder deviceUri;
public Form1()
{
InitializeComponent();
//LibVLCSharp Specific
Core.Initialize();
this.KeyPreview = true;
//Just controlling the size. TODO: Imp controls
VidSize = videoView.Size;
FormSize = this.Size;
OldVidLoc = videoView.Location;
//Vlc Specific
//Set up the Vlc Lib and then connect the Form1 media window player to the media player of the library.
//videoVew is vlcsharp item in Form1.
_libVLC = new LibVLC();
_mp = new MediaPlayer(_libVLC);
videoView.MediaPlayer = _mp;
}
private void button1_Click(object sender, EventArgs e)
{
//Set up device to get profiles (Onvif Specific)
//Required a custom URI and binding.
deviceUri = new UriBuilder("Http:/onvif/device_service");
System.ServiceModel.Channels.Binding binding;
HttpTransportBindingElement httpTransport = new HttpTransportBindingElement();
httpTransport.AuthenticationScheme = System.Net.AuthenticationSchemes.Digest;
binding = new CustomBinding(new TextMessageEncodingBindingElement(MessageVersion.Soap12, Encoding.UTF8), httpTransport);
//Assign IP Address to device URI. TODO: This eventually will be pulled from user entered value in an text box.
deviceUri.Host = "xxx.xxx.x.x";
DeviceClient Onvif_Device = new DeviceClient(binding, new EndpointAddress(deviceUri.ToString()));
OnvifDevice.Service[] service = Onvif_Device.GetServices(false);
//Check if they contain media and that we have made contact TODO wrap in a try catch block
OnvifDevice.Service xmedia = service.FirstOrDefault(s => s.Namespace == "http://www.onvif.org/ver20/media/wsdl");
if (xmedia != null)
{
Onvif_media = new Media2Client(binding, new EndpointAddress(deviceUri.ToString()));
Onvif_media.ClientCredentials.HttpDigest.ClientCredential.UserName = "admin";
Onvif_media.ClientCredentials.HttpDigest.ClientCredential.Password = "admin";
Onvif_media.ClientCredentials.HttpDigest.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
//Get camera Profiles.
profiles = Onvif_media.GetProfiles(null, null);
if (profiles != null)
{
foreach (var p in profiles)
{
listBox.Items.Add(p.Name);
//Profiles listed in box match profiles setup on camera.
}
}
}
//Eventually add a selection option on the list box.
//listBox.SelectedINdexChanged += OnSelectionChanged
//If we have profiles build a custom URI to past to the vlc boject
if (profiles != null)
{
//Building URI to pass to VLCSharp VideoView Item.
//https://www.onvif.org/ver20/media/wsdl/media.wsdl
//GetSreamUri and define RtspUnicast.
//http://www.openipcam.com/files/ONVIF/ONVIF_WG-APG-Application_Programmer's_Guide.pdf on page 57&58
UriBuilder local_uri = new UriBuilder(Onvif_media.GetStreamUri("RtspUnicast", profiles[0].token));
//ToDO: Build list box to allow user to switch between profiles. Just past main profile for now.
local_uri.Host = deviceUri.Host;
local_uri.Port = deviceUri.Port;
local_uri.Scheme = "rtsp";
//List full URI info.
infoBox.Text = local_uri.Host + local_uri.Port + local_uri.Path;
//Past it to VideoView and start playing video.
_mp.Play(new Media(_libVLC, local_uri.Uri));
}
}
}
}
Update: I believe my issue is the URI I have built requires validation. When I take this URI and put it into a web browser I get a 401 Error. I'm not sure why I don't see this error on wire-shark. I assign the user name and password into URI object but when I check "IsWellFormedURIString" I get an "invalid Port Error."
Did you try --rtsp-user and --rtsp-pwd ? you could also set the RTSP password with the dialog API.
If that doesn't work, please share your full logs.
You should be able to copy/paste the URL from Onvif Device Manager right into VLC and see it play (provided that you entered the correct credentials). If it doesn't, that's already an issue on its own.
You can still assign the Password and Username password.
MyUri.UserName = MyName
MyUri.Password = password
You run into problems when your password has characters like "#"
While I haven't figured out a workaround on this, for the time being keeping the password simple like "MyPassword" instead of "MyPassword#1234" will allow you to use the URI with the name and password built into the string.

Webmasters API - Quota limits

We're trying to download page data for sites using the Webmasters API .NET Client Library, by calling WebmastersService.SearchAnalytics.Query(). To do this we are using Batching and sending approx. 600 requests in one batch. However most of these fail with the error "Quota Exceeded". The amount that fail varies each time but it is only about 10 of the 600 that work (and it varies where they are within the batch). The only way we can get it to work is to reduce the batch size down to 3, and wait 1 second between each call.
According to the Developer Console our daily quota is set to 1,000,000 (and we have 99% remaining) and our per user limit is set to 10,000 requests / second / user.
The error we get back is:
Quota Exceeded [403] Errors [ Message[Quota Exceeded] Location[ - ]
Reason[quotaExceeded] Domain[usageLimits]]
Is there another quota which is enforced? What does "Domain[usage limits]" mean - is the domain the site we are query the page data for, or is it our user account?
We still get the problem if we run each request separately, unless we wait 1 second between each call. Due to the number of sites and the number of pages we need to download the data for this isn't really an option.
I found this post which points out that just because the max batch size is 1000 doesn't mean to say the Google service you are calling supports batches of those sizes. But I'd really like to find out exactly what the quota limits really are (as they don't relate to the Developer Console figures) and how to avoid the errors.
Update 1
Here's some sample code. Its specially written just to prove the problem so no need to comment on it's quality ;o)
using Google.Apis.Auth.OAuth2;
using Google.Apis.Services;
using Google.Apis.Util.Store;
using Google.Apis.Webmasters.v3;
using Google.Apis.Webmasters.v3.Data;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
new Program().Run().Wait();
}
private async Task Run()
{
List<string> pageUrls = new List<string>();
// Add your page urls to the list here
await GetPageData("<your app name>", "2015-06-15", "2015-07-05", "web", "DESKTOP", "<your domain name>", pageUrls);
}
public static async Task<WebmastersService> GetService(string appName)
{
//if (_service != null)
// return _service;
//TODO: - look at analytics code to see how to store JSON and refresh token and check runs on another PC
UserCredential credential;
using (var stream = new FileStream("c:\\temp\\WMT.json", FileMode.Open, FileAccess.Read))
{
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
new[] { Google.Apis.Webmasters.v3.WebmastersService.Scope.Webmasters },
"user", CancellationToken.None, new FileDataStore("WebmastersService"));
}
// Create the service.
WebmastersService service = new WebmastersService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = appName,
});
//_service = service;
return service;
}
private static async Task<bool> GetPageData(string appName, string fromDate, string toDate, string searchType, string device, string siteUrl, List<string> pageUrls)
{
// Get the service from the initial method
bool ret = false;
WebmastersService service = await GetService(appName);
Google.Apis.Requests.BatchRequest b = new Google.Apis.Requests.BatchRequest(service);
try
{
foreach (string pageUrl in pageUrls)
{
SearchAnalyticsQueryRequest qry = new SearchAnalyticsQueryRequest();
qry.StartDate = fromDate;
qry.EndDate = toDate;
qry.SearchType = searchType;
qry.RowLimit = 5000;
qry.Dimensions = new List<string>() { "query" };
qry.DimensionFilterGroups = new List<ApiDimensionFilterGroup>();
ApiDimensionFilterGroup filterGroup = new ApiDimensionFilterGroup();
ApiDimensionFilter filter = new ApiDimensionFilter();
filter.Dimension = "device";
filter.Expression = device;
filter.Operator__ = "equals";
ApiDimensionFilter filter2 = new ApiDimensionFilter();
filter2.Dimension = "page";
filter2.Expression = pageUrl;
filter2.Operator__ = "equals";
filterGroup.Filters = new List<ApiDimensionFilter>();
filterGroup.Filters.Add(filter);
filterGroup.Filters.Add(filter2);
qry.DimensionFilterGroups.Add(filterGroup);
var req = service.Searchanalytics.Query(qry, siteUrl);
b.Queue<SearchAnalyticsQueryResponse>(req, (response, error, i, message) =>
{
if (error == null)
{
// Process the results
ret = true;
}
else
{
Console.WriteLine(error.Message);
}
});
await b.ExecuteAsync();
}
}
catch (Exception ex)
{
Console.WriteLine("Exception occurred getting page stats : " + ex.Message);
ret = false;
}
return ret;
}
}
}
Paste this into program.cs of a new console app and add Google.Apis.Webmasters.v3 via nuget. It looks for the wmt.json file in c:\temp but adjust the authentication code to suit your setup. If I add more than 5 page urls to the pageUrls list then I get the Quota Exceeded exception.
I've found that the stated quotas don't really seem to be the quotas. I had to slow my requests down to avoid this same issue (1/sec), even though I was always at or below the stated rate limit (20/sec). Furthermore, it claims that it gives a rateLimitExceeded error in the docs for going too fast, but really it returns a quotaExceeded error. It might have to do with how Google averages the rate of requests over time (as some of the requests we made were simultaneous, even though the long-run average was designed to be at or below 20/sec), but I cannot be sure.

Create a Windows Session from a service via the Win32 API

I have a windows service that can create an executable in the users windows session, via calling the "CreateProcessAsUser" function. This works fine as long as there is a windows session already there. In the case that there isn't one already I'd like to be able to create one programmatically. Is this is possible? Can't seem to find a function to do it.
This isn't quite the solution for the question I asked, but it was the solution that helped achieve what I was trying to achieve by asking this question, if you see what I mean.
Rather than have having a windows services that creates a server session you can configure windows to automatically logon at boot time. This still means someone could accenditally log off, but cures the main reason for sessions disappearing: the server being rebooted. Use the following steps to activate auto-logon:
Press the Windows key + R on your keyboard to launch the “Run” dialog box.
Type regedit and hit enter to open the Registry Editor
Then browse to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Winlogon\
Set AutoAdminLogon = 1 (create it if doesn't exist its a string variable)
Set DefaultUserName = your username (create it if doesn't exist its a string variable)
Set DefaultPassword = your password (create it if doesn't exist its a string variable)
Instructions were taken from this post:
http://channel9.msdn.com/Blogs/coolstuff/Tip-Auto-Login-Your-Windows-7-User-Account
You cannot create a new session from a service. Sessions are managed by the OS. New ones get created when users logon interactively.
#Robert, I know this is an old question and that you've already found something that works for you but in my case I was looking for something similar to your original question and I did finally figure it out so I thought I'd share. My solution uses only .NET and a COM reference not the Win32 API mentioned in your title, but I'm guessing that wasn't really a requirement for you.
I've written a simple utility to using the Remote Desktop ActiveX control (COM Reference). If you paste this code into a Class Library you can then call it by simply passing in the server, username, domain, and password and everything is done for you without any other interaction required. Once the method is complete you can then call your "CreateProcessAsUser" Code. I've written this utility in a way so that you could call it every time but initiating an RDP session takes several seconds so for performance sake I'd suggest you write another method to enumerate the sessions and see if your user is logged in and only call this utility when you determine that your user isn't logged in (That's what I did in my actual project). If you feel you need help with that post in the comments and I'll share how I did that but It's not really part of this question so for now I'm leaving it out.
Here's a link back to my question that has a few more requirements/details than this question.
Create Windows Session programmatically from Console or Windows Service
And here's my RDP utility. After you put this code in a class library you can then call it from a console app, winForms app, or from a windows service running on the same machine or from a remote machine.
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using AxMSTSCLib;
namespace Utility.RemoteDesktop
{
public class Client
{
private int LogonErrorCode { get; set; }
public void CreateRdpConnection(string server, string user, string domain, string password)
{
void ProcessTaskThread()
{
var form = new Form();
form.Load += (sender, args) =>
{
var rdpConnection = new AxMSTSCLib.AxMsRdpClient9NotSafeForScripting();
form.Controls.Add(rdpConnection);
rdpConnection.Server = server;
rdpConnection.Domain = domain;
rdpConnection.UserName = user;
rdpConnection.AdvancedSettings9.ClearTextPassword = password;
rdpConnection.AdvancedSettings9.EnableCredSspSupport = true;
if (true)
{
rdpConnection.OnDisconnected += RdpConnectionOnOnDisconnected;
rdpConnection.OnLoginComplete += RdpConnectionOnOnLoginComplete;
rdpConnection.OnLogonError += RdpConnectionOnOnLogonError;
}
rdpConnection.Connect();
rdpConnection.Enabled = false;
rdpConnection.Dock = DockStyle.Fill;
Application.Run(form);
};
form.Show();
}
var rdpClientThread = new Thread(ProcessTaskThread) { IsBackground = true };
rdpClientThread.SetApartmentState(ApartmentState.STA);
rdpClientThread.Start();
while (rdpClientThread.IsAlive)
{
Task.Delay(500).GetAwaiter().GetResult();
}
}
private void RdpConnectionOnOnLogonError(object sender, IMsTscAxEvents_OnLogonErrorEvent e)
{
LogonErrorCode = e.lError;
}
private void RdpConnectionOnOnLoginComplete(object sender, EventArgs e)
{
if (LogonErrorCode == -2)
{
Debug.WriteLine($" ## New Session Detected ##");
Task.Delay(10000).GetAwaiter().GetResult();
}
var rdpSession = (AxMsRdpClient9NotSafeForScripting)sender;
rdpSession.Disconnect();
}
private void RdpConnectionOnOnDisconnected(object sender, IMsTscAxEvents_OnDisconnectedEvent e)
{
Environment.Exit(0);
}
}
}
What about the LogonUser function?
http://winapi.freetechsecrets.com/win32/WIN32LogonUser.htm

Get Page owner contact email and display in SharePoint 2010 Masterpage

I've built out a solution with multiple masterpages/page layouts as features for a set of SharePoint 2010 publishing site collections.
One consistent request is to be able to grab the page owner contact email and display it in the footer of the masterpage. If the page Contact Email isn't entered, then I need to grab the page owner data from the People Picker, and grab the contact email from that.
I don't want to have to add every single publishing page layout to my solution, and manually add the Contact Email column into a place holder, that seems crazy to me. I figure there has to be a way to grab the page owner data from within the masterpage, but I can't figure it out. I started looking at the jQuery SPServices library, but so far I haven't been able to figure it out there, either.
Does anyone have any experience in adding a contact email using the supplied page owner contact information in the Masterpage?
OK, in order to resolve this, you need jQuery 1.7.x+ and the SPServices jQuery library version 0.7.2 or greater installed on your site.
Use GetListItems as the operation from SPServices.
I'm searching for pages within the Pages directory, so listName is "Pages".
The CAML View Fields are basically the columns for PublishingContactEmail and PublishingContact. I found those using u2u's CAML builder version 4.0.0.0
The ows_ variables can be found in the xml view of the POST object in firebug.
The ows_PublishingContact returns a long nasty string of the contact's information. Fortunately the email address is surrounded by ,#, which made splitting it into an array and then searching for an email # easy, but that's why that's there.
function get_page_contact_email() {
var thisPageID = _spPageContextInfo.pageItemId;
var e;
$().SPServices({
operation: "GetListItems",
async: false,
listName: "Pages",
CAMLViewFields: "<ViewFields><FieldRef Name='PublishingContactEmail' /><FieldRef Name='PublishingContact' /></ViewFields>",
CAMLQueryOptions: "<QueryOptions><ExpandUserField>True</ExpandUserField></QueryOptions>",
completefunc: function (xData, Status) {
$(xData.responseXML).SPFilterNode("z:row").each(function () {
if (thisPageID == $(this).attr("ows_ID")) {
if ($(this).attr("ows_PublishingContactEmail")) { // if page email is set
e = $(this).attr("ows_PublishingContactEmail");
} else if ($(this).attr("ows_PublishingContact")) { //otherwise use contact info
var contact = $(this).attr("ows_PublishingContact").split(",#");
for (var c = 0; c < contact.length; c++) {
if (contact[c].indexOf("#") != -1) {
e = contact[c];
}
}
} else { //or nothing is set.
e = false;
}
}
});
}
});
return e;
}

Navigation using RelayCommand<T> in MVVM Light

I have been following Jesse Liberty's tutorial on MVVM Light for Windows Phone 7, but I'm stuck on this problem. I need to navigate from a main page to a detail page. Following the tutorial, I'm using a RelayCommand in the MainViewModel:
public RelayCommand<Customer> DetailsPageCommand { get; private set;}
I then initialize it in the constructor:
DetailsPageCommand = new RelayCommand<Customer>((msg) => GoToDetailsPage(msg));
Finally you implement the GoToDetailsPage method:
private object GoToDetailsPage(Customer msg)
{
System.Windows.MessageBox.Show("Go to details page with: " +
msg.First +
" " +
msg.Last );
return null;
}
Showing the message box works, but I'm not sure how to navigate to the detail page instead. In previous sections of the tutorial page navigation was handled with something like this:
var msg = new GoToPageMessage {PageName = "DetailPage"};
Messenger.Default.Send(msg);
You'll need to register to receive messages of that type and then navigate appropriately.
The following assumes a page name and that you're navigating to details of the specific customer by passing their Id in the query string.
Messenger.Default.Register<Customer>(
this,
c => NavigationService.Navigate("/Pages/CustomerDetails.xaml?cid=" + c.Id));
You'd then adjust your code accordingly:
private void GoToDetailsPage(Customer msg)
{
Messenger.Default.Send(msg);
}
I hope this helps.

Resources