How to add / create Foul or bad language keyword filter in SharePoint Lists, Documents? - sharepoint-2007

I am building an Internal social networking website on SharePoint. Since its a networking intranet, I want it to be Open and non moderated. However, I also dont want people to use abusive / Foul or bad language words in the portal.
I tried Googling and wasnt really sucessfull in finding a solution.
Microsoft Forefront will do that for me, but it only does for Documents. But I also want to do that on Lists since Discussion forum on the SharePoint is in a list format.

You may create site solution/list definition for your site using Visual studio Sharepoint Site Solution Genarator. Create a custom list and name it as you wish. I would name it "AbusiveWordList" in the following code example.
After creating site solution/list definition, Add below code in Item Adding function, which will iterate through all column in the list and will check from the custom list that is created named "AbusiveWordList". This list contains abusive words.
The chkbody function which will reference list item from custom list named "AbusiveWordList" and check if the bodytext contains item from AbusiveWordList.If yes, then it will throw an error.
*base.ItemAdding(properties);
foreach (DictionaryEntry
dictionaryEntry in
properties.AfterProperties) { string
bodytext = "";
bodytext = bodytext +
dictionaryEntry.Value;
finalwordcount = finalwordcount +
chkbody(bodytext, properties); }
if (finalwordcount > 0) {
properties.ErrorMessage = "Abusive /
Foul / Illicit information
found.Kindly refer to the terms and
conditions.";
properties.Cancel = true;
}

You will probably need to override any controls that display text to avoid this issue. As this would be a lot of work, perhaps an HTTP Module would be a better solution.
I've worked on a module that used regular expressions to make SharePoint's output XHTML compliant. Similarly, you could use regular expressions to strip out offensive words when a page is rendered. It wouldn't stop people typing them but as no-one would be able to see them this wouldn't matter. You could use a basic SharePoint custom list to store the offensive words you don't want displayed.

Related

How to get via Organisation service for Microsoft Dynamics the OptionSet value and Formatted value in different languages?

I have a custom .NET application to query and managing data on a Microsoft Dynamics CRM instance.
This application is multilingual and the user can change via a language switch the language of the application.
For the connection and actions I'm using the OrganizationService and CRMServiceClient from Microsoft.Xrm.Sdk. This is combined with dependency injection to pass the connection to our different classes.
With Ninject this bindings look like
Bind().To().WithConstructArgument("crmConnectionString","the connection string");
Querying and updating the data in Dynamics is working but we are not able to retrieve the OptionSet values and Formatted values in the language the visitor have selected in the custom app. This is always in the same language even when we change the culture for the Thread before we call Dynamics.
How can we pass the current language / culture to the OrganizationService so that it knows in what language it have to retrieve the fields?
Someone told me that this is based on the account used to connect to the CRM. So if that's indeed the case then it means that if we have 5 languages that we need to have 5 connection strings and 5 OrgnaizationService instances that need to be called. How should I handle this in a good way in that case?
Thanks for your answers
The solution I implemented was to use CallerId.
Before returning the client I fill the CallerId with a Guid.
The Guid is from a user configured with a specific language in Dynamics.
Based on the language I take a different user.
I don't know if you can pass a culture to the OrganizationService, and I think having different connection strings would work if you want to go this route.
However, you can query the CRM to retrieve the localized labels for the option set you want, as described here.
To sum it up, it's using a RetrieveAttributeRequest, passing the entity logical name and field name and looping trough the result to get the labels.
var request = new RetrieveAttributeRequest
{
EntityLogicalName = "incident",
LogicalName = "casetypecode"
};
var response = organizationService.Execute(request) as RetrieveAttributeResponse;
var optionSetAttributeMetadata = response.AttributeMetadata as EnumAttributeMetadata;
foreach (var option in optionSetAttributeMetadata.OptionSet.Options)
{
Console.WriteLine($"Localized labels for option {option.Value}:");
foreach (var locLabel in option.Label.LocalizedLabels)
{
Console.WriteLine($"Language {locLabel.LanguageCode}: {locLabel.Label}");
}
Console.WriteLine($"Localized description for option {option.Value}:");
foreach (var locLabel in option.Description.LocalizedLabels)
{
Console.WriteLine($"Language {locLabel.LanguageCode}: {locLabel.Label}");
}
}
The code in the link also add caching of already retrieved values, so that you only query the CRM once per option set.

