I'm using ASP.NET plugin for reCAPTCHA in my ASP.NET MVC application. Recaptcha assembly version is 1.0.4.0. Is there a way to set language to be used for RecaptchaControl?
var captchaControl = new Recaptcha.RecaptchaControl
{
ID = "recaptcha",
Theme = "blackglass",
PublicKey = "public_key",
PrivateKey = "private_key"
};
This feature was not supported in v1.0.4.0. Please download the latest version and try again.
http://code.google.com/p/recaptcha/downloads/detail?name=recaptcha-dotnet-1.0.5.0-binary.zip
with the help of this article here is how I've done it. the key is editing the generated html at the end; replacing "RecaptchaOptions = {" with "RecaptchaOptions = { lang : 'supported_language_code',"
public static string GenerateCaptcha(this HtmlHelper helper)
{
var captchaControl = new Recaptcha.RecaptchaControl
{
ID = "recaptcha",
Theme = "clean",
PublicKey = "public_key_here",
PrivateKey = "private_key_here"
};
var htmlWriter = new HtmlTextWriter(new StringWriter());
captchaControl.RenderControl(htmlWriter);
var html = htmlWriter.InnerWriter.ToString();
html = html.Replace("RecaptchaOptions = {", "RecaptchaOptions = { lang : 'tr', ");
return html;
}
EDIT: A cleaner solution is given here. (System.Web.Helpers)
Related
I have the Presentation Web Script (script A) and the Data Web Script (script B).
In the script A I build the dialog that interacts with the script B.
Here I am forming some path where the some file will be uploaded (group, year and number parameters define this path):
...
var submitHandler = function() {
var dataWebScriptUrl = window.location.protocol + '//' +
window.location.host + "/alfresco/s/ms-ws/script-b?guest=true";
var yearCombo = document.getElementById("year");
var year = yearCombo.options[yearCombo.selectedIndex].value;
var groupCombo = document.getElementById("group");
var group = groupCombo.options[groupCombo.selectedIndex].value;
var numberCombo = document.getElementById("number");
var number = numberCombo.value;
var uploadedFile = document.getElementById("uploadedFile");
var file = uploadedFile.files[0];
var formData = new FormData();
formData.append("year", year);
formData.append("group", group);
formData.append("number", number);
formData.append("uploadedFile", file);
var xhr = new XMLHttpRequest();
xhr.open("POST", dataWebScriptUrl);
xhr.send(formData);
};
...
In script B, I'm using the Apache Chemistry OpenCMIS API to create a path in the CMIS-compatible Alfresco repository:
public class CustomFileUploader extends DeclarativeWebScript implements OpenCmisConfig {
...
private void retrievePostRequestParams(WebScriptRequest req) {
String groupName = null, year = null, number = null;
FormData formData = (FormData) req.parseContent();
FormData.FormField[] fields = formData.getFields();
for(FormData.FormField field : fields) {
String fieldName = field.getName();
String fieldValue = field.getValue();
if(fieldName.equalsIgnoreCase("group")) {
if(fieldValue.equalsIgnoreCase("services")) {
groupName = "Услуги";
...
}
firstLevelFolderName = "/" + groupName;
secondLevelFolderName = groupName + " " + year;
thirdLevelFolderName = number;
}
...
Folder firstLevelFolder =
createFolderIfNotExists(cmisSession, docLibFolder, firstLevelFolderName);
...
private Folder createFolderIfNotExists(Session cmisSession,
Folder parentFolder, String folderName) {
Folder subFolder = null;
for(CmisObject child : parentFolder.getChildren()) {
if(folderName.equalsIgnoreCase(child.getName())) {
subFolder = (Folder) child;
}
}
if(subFolder == null) {
Map<String, Object> props = new HashMap<>();
props.put("cmis:objectTypeId", "cmis:folder");
props.put("cmis:name", folderName);
subFolder = parentFolder.createFolder(props);
}
return subFolder;
}
private Folder getDocLibFolder(Session cmisSession, String siteName) {
String path = "/Sites/" + siteName + "/documentLibrary";
return (Folder) cmisSession.getObjectByPath(path);
}
private Session getCmisSession() {
SessionFactory factory = SessionFactoryImpl.newInstance();
Map<String, String> conf = new HashMap<>();
// http://localhost:8080/alfresco/api/-default-/public/cmis/versions/1.1/atom
conf.put(SessionParameter.ATOMPUB_URL, ATOMPUB_URL);
conf.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value());
conf.put(SessionParameter.USER, USER_NAME);
conf.put(SessionParameter.PASSWORD, PASSWORD);
// "org.alfresco.cmis.client.impl.AlfrescoObjectFactoryImpl"
conf.put(SessionParameter.OBJECT_FACTORY_CLASS, OBJECT_FACTORY_CLASS);
conf.put(SessionParameter.REPOSITORY_ID, "-default-");
Session session = factory.createSession(conf);
return session;
}
...
It's all works well... But I need to create the directory structure on a specific site, e.g. "contracts-site", here:
/site/contracts-site/documentlibrary
When I specifying the following:
/Sites/contracts-site/documentLibrary/Услуги
/Sites/contracts-site/Услуги
/site/contracts-site/documentlibrary/Услуги
I get the following exception (depending on the path):
org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException: Object not found: /Sites/contracts-site/Услуги
When I specifying the following:
"/Услуги"
Everything works, but the directory structure is created outside the site...
How to create a folder on the Alfresco site by using OpenCMIS API?
Arn't you missing /company_home/ ?
This would lead to
/company_home/Sites/contracts-site/documentLibrary/Услуги
Just accidentally found the solution. Works perfectly if specify the following path:
// locate the document library
String path = "/Сайты/contracts-site/documentLibrary";
Ie, "Сайты" instead of "Sites"... (Cyrillic alphabet)
I'm using ru_RU locale and UTF-8 encoding. Then this example also works.
we have a textarea using CKEditor 4.4 on our admin website where users can edit content. They would like to be able to add images from their computer and have them uploaded automatically to the server for hosting.
I've seen a number of image upload scripts for CKEditor, but they all come with a PHP back-end. Does one exist for ASP.NET MVC 4?
I've seen this post and this one which show server-side controls for WebForms, but haven't been able to find an MVC version that we could drop in, or modify to our tastes.
Is my only option to use one of the existing PHP plugins and rewrite the endpoints as ASP.NET MVC?
Thanks.
Based on Alfonso's WebForms code mentioned in the accepted answer, I ended up using a script similar to this in MVC:
using System.Web;
using System.Web.Mvc;
namespace WebApplication1.Controllers
{
public class CKEditorController : Controller
{
const string basePath = #"D:\CKFinder\ckfinder\userfiles\";
const string baseUrl = #"/ckfinder/userfiles/";
const string scriptTag = "<script type='text/javascript'>window.parent.CKEDITOR.tools.callFunction({0}, '{1}', '{2}')</script>";
public ActionResult Index()
{
var funcNum = 0;
int.TryParse(Request["CKEditorFuncNum"], out funcNum);
if (Request.Files == null || Request.Files.Count < 1)
return BuildReturnScript(funcNum, null, "No file has been sent");
if (!System.IO.Directory.Exists(basePath))
return BuildReturnScript(funcNum, null, "basePath folder doesn't exist");
var receivedFile = Request.Files[0];
var fileName = receivedFile.FileName;
if (string.IsNullOrEmpty(fileName))
{
return BuildReturnScript(funcNum, null, "File name is empty");
}
var sFileName = System.IO.Path.GetFileName(fileName);
var nameWithFullPath = System.IO.Path.Combine(basePath, sFileName);
//Note: you may want to consider using your own naming convention for files, as this is vulnerable to overwrites
//e.g. at the moment if two users uploaded a file called image1.jpg, one would clash with the other.
//In the past, I've used Guid.NewGuid() combined with the file extension to ensure uniqueness.
receivedFile.SaveAs(nameWithFullPath);
var url = baseUrl + sFileName;
return BuildReturnScript(funcNum, url, null);
}
private ContentResult BuildReturnScript(int functionNumber, string url, string errorMessage)
{
return Content(
string.Format(scriptTag, functionNumber, HttpUtility.JavaScriptStringEncode(url ?? ""), HttpUtility.JavaScriptStringEncode(errorMessage ?? "")),
"text/html"
);
}
}
}
These aren't exactly MVC samples, but you can find a sample in VB.Net and C# to handle uploads from CKEditor: https://github.com/AlfonsoML/CKEditorUploader
Pick the code that you want and adjust it to your CMS.
The plugin sends the image asynchronously to the server. As long as you have an ASP.NET MVC/Web Api end point to accept the image and save it to the relavant place/update relevant tables, You should be good. Make sure you return data which your plugin is expecting.
for example, from the demo page you provided, the PHP server page is returning the following string on successful upload of the image
<script type="text/javascript">
window.parent.CKEDITOR.tools.callFunction("92", "\/userfiles\/images\/myImgy.jpg", "");
</script>
In your Web api endpoint, You can use HttpContext.Current.Request.Files collection to look for the posted files.
Try this
Html and JavaScript
<script src="~/Vendors/ckeditor/ckeditor.js"></script>
<script src="~/Vendors/ckeditor/adapters/jquery.js"></script>
<div class="jumbotron">
<textarea name="editor1"></textarea>
<script>
CKEDITOR.replace('editor1', {
uiColor: '#9AB8F3',
filebrowserUploadUrl: '/CkEditorUpload/'
});
</script>
</div>
Controller
using System;
using System.IO;
using System.Web;
using System.Web.Mvc;
namespace ImageUploadCkEditor.Controllers
{
public class CkEditorUploadController : Controller
{
const string filesavepath = "~/Content/Uploads/Ckeditor";
const string baseUrl = #"/Content/Uploads/Ckeditor/";
const string scriptTag = "<script type='text/javascript'>window.parent.CKEDITOR.tools.callFunction({0}, '{1}', '{2}')</script>";
public ActionResult Index()
{
var funcNum = 0;
int.TryParse(Request["CKEditorFuncNum"], out funcNum);
if (Request.Files == null || Request.Files.Count < 1)
return BuildReturnScript(funcNum, null, "No file has been sent");
string fileName = string.Empty;
SaveAttatchedFile(filesavepath, Request, ref fileName);
var url = baseUrl + fileName;
return BuildReturnScript(funcNum, url, null);
}
private ContentResult BuildReturnScript(int functionNumber, string url, string errorMessage)
{
return Content(
string.Format(scriptTag, functionNumber, HttpUtility.JavaScriptStringEncode(url ?? ""), HttpUtility.JavaScriptStringEncode(errorMessage ?? "")),
"text/html"
);
}
private void SaveAttatchedFile(string filepath, HttpRequestBase Request, ref string fileName)
{
for (int i = 0; i < Request.Files.Count; i++)
{
var file = Request.Files[i];
if (file != null && file.ContentLength > 0)
{
fileName = Path.GetFileName(file.FileName);
string targetPath = Server.MapPath(filepath);
if (!Directory.Exists(targetPath))
{
Directory.CreateDirectory(targetPath);
}
fileName = Guid.NewGuid() + fileName;
string fileSavePath = Path.Combine(targetPath, fileName);
file.SaveAs(fileSavePath);
}
}
}
}
}
I wish to get the data of Google analytics via service account.
When I launch first time the application, everything works correctly and I have access to the data. But When I launch second time the application I have the following error which appears: " the system cannot find the path specified ". Have you an idea? I thought it can be a lock.
This is my source code:
public static String GetAccessToken(string clientIdEMail, string keyFilePath, String scope)
{
// certificate
var certificate = new X509Certificate2(keyFilePath, "notasecret", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
// header
var header = new { typ = "JWT", alg = "RS256" };
// claimset
var times = GetExpiryAndIssueDate();
var claimset = new
{
iss = clientIdEMail,
scope = scope,
aud = "https://accounts.google.com/o/oauth2/token",
iat = times[0],
exp = times[1],
};
JavaScriptSerializer ser = new JavaScriptSerializer();
// encoded header
var headerSerialized = ser.Serialize(header);
var headerBytes = Encoding.UTF8.GetBytes(headerSerialized);
var headerEncoded = Convert.ToBase64String(headerBytes);
// encoded claimset
var claimsetSerialized = ser.Serialize(claimset);
var claimsetBytes = Encoding.UTF8.GetBytes(claimsetSerialized);
var claimsetEncoded = Convert.ToBase64String(claimsetBytes);
// input
var input = headerEncoded + "." + claimsetEncoded;
var inputBytes = Encoding.UTF8.GetBytes(input);
// signiture
var rsa = certificate.PrivateKey as RSACryptoServiceProvider;
var cspParam = new CspParameters
{
KeyContainerName = rsa.CspKeyContainerInfo.KeyContainerName,
KeyNumber = rsa.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2,
Flags = CspProviderFlags.UseMachineKeyStore
};
var aescsp = new RSACryptoServiceProvider(1024,cspParam) { PersistKeyInCsp = false };
var signatureBytes = aescsp.SignData(inputBytes, "SHA256");
var signatureEncoded = Convert.ToBase64String(signatureBytes);
// jwt
var jwt = headerEncoded + "." + claimsetEncoded + "." + signatureEncoded;
var client = new WebClient();
client.Encoding = Encoding.UTF8;
var uri = "https://accounts.google.com/o/oauth2/token";
var content = new NameValueCollection();
content["assertion"] = jwt;
content["grant_type"] = "urn:ietf:params:oauth:grant-type:jwt-bearer";
string response = Encoding.UTF8.GetString(client.UploadValues(uri, "POST", content));
JsonGoogleResponse result = (ser.Deserialize<JsonGoogleResponse>(response));
return result.access_token;
}
And this is the stack:
à System.Security.Cryptography.CryptographicException.ThrowCryptogaphicException(Int32 hr)
à System.Security.Cryptography.SafeProvHandle._FreeCSP(IntPtr pProvCtx)
à System.Security.Cryptography.SafeProvHandle.ReleaseHandle()
à System.Runtime.InteropServices.SafeHandle.InternalFinalize()
à System.Runtime.InteropServices.SafeHandle.Dispose(Boolean disposing)
à System.Runtime.InteropServices.SafeHandle.Finalize()
If you are running in IIS, you need to set "Load User Profile" to True in the application pool's advanced settings to be able to load a cert by filename & password.
So, I just had the exact same problem. I tried to solve it for almost 4 hours.
Problem was in passed path to key. Because I used the code from Google sample console application, where the path was just "key.p12" and the key was in the same directory as the exe file.
And when I wanted to create MVC application, I did not realize, that root of virtual server path can not be called just like "key.p12".
SOLUTION
Double check the path to the key. If it is MVC application (or another ASP web), then add the key file to the root and in code call the key by using Server.MapPath("key.p12").
I just had the same issue, in my case it was a space in the path. I have no idea why, but when I put the p12 file on c:\ root, it's working...
I am a Flex newbie and I'm developing a Flex application that needs to talk to an AMF server in order to authenticate the user.
Where should I store the server URL? I don't want to hardcode it in the source code, but the URL should be fixed at compile time, because when I compile the app it should be tied to a specific server.
If you need the URL at compile time but you don't want to "hardcode" it, the best thing to do is to store it in inline constants. They work as #IFDEF or #define on C/C++ and you can easy change the URL without changing the application (just re-compiling it).
You have to add something like this into your compiler options:
-define+=APP::amfServerUrl,'http://localhost/some/path/'
And then, on your app code:
private static const AMF_SERVER_URL:String = APP::amfServerUrl;
If it's not AIR, you could give your flash the server URL via FlashVars
HTML
<script type="text/javascript">
var flashvars = {gateway:'http://myserver/amfphp'
};
var params = {
menu: "false",
scale: "showAll",
allowFullscreen: "true",
allowScriptAccess: "always",
quality:"best",
bgcolor: "#FFFFFF"
};
var attributes = {
id:"main", name:"main"
};
swfobject.embedSWF("main.swf", "altContent", "100%", "100%", "10.0.0", "expressInstall.swf", flashvars, params, attributes);
</script>
Then to retrieve this parameter, use:
AS3
var gatewayUrl:String = stage.loaderInfo.parameters["gateway"];
I use an external config.xml file that resides on the server. My swf/wrapper are in the root, and the config is in a folder there named 'config'. Here is code from my current project that uses this config:
.
override protected function doStart() : void {
var xmlLoader : URLLoader = new URLLoader();
xmlLoader.addEventListener(Event.COMPLETE, result, false, EventPriority.DEFAULT_HANDLER, true);
xmlLoader.addEventListener(IOErrorEvent.IO_ERROR, fault, false, EventPriority.DEFAULT_HANDLER, true);
xmlLoader.load(new URLRequest("config/config.xml"));
}
public function fault(info : *) : void {
error("Failed to load config file.");
trace("Error Loading Configuration");
}
public function result(data : Event) : void {
var xml : XML = new XML(data.target.data);
var settings : Object = XMLMapperUtil.mapAppSettingsModelFromXML(xml);
var appSettingsModel : AppSettingsModel = AppSettingsModel.getInstance();
ExObjectUtil.copyObjectProperties(appSettingsModel, settings);
var secureString : String = (appSettingsModel.serverProtocol == 'https') ? "secure" : "";
var firstURLSegment : String =
appSettingsModel.serverProtocol
+ "://"
+ appSettingsModel.serverIP
+ ":"
+ appSettingsModel.serverPort
+ "/FlexClient/messagebroker/";
var remotingURL : String = firstURLSegment + "amf" + secureString;
var messagingURL : String = firstURLSegment + secureString + "streamingamf";
var remotingChannelSet : ChannelSet = new ChannelSet();
var messagingChannelSet : ChannelSet = new ChannelSet();
if (appSettingsModel.serverProtocol == 'https') {
remotingChannelSet.addChannel(new SecureAMFChannel("my-secure-amf", remotingURL));
messagingChannelSet.addChannel(new SecureStreamingAMFChannel("my-secure-amf-stream", messagingURL));
}
else {
remotingChannelSet.addChannel(new AMFChannel("my-amf", remotingURL));
messagingChannelSet.addChannel(new StreamingAMFChannel("my-streaming-amf", messagingURL));
}
appSettingsModel.remoteObject_ChannelSet = remotingChannelSet;
appSettingsModel.messaging_ChannelSet = messagingChannelSet;
complete();
}
My result function uses SpiceLab's XMLObjectMapper, a singleton, and a special property copying function to get the settings from the XML into a global object that I can use (appSettingsModel). All you really need to do is get that XML, parse it all out, and create some channels with the results. Oh, here is my XML file:
<AppSettingsModelXML
serverIP = "123.123.123.123"
serverPort = "8080"
serverProtocol = "http"/>
How can I add
<%# webservice class="MyNamespace.MyClass" ... %>
To the top of a CodeDom generated .asmx file?
Here's some code to fill this question out a bit more:
public void Generate<T>()
{
string[] importNameSpaces = new string[] { "System","CoreData","System.Web.Services", "System.Data", "System.Text", "System.Collections.Generic" };
targetUnit = new CodeCompileUnit();
CodeNamespace samples = new CodeNamespace(TargetNamespace);
foreach (string space in importNameSpaces)
{
samples.Imports.Add(new CodeNamespaceImport(space));
}
ClassName = typeof(T).Name;
CodeSnippetStatement WebServiceDirective = new CodeSnippetStatement("<%# WebService Language=\"C#\" CodeBehind=\"Plans.asmx.cs\" Class=\"" + TargetNamespace + "." + ClassName + "\" %>");
targetClass = new CodeTypeDeclaration(ClassName);
targetClass.IsClass = true;
targetClass.TypeAttributes =
TypeAttributes.Public;
targetClass.IsPartial = true;
CodeAttributeDeclaration WebServiceAtt = new CodeAttributeDeclaration(
new CodeTypeReference(
typeof(WebServiceAttribute)), new CodeAttributeArgument[]
{ new CodeAttributeArgument("Namespace",new CodeSnippetExpression(#"http://tempuri.org"))});
targetClass.CustomAttributes.Add(WebServiceAtt);
WebServiceAtt = new CodeAttributeDeclaration(
new CodeTypeReference(
typeof(WebServiceAttribute)),
new CodeAttributeArgument[]
{ new CodeAttributeArgument("ConformsTo", new CodeTypeReferenceExpression(WsiProfiles.BasicProfile1_1.GetType())) });
targetClass.CustomAttributes.Add(WebServiceAtt);
foreach (OperationType o in Enum.GetValues(typeof(OperationType)))
{
if (CoreData.Utility.SupportsOperation(typeof(T),o))
{
targetClass.Members.Add(createWebServiceMethod(typeof(T).Name,typeof(T).GetProperties(),o));
}
}
samples.Types.Add(targetClass);
targetUnit.Namespaces.Add(samples);
//targetUnit.StartDirectives.Add(WebServiceDirective);
CSharpCodeProvider provider = new CSharpCodeProvider();
IndentedTextWriter tw = new IndentedTextWriter(new StreamWriter(OutputDirectory + #"\" + targetClass.Name + ".asmx", false));
provider.GenerateCodeFromCompileUnit(targetUnit, tw, new CodeGeneratorOptions());
tw.Close();
}
CodeDom doesn't directly support generating ASMX files. It only supports languages such as C# and VB.
You'll have to insert the WebService directive manually. You might be able to do this by first writing the directive to the tw writer before passing it into the CodeDom provider.