I'm stuck with an issue that I'm gonna try and explain clearly. I'm using a gtkmm webkit browser in a sort of embedded application to access php/html files. The point is that I fail to code a way for this webkit to handle downloads.
Oh, and I'm coding in C++.
The file to download currently looks like below in my HTML code :
<a href='excel/template_users.php'><img src='imgs/excelbis.png'/>Download Excel File</a>
The "template_users.php" file is just a way of forcing the user to download the file (you can also access to the website via a "classic" web browser). It contains only :
<?php
header("Content-disposition: attachment; filename=template_users.xls");
header("Content-type: application/vnd.ms-excel:");
readfile("template_users.xls");
?>
I've been trying to handle downloads by adding to my IntegratedBrowser class constructor (which instantiate the webkit) a connector to the signal "download-requested" :
gboolean ret = FALSE;
g_signal_connect(webView, "download-requested", G_CALLBACK(&IntegratedBrowser::downloadRequested), &ret);
And the associated method :
gboolean IntegratedBrowser::downloadRequested(WebKitWebView* webView, WebKitDownload *download, gboolean *handled)
{
const gchar* dest = webkit_download_get_uri(download);
webkit_download_set_destination_uri(download, dest);
return FALSE;
}
I should precise that everything runs of course fine when I'm trying to download the file via a "classic web browser". The c++ code compile smoothly, however, nothing happens when I click on the link using the webkit. I would like the file to be downloaded in a location chosen by the user if possible (downloading the file into a specific location is viable as well) when clicking on the link.
Have you got any idea of what I am doing incorrectly ?
Thanks for your answers !
Edit : now my downloadRequested method looks like that :
gboolean IntegratedBrowser::downloadRequested(WebKitWebView* webView, WebKitDownload *download, gboolean *handled)
{
const gchar* dest = g_strdup_printf("%s", "file:///home/user/test.xls");
webkit_download_set_destination_uri(download, dest);
return TRUE;
}
The return FALSE from your IntegratedBrowser::downloadRequested() method cancels the download. return TRUE should start it.
Also, you are getting the URI that you are downloading with webkit_download_get_uri() (e.g. http://my.website.com/myfile.jpeg) and setting that to be the destination URI. Set the destination URI to point to a local file instead (although leaving it unset probably downloads the file to a default location.)
If you want a file selector for choosing where to save the download, use GtkFileChooser and when you are done with it, retrieve a URI using gtk_file_chooser_get_uri().
Related
How do i set up a custom protocol handler in chrome? Something like:
myprotocol://testfile
I would need this to send a request to http://example.com?query=testfile, then send the httpresponse to my extension.
The following method registers an application to a URI Scheme. So, you can use mycustproto: in your HTML code to trigger a local application. It works on a Google Chrome Version 51.0.2704.79 m (64-bit).
I mainly used this method for printing document silently without the print dialog popping up. The result is pretty good and is a seamless solution to integrate the external application with the browser.
HTML code (simple):
Click Me
HTML code (alternative):
<input id="DealerName" />
<button id="PrintBtn"></button>
$('#PrintBtn').on('click', function(event){
event.preventDefault();
window.location.href = 'mycustproto:dealer ' + $('#DealerName').val();
});
URI Scheme will look like this:
You can create the URI Scheme manually in registry, or run the "mycustproto.reg" file (see below).
HKEY_CURRENT_USER\Software\Classes
mycustproto
(Default) = "URL:MyCustProto Protocol"
URL Protocol = ""
DefaultIcon
(Default) = "myprogram.exe,1"
shell
open
command
(Default) = "C:\Program Files\MyProgram\myprogram.exe" "%1"
mycustproto.reg example:
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Classes\mycustproto]
"URL Protocol"="\"\""
#="\"URL:MyCustProto Protocol\""
[HKEY_CURRENT_USER\Software\Classes\mycustproto\DefaultIcon]
#="\"mycustproto.exe,1\""
[HKEY_CURRENT_USER\Software\Classes\mycustproto\shell]
[HKEY_CURRENT_USER\Software\Classes\mycustproto\shell\open]
[HKEY_CURRENT_USER\Software\Classes\mycustproto\shell\open\command]
#="\"C:\\Program Files\\MyProgram\\myprogram.exe\" \"%1\""
C# console application - myprogram.exe:
using System;
using System.Collections.Generic;
using System.Text;
namespace myprogram
{
class Program
{
static string ProcessInput(string s)
{
// TODO Verify and validate the input
// string as appropriate for your application.
return s;
}
static void Main(string[] args)
{
Console.WriteLine("Raw command-line: \n\t" + Environment.CommandLine);
Console.WriteLine("\n\nArguments:\n");
foreach (string s in args)
{
Console.WriteLine("\t" + ProcessInput(s));
}
Console.WriteLine("\nPress any key to continue...");
Console.ReadKey();
}
}
}
Try to run the program first to make sure the program has been placed in the correct path:
cmd> "C:\Program Files\MyProgram\myprogram.exe" "mycustproto:Hello World"
Click the link on your HTML page:
You will see a warning window popup for the first time.
To reset the external protocol handler setting in Chrome:
If you have ever accepted the custom protocol in Chrome and would like to reset the setting, do this (currently, there is no UI in Chrome to change the setting):
Edit "Local State" this file under this path:
C:\Users\Username\AppData\Local\Google\Chrome\User Data\
or Simply go to:
%USERPROFILE%\AppData\Local\Google\Chrome\User Data\
Then, search for this string: protocol_handler
You will see the custom protocol from there.
Note: Please close your Google Chrome before editing the file. Otherwise, the change you have made will be overwritten by Chrome.
Reference:
https://msdn.microsoft.com/en-us/library/aa767914(v=vs.85).aspx
Chrome 13 now supports the navigator.registerProtocolHandler API. For example,
navigator.registerProtocolHandler(
'web+custom', 'http://example.com/rph?q=%s', 'My App');
Note that your protocol name has to start with web+, with a few exceptions for common ones (like mailto, etc). For more details, see: http://updates.html5rocks.com/2011/06/Registering-a-custom-protocol-handler
This question is old now, but there's been a recent update to Chrome (at least where packaged apps are concerned)...
http://developer.chrome.com/apps/manifest/url_handlers
and
https://github.com/GoogleChrome/chrome-extensions-samples/blob/e716678b67fd30a5876a552b9665e9f847d6d84b/apps/samples/url-handler/README.md
It allows you to register a handler for a URL (as long as you own it). Sadly no myprotocol:// but at least you can do http://myprotocol.mysite.com and can create a webpage there that points people to the app in the app store.
This is how I did it. Your app would need to install a few reg keys on installation, then in any browser you can just link to foo:\anythingHere.txt and it will open your app and pass it that value.
This is not my code, just something I found on the web when searching the same question. Just change all "foo" in the text below to the protocol name you want and change the path to your exe as well.
(put this in to a text file as save as foo.reg on your desktop, then double click it to install the keys)
-----Below this line goes into the .reg file (NOT including this line)------
REGEDIT4
[HKEY_CLASSES_ROOT\foo]
#="URL:foo Protocol"
"URL Protocol"=""
[HKEY_CLASSES_ROOT\foo\shell]
[HKEY_CLASSES_ROOT\foo\shell\open]
[HKEY_CLASSES_ROOT\foo\shell\open\command]
#="\"C:\\Program Files (x86)\\Notepad++\\notepad++.exe\" \"%1\""
Not sure whether this is the right place for my answer, but as I found very few helpful threads and this was one of them, I am posting my solution here.
Problem: I wanted Linux Mint 19.2 Cinnamon to open Evolution when clicking on mailto links in Chromium. Gmail was registered as default handler in chrome://settings/handlers and I could not choose any other handler.
Solution:
Use the xdg-settings in the console
xdg-settings set default-url-scheme-handler mailto org.gnome.Evolution.desktop
Solution was found here https://alt.os.linux.ubuntu.narkive.com/U3Gy7inF/kubuntu-mailto-links-in-chrome-doesn-t-open-evolution and adapted for my case.
I've found the solution by Jun Hsieh and MuffinMan generally works when it comes to clicking links on pages in Chrome or pasting into the URL bar, but it doesn't seem to work in a specific case of passing the string on the command line.
For example, both of the following commands open a blank Chrome window which then does nothing.
"c:\Program Files (x86)\Google\Chrome\Application\chrome.exe" "foo://C:/test.txt"
"c:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --new-window "foo://C:/test.txt"
For comparison, feeding Chrome an http or https URL with either of these commands causes the web page to be opened.
This became apparent because one of our customers reported that clicking links for our product from a PDF being displayed within Adobe Reader fails to invoke our product when Chrome is the default browser. (It works fine with MSIE and Firefox as default, but not when either Chrome or Edge are default.)
I'm guessing that instead of just telling Windows to invoke the URL and letting Windows figure things out, the Adobe product is finding the default browser, which is Chrome in this case, and then passing the URL on the command line.
I'd be interested if anyone knows of Chrome security or other settings which might be relevant here so that Chrome will fully handle a protocol handler, even if it's provided via the command line. I've been looking but so far haven't found anything.
I've been testing this against Chrome 88.0.4324.182.
open
C:\Users\<Username>\AppData\Local\Google\Chrome\User Data\Default
open Preferences then search for excluded_schemes you will find it in 'protocol_handler' delete this excluded scheme(s) to reset chrome to open url with default application
I have a default website in my IIS where I have created one virtual directory "wsdls".
I would want to gather statistics on how many requests are triggered to my virtual directory. This would need a request interception at web server level and gather statistics. "HTTPModule" was one of the many solutions I have considered which is suitable for such scenario. Hence I have started building one.
For testing purpose, I wanted to create a HTTP Module and apply it on a particular extension files (say *.wsdl) and on every GET request of any .wsdl files in this virtual directory, I will want to redirect the application to "www.google.com". This would demonstrate a good example of how HTTP Module can be used and deployed on IIS.
HTTPModule which is written using Visual Studio is shown below,
namespace Handler.App_Code
{
public class HelloWorldModule : IHttpModule
{
public HelloWorldModule(){
}
public String ModuleName{
get { return "HelloWorldModule"; }
}
// In the Init function, register for HttpApplication
// events by adding your handlers.
public void Init(HttpApplication application){
application.BeginRequest +=
(new EventHandler(this.Application_BeginRequest));
application.EndRequest +=
(new EventHandler(this.Application_EndRequest));
}
private void Application_BeginRequest(Object source,
EventArgs e)
{
// Create HttpApplication and HttpContext objects to access
// request and response properties.
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
context.Response.Redirect("www.google.com");
}
private void Application_EndRequest(Object source, EventArgs e)
{
//Nothing to be done here
}
public void Dispose() { }
}
}
Now I have done a build of this project for x64 version and I am able to browser successfully the "dll" file. Now I have to register this dll in IIS and whenever I try to access the *.wsdl files, the requests automatically divert to "www.google.com". Here is the next step I have done,
Then I have enabled the Handler mappings as shown below,
I am assuming that is it!! Nothing more to be done. I should be able to intercept the requests for all HTTP requests which are of the form "*.wsdl". This means whenever I access any wsdl from the server, control should be going back to google(Because of the logic written in begin request ). But unfortunately, I failed in achieving it. What can be done here?
One thing I noticed is that when you are trying to redirect to an external URL use
http://
So change
context.Response.Redirect("www.google.com");
to
context.Response.Redirect("http://www.google.com", true);
I could solve the problem what I am facing and below are the observations which were missing in my understanding and which helped me in solving my problem:
Locating proper web.config file :
Every website in IIS will be having a web.config file to have control over the application.
Since I am working with "Default Website", this refers to the directory "C:\\inetpub\\wwwroot"
There will be a "web.config" file which would be present in this director. Please create it if not already present.
Modifying web.config :
Once you have identified the file which needs to be modified, just add necessary module configuration to web.config
In this case, we would want to add a Module to the default website, the probably setting would be shown below,
Adding contents to bin directory :
Now if you try to run the application, the IIS would not find any dll or executable to run and hence we would need to keep the executables at a particular location.
Create a director if not already present with the name "bin" at the root of the directory and place all the dlls which you would want this website to execute. Sample shown below,
General Points to be considered:
Proper access must be given for the folder which consists of dll.
It is ideally not suggested to modify the entire website. It would be ideal if one works only on their web application.
If web.config is not found, we can create one.
If bin is not present in the web root directory, we can create one.
I have a Sitecore 6.4 setup where an editor can click a button to generate a Word doc. I was adding the file to the media library and that was working fine. The editor would click the button in the content editor, the file was generated, media item was generated, then the content editor would show the new item in the media library and the editor could click the "download" button on the ribbon or the item to download it. However, my media library was getting unnecessarily filled up so I am trying to bypass the media library.
Instead of making the file in an arbitrary location as before, I am putting it in the temp directory like this:
wordOutputPath = Sitecore.IO.FileUtil.GetWorkFilename(Sitecore.Configuration.Settings.TempFolderPath, printItem.Name, ".docx");
File.Copy(wordTemplatePath, wordOutputPath);
WordprocessingDocument doc = WordprocessingDocument.Open(wordOutputPath, true);
After I "fill in" the file with content, I do this:
Sitecore.Context.ClientPage.ClientResponse.Download(wordFilePath);
Now if I am logged in as a Sitecore admin I get the browser's download dialog and can download the file. However, if I am logged in as a non-admin user, I get a little clicking and whirring, so to speak, and the file is generated, but the save file dialog never comes up in the browser. I can go in through the file system and see & open the Word doc, and it looks fine.
I found something in the Sitecore release notes for 6.6:
Released Sitecore CMS and DMS 6.6.0 rev. 130111 (6.6.0 Update-3)
[...]
Miscellaneous
Only Administrators were allowed to download files. (316774, 348557)
This was a problem in several areas of the system, for example the Package Generator and the Export Language Wizard in the CMS. It also affected the Export Users Wizard in the ECM module.
So I tried using SecurityDisabler (no longer have the code handy) and UserSwitcher like this:
using (new Sitecore.Security.Accounts.UserSwitcher(Sitecore.Security.Accounts.User.FromName("sitecore\admin", false)))
{
Sitecore.Context.ClientPage.ClientResponse.Download(wordFilePath);
}
The IUSR and IIS_IUSRS accounts both have read, list & read/execute permissions on the temp folder and the individual files show read & read/execute permissions for those two accounts as well.
What can I do to allow non-admin users to download these files? Does the bug that was fixed in 6.6 have anything to do with it?
Thank you.
Calling Sitecore.Context.ClientPage.ClientResponse.Download() method will result in a Download command sent back to the Sitecore Client in the Web browser, which in turn will make a call back to the server to execute it. This will be why using a security switcher (or a security disabler for that matter) before calling the Sitecore.Context.ClientPage.ClientResponse.Download() method has no effect, as the admin only restriction is being applied to the download else where.
If you search through sitecore\shell directory in your webroot, you will find that there is a file called download.aspx. This should be the actual page the download request is sent to. This web form page inherits the Sitecore.Shell.DownloadPage class, so if you take a look at that class's implementation, you will find that the OnLoad method is implemented as such:
protected override void OnLoad(EventArgs e)
{
Assert.ArgumentNotNull(e, "e");
base.OnLoad(e);
string fileHandle = StringUtil.GetString(new string[] { base.Request.QueryString["file"] });
bool flag = false;
string filename = FileHandle.GetFilename(fileHandle);
if (!string.IsNullOrEmpty(filename))
{
fileHandle = filename;
flag = true;
}
if (!string.IsNullOrEmpty(fileHandle))
{
if (MediaManager.IsMediaUrl(fileHandle))
{
this.DownloadMediaFile(fileHandle);
}
else if (fileHandle.IndexOf("id=", StringComparison.OrdinalIgnoreCase) >= 0)
{
this.DownloadMediaById(fileHandle);
}
else if (flag || Context.IsAdministrator)
{
this.DownloadFile(fileHandle);
}
}
}
As you can see, the last if block has an IsAdministrator check which would be where your non-admin users are getting blocked.
Although I haven't 100% verified that this is where the problem lies, the download restriction issue can be resolved, by creating a new class that inherits Sitecore.Shell.DownloadPage and overrides the OnLoad implementation with some extra security checks as required. I recommend that you don't remove the IsAdministrator check altogether as it is there for a good reason. Update the Inherits attribute in the download.aspx to make it use it instead.
I want to change the default search provider of IE (9) by editing the registry file. I have followed the steps given in the link: http://www.online-tech-tips.com/internet-explorer-tips/change-default-search-engine-ie/.
But when I change DefaultScope value to a scope in SearchScopes, then restart the computer, or open IE, make a search in address bar, or close IE. The value of DefaultScope is restore to previous value.
Why? Or what is my mistake?
How to change the search provider engine of IE programatically (not in IE, may be through registry, or in my C++ code)? (I write a C++ program that need to change IE's search provider engine)
I have written this function for Firefox or Chrome. It works well.
With Firefox, those information is stored in the prefs.js file. I can
read or write information requisite to this file easily. With Chrome,
those information is stored in two files in user profile folder:
Preferences and Web Data files. The Preferences file is a JSON file. I
get those information easily by parsing this JSON file. But to set
search engine provider information for Chrome. We need to change those
information in Web Data file. Web Data file is a SQLite file. I use
SQLite library to access this.
With Internet Explorer, I can get those information in that registry
path. But I can't set those information with that registry path. So, I
think, like Chrome, IE (or registry) needs to change those information
somewhere. But I don't know where.
Here is a detailed answer to your question.
There are two options you may choose from use IOpenServiceManager:
CComQIPtr<IOpenServiceManager> spManager;
check(spManager.CoCreateInstance(__uuidof(OpenServiceManager), CLSCTX_ALL));
CComQIPtr<IOpenService> spService;
check(spManager->InstallService(PU_POSTINSTALL_ANT_SEARCH_PROVIDER_XML, &spService));
if(makeItDefault)
{
// Request that the user change their search default
check(spService->SetDefault( TRUE, hPromptParent ));
}
or modify the registry:
LPCWSTR searchScopesKeyName = L"Software\\Microsoft\\Internet Explorer\\SearchScopes";
createKey(rootKey, HKEY_CURRENT_USER, searchScopesKeyName);
std::wstring clsidString = findProviderClsid(false);
if( clsidString.empty() )
clsidString = mc_providerClsidString;
if( makeItDefault )
setStringValue( rootKey, mc_defaultScopeValueName, clsidString.c_str() );
ATL::CRegKey subKey;
createKey(subKey, rootKey.m_hKey, clsidString.c_str() );
setStringValue( subKey, mc_displayNameValueName, mc_providerName );
setStringValue( subKey, mc_faviconUrlValueName, mc_providerFaviconURL );
setStringValue( subKey, mc_urlValueName, mc_providerURL );
Just giving a side note that SetDefault function was deprecated on Microsoft Edge browser. Also, after KB3148198 update, it's blocked. Function will return
OS_E_CANCELLED instead.
Hey, I've got this nice little piece of code, much like all the other versions of this method of upload using WSS WebServices. I've got one major problem though - once I have uploaded a file into my doc list, and updated the list item to write a comment/description, the file is stuck there. What I mean is that this method will not overwrite the file once I've uploaded it. Nobody else out there seems to have posted this issue yet, so .. anyone?
I have another version of the method which uses a byte[] instead of a Stream .. same issue though.
Note: I have switched off the 'require documents to be checked out before they can be edited' option for the library. No luck tho .. The doc library does have versioning turned on though, with a major version being created for each update.
private void UploadStream(string fullPath, Stream uploadStream)
{
WebRequest request = WebRequest.Create(fullPath);
request.Credentials = CredentialCache.DefaultCredentials; // User must have 'Contributor' access to the document library
request.Method = "PUT";
request.Headers.Add("Overwrite", "t");
byte[] buffer = new byte[4096];
using (Stream stream = request.GetRequestStream())
{
for (int i = uploadStream.Read(buffer, 0, buffer.Length); i > 0; i = uploadStream.Read(buffer, 0, buffer.Length))
{
stream.Write(buffer, 0, i);
}
}
WebResponse response = request.GetResponse(); // Upload the file
response.Close();
}
Original credits to: http://geek.hubkey.com/2007/10/upload-file-to-sharepoint-document.html
EDIT -- major finding .. when I call it from my nUnit test project it works fine. It seems it only fails when I call it from my WCF application (nUnit running under logged on user account, WCF app has app pool running under that same user -- my account, which also has valid permissions in SharePoint).
Nuts. "Now where to start?!", I muses to myself.
SOLVED -- I found a little bug - the file was being created in the right place, but the update path was wrong.. I ended up finding a folder full of files with many, many new versions.. doh!
Why not use the out-of-the-box SharePoint webservice, Lists.asmx? You'll find it in
http://SITEURL/___vti_bin/Lists.asmx
Edit, I checked out the link and it seems you are calling the out of the box web service. This has got be versioning related then. Can you check out the different versions that exist in the doc lib of the specific file? see if it perhaps gets added as a minor version through the service?
Have you tried using a capital T? SharePoint's webdav header processing is not very likely to be case-sensitive, but the protocol does specify a capital T. Oh, and what is the response? A 412 error code or something altogether different?