iOS Localization of Server Provided Strings

I need to figure out what is the standard/best practice for displaying localized UI text in an iOS from text that is received from a remote source, such as API driven, server-provided text. iOS Localization of static text is not a problem and we already have a system for managing that.
It seems to me the right and best thing would be to have the translated text sent by the server and displayed as received on the app, but there are some concerns about doing it this way, such as the app's locale/current language being possibly different than the current settings on the server. This presents the possibility that there may be a mismatch in dialect or language between what the phone is currently set to and what the server is set to. Also, we are considering how having the server do this breaks any of the S.O.L.I.D. design principles.
So, it comes to two possibilities. Either the server provides the translated text or the app does.
We could possibly provide a parameter to the server that would indicate which locale the device is set to (ie "en-us"). I imagine that this would be sent as an HTTP request header parameter.
It has also been suggested that the mobile app provide similar functionality for itself. This would involve maintaining a data store of some kind (tbd) so that display strings would be given to a facade and translated strings would be returned. ie: func translate(uiText: String) -> String. Internally, it could determine the user's locale and use that as part of the query needed to select the correct translated text. Again, the implementation of this would have to be decided, but that's not the problem I'm hoping to find a solution for.
To sum it up, what I really need is to know what is standard practice for translating server provided text that is to be displayed to the user and are there any frameworks out there designed to assist with this requirement (assuming the solution should exist in the mobile app)?
It seems to me that this is functionality best provided by the server. Also note that we have an Android app that would require similar enhancement.
I think I found a solution to this question but I do not want to mark it as the accepted answer unless I can get some feedback reinforcing what I have learned.
Most of the research I've done has lead me to what works for Web development, which is similar because it's still development but a much different creature than mobile. Mobile is compiled, which makes the advantages and disadvantages of where to do the presentation logic balance a little differently.
Some sources said it belongs on the server where it came from. Some sources said the client should do it. (I'll post references at the end.)
I opened up a discussion amongst my colleagues on the topic and this is where I found what I think will be our best solution. (Comments and criticisms are certainly welcome.)
I'll refer to data provided by the server through the API here forth as just "server".
For every string that the server provides that is meant to be displayed in the UI, I need to have some way to define these strings statically in the iOS app. Ideally I think an enum per display string would work. I can wrap every string with NSLocalizedString in the definition of the enum. Make the enum a String type, and initialize an instance of the enum from the string received from the server. The enum will return the NSLocalizedString. The iOS Localization system should export all of those localized strings, I will receive translations, and they will then exist in the various respective .strings files.
EG:
enum Emotion: String {
case happy = "Happy"
case sad = "Sad"
case angry = "Angry"
case joy = "Joy"
case amused = "Amused"
case bored = "Bored"
case undefined = ""
func translation() -> String {
switch self {
case .happy:
return NSLocalizedString("Happy", comment: "Happy")
case .sad:
return NSLocalizedString("Sad", comment: "Sad")
case .angry:
return NSLocalizedString("Angry", comment: "Angry")
case .joy:
return NSLocalizedString("Joy", comment: "Joy")
case .amused:
return NSLocalizedString("Amused", comment: "Amused")
case .bored:
return NSLocalizedString("Bored", comment: "Bored")
default:
return "--"
}
}
}
Implementation:
let thisCameFromTheServer: String? = "Happy"
let emo = Emotion(rawValue: thisCameFromTheServer ?? "") ?? .undefined
References
https://softwareengineering.stackexchange.com/questions/313726/where-should-i-do-localization-server-side-or-client-side
https://softwareengineering.stackexchange.com/questions/373395/api-internationalization
https://www.appliedis.com/localization-of-xcode-ios-apps-part-1/

How to Let Chrome History Ignore Part of URL

As my work involves viewing many items from a website, I need to know which items have been visited and which not, so as to avoid repeated viewing.
The problem is that the URL of these items include some garbage parameters that are dynamically changing. This means the browser's history record is almost useless in identifying which items have already been viewed.
This is an example of the URL:
https://example.com/showitemdetail/?item_id=e6de72e&hitkey=true&index=234&cur_page=1&pageSize=30
Only the "item_id=e6de72e" part is useful in identifying each item. The other parameters are dynamic garbage.
My question is: how to let Chrome mark only the "example.com/showitemdetail/?item_id=e6de72e" part as visited, and ignore the rest parameters?
Please note that I do NOT want to modify the URLs, because that might alarm the website server to suspect that I am abusing their database. I want the garbage parameters to be still there, but the browser history mechanism to ignore them.
I know this is not easy. I am proposing a possible solution, but do not know whether it can be implemented. It's like this:
Step: 1) An extension background script to extract the item_id from each page I open, and then store it in a collection of strings. This collection of strings should be saved in a file somewhere.
Step: 2) Each time I open a webpage with a list of various items, the background script verifies whether each URL contains a string which matches any one in the above collection. If so, that URL would be automatically added to history. Then that item will naturally be shown as visited.
Does the logic sound OK? And if so how to implementable it by making a simple extension?
Of course, if you have other more neat solutions, I'd be very interested to learn.
Assuming that the link to the items always have the item_id, that would work, yes.
You would need the following steps:
Recording an element
content_script that adds a code to the product pages and tracks it.
On accessing the product page:
i. You can extract the current product id by checking the URL parameters (see one of these codes).
ii. You use storage api to retrieve a certain stored variable, say: visited_products. This variable you need to implement it as a Set since it's the best data type to handle unique elements.
iii. You check whether the current element is on the list with .has(). If yes, then you skip it. If all is good, it should always be new, but no harm in checking. If not, then you use add() to add the new product id (although Set will not allow you to add a repeated items, so you can skip the check and just save add it directly). Make sure you store it to Chrome.
Now you have registered a visit to a product.
Checking visited elements
You use a content_script again to be inserted on product pages or all pages if desired.
You get all the links of the page with document.querySelectorAll(). You could apply a CSS selector like: a[href*="example.com/showitemdetail/?item_id="] which would select all the links whose href contains that URL portion.
Then, you iterate the links with a for loop. On each iteration, you extract the item_id. Probably, the easiest way is: /(?:item_id=)(.*?)(?:&|$)/. This matches all characters preceded by item_id= (not captured) until it finds an & or end of the string (whichever happens first, and not captured).
With the id captured, you can check the Set of the first part with .has() to see whether it's on the list.
Now, about how to handle whether it's on the list, depends on you. You could hide visited elements. Or apply different CSS classes or style to them so you differentiate them easily.
I hope this gives you a head start. Maybe you can give it a try and, if you cannot make it work, you can open a new question with where you got stuck.
Thanks a lot, fvbuendia. After some trial and error elbow grease, I made it.
I will not post all the codes here, but will give several tips for other users' reference:
1) To get the URL of newly opened webpage and extract the IDs, use chrome.tabs.onUpdated.addListener and extractedItemId = tab.url.replace(/..../, ....);
2) Then save the IDs to storage.local, using chrome.storage.local.set and chrome.storage.local.get. The IDs should be saved to an object array.
1) and 2) should be written in the background script.
3) Each time the item list page is opened, the background calls a function in the content script, asking for all the URLs in the page. Like this:
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if(changeInfo.status == "complete") {
if(tab.url.indexOf("some string typical of the item list page URL") > -1) {
chrome.tabs.executeScript(null, { code: 'getalltheurls();' });
} }
});
4) The function to be executed in content script:
function getalltheurls() {
var urls = [];
var links = document.links;
for (var i = 0; i < links.length; i++) {
if(links[i].href.indexOf("some string typical of the item list URLs") > -1) { urls.push(links[i].href);}
}
chrome.runtime.sendMessage({ urls: urls });
};
5) Background receives the URLs, then converts them to an array of IDs, using
idinlist = urls[i].replace(........)
6) Then background gets local storage, using chrome.storage.local.get, and checks if these IDs are in the stored array. If so, add the URL to history.
for (var i = 0; i < urls.length; i++) {
if (storedIDs.indexOf(idinlist) > -1 ) { chrome.history.addUrl({ url: urls[i] }); }
}

Find an specific item in the master list of an split app by using oModel.createKey

I'm using a split app layout for editing and creating new employees. Therefore I do have a button "Add employee". After submitChanges is done, I want to find this new employee in the master list and select it.
I am using an event-bus for the communication between detail-controller and master-controller.
fnAfterSubmitChangesSuccess: function(sChanel, sEvent, oData) {
var oResponseData = oData.__batchResponses[0].__changeResponses[0].data;
var sBindingPath = oModel.createKey("/EmployeeSet", {Begda: oData.Begda, Endda: oData.Endda, Pernr: oData.Pernr}).replace(/:\s*/g, "%3A");
},
Is there a way to find the index of a specific listitem by the using binding-path. Or is there another way to solve this problem, instead of looping over the whole list a do a comparison?
I'm afraid the only way to find the index of a specific listItems by binding-path is to walk through the collection of list items. So, I'm afraid that a very plain and short answer would be "No".
It's quite easy though, code is not that lengthy, and it also shouldn't cost to much performance if you're not talking about humongous lists. You will have to walk through the list of items though. Once you have found the item with a binding to the context path you're looking for, you can select it using setSelectedItem, like so:
var list = this.getView().byId("list");
jQuery.each(list.getList(), function(idx, item) {
if (items.getBindingContext().getPath = sBindingPath) {
list.setSelectedItem(item);
}
});
Note: Do keep in mind that if you're working with OData services and are working with a so-called 'growing list', the entry you're looking for may not necessarily be in the list.
Apologies, wish I could give you a more pleasant answer.

What is available for limiting the use of extend when using Breezejs, such users cant get access to sensitive data

Basically this comes up as one of the related posts:
Isn't it dangerous to have query information in javascript using breezejs?
It was someone what my first question was about, but accepting the asnwers there, i really would appreciate if someone had examples or tutorials on how to limit the scope of whats visible to the client.
I started out with the Knockout/Breeze template and changed it for what i am doing. Sitting with a almost finished project with one concern. Security.
I have authentication fixed and is working on authorization and trying to figure out how make sure people cant get something that was not intended for them to see.
I got the first layer fixed on the root model that a member can only see stuff he created or that is public. But a user may hax together a query using extend to fetch Object.Member.Identities. Meaning he get all the identities for public objects.
Are there any tutorials out there that could help me out limiting what the user may query.?
Should i wrap the returned objects with a ObjectDto and when creating that i can verify that it do not include sensitive information?
Its nice that its up to me how i do it, but some tutorials would be nice with some pointers.
Code
controller
public IQueryable<Project> Projects()
{
//var q = Request.GetQueryNameValuePairs().FirstOrDefault(k=>k.Key.ToLower()=="$expand").Value;
// if (!ClaimsAuthorization.CheckAccess("Projects", q))
// throw new WebException("HET");// UnauthorizedAccessException("You requested something you do not have permission too");// HttpResponseException(HttpStatusCode.MethodNotAllowed);
return _repository.Projects;
}
_repository
public DbQuery<Project> Projects
{
get
{
var memberid = User.FindFirst("MemberId");
if (memberid == null)
return (DbQuery<Project>)(Context.Projects.Where(p=>p.IsPublic));
var id = int.Parse(memberid.Value);
return ((DbQuery<Project>)Context.Projects.Where(p => p.CreatedByMemberId == id || p.IsPublic));
}
}
Look at applying the Web API's [Queryable(AllowedQueryOptions=...)] attribute to the method or doing some equivalent restrictive operation. If you do this a lot, you can subclass QueryableAttribute to suit your needs. See the Web API documentation covering these scenarios.
It's pretty easy to close down the options available on one or all of your controller's query methods.
Remember also that you have access to the request query string from inside your action method. You can check quickly for "$expand" and "$select" and throw your own exception. It's not that much more difficult to block an expand for known navigation paths (you can create white and black lists). Finally, as a last line of defense, you can filter for types, properties, and values with a Web API action filter or by customizing the JSON formatter.
The larger question of using authorization in data hiding/filtering is something we'll be talking about soon. The short of it is: "Where you're really worried, use DTOs".

Resources