Link to home
Start Free TrialLog in
Avatar of Answers2000
Answers2000

asked on

Pluggable Protocols, urlmon - need a sample

Hi I am trying to write a program that embeds the Internet Explorer control using CHTMLView. This much is easy.

However I eventually will want the program to me able to read the data from a data-source that Internet Explorer doesn't normally support.  Basically I want to extend the protocol name space, for the duration that the program is running.

For example:
 
   myprotocol://index.htm  - would send a request to my code (which must also be inside the EXE for reasons relating distribution) asking my code to get the data for this HTML page (it could also be an image, etc.) and give back the data

I need a sample which demonstrates this inside a Windows MFC .exe program

The program should operate something like:

(1) When the program starts in opens up an SDI CHTMLView

(2) When the program starts it should also register a new protocol that the IE control will be able to understand

(3) Whenever the program navigates to a new URL which is part of my protocol's name space it will give my code the full URL and ask for the data back

(4) My code gives the data back

(5) CHTMLView shows the data I've returned.

(6) Steps (3) to (5) repeat until the user exits te program

(7) When the user exits, myprotocol is no longer part of the Internet Explorer name space.


For steps (3) and (4) for demo purposes, the sample could popup dialog showing the URL, and allowing entry of arbitary text into an edit control or something.

If somebody wants to write this sample - A grade - ZIP it and e-mail to sunil@answers2000.freeserve.co.uk

If somebody wants to give _detailed_ instructions on all the steps [not just a rehash of the developer documentation], or somebody knows something very close, I will consider your answer for a lower grade

Thanks!
Avatar of Answers2000
Answers2000

ASKER

Adjusted points to 750
Adjusted points to 1000
Here is the basic idea which will help you achieve what you want.

1. Override the OnBeforeNavigate2 function in HTML View

2. In this finction parse the URL you are recieving.

3. If it is not your protocol then do nothing

4. if this is your protocol then get the data you want, save it as a disk file and call a code like this

*pbCancel=1;
Stop();
Navigate2(_T("http://www.microsoft.com"),NULL,NULL);

this will redirect your CHTMLView to the file you just created.

The problem is that you will have to use your own AddressBar, because you don't want your customers to see the real address but yourptotocol://something

This is not hard to do at all - you will simply create an edit control and whenever the user enters an address there and presses enter you will call CHTMLView::Navigate2 function

If you want to reflect the changes of the URL the customer is browsing you can do this in OnBeforeNavigate2

A good place to delete your temporary file is OnDocumentComplete.

As for a source for all of the above I can send it to you monday or tuesday if you want
Sorry this isn't the answer I'm looking for.  

In case it wasn't absolutely clear, what I want to do is extend the protocol name space with pluggable protocols (or another method).

I do not want to create any temporary files as this blows any security of my application away. I need to have the web browser control call some kind of function in my application to get the data at the "magic" URLs.  My call back function can then return the data directly to IE.
then you can do this without using temporary files - instead of redirecting the browser, you redirect it to the local ip address on some port(http://127.0.0.1:23000 for example).
On this part a thread in your program is listening and transmits the result to the browser control. So you will have a mini Web Server in your apllicaiton.

This way you will not  compromise security, and the browser will get the data directly from your application.
You can evem make the port number dynamic - for every request you generate unique port number, and after the results are at the browser , you stop listening on that port.

If you don't like this solution , there is something else, but I can't be of much help to you - as far as I know a web browser can open a Windows Explorer namespace. So you can create your own Windows Explroer namespace extension. However it will appear always when Windows Explorer is open. But I don't know if this can be of any help and my personal opinion is even if this soultion can do the work, it is not good.
Temporary files - additionally to what I said previously, I don't think this can work even in theory. The problem is that if an HTML has a relative link or a relative reference to an image.  For links I appreciate I could pick up the navigation change and generate the file on navigate, but for images, they simply wouldn't exist.  In any case, the temporary files would have to have the exact same names as the contents of the HTML.  This is another reason why I can't use this approach in addition to the security issues.

Local Port - Actually I would have to stick to the same port number, or all links, image references etc. would be broken. Additionally my application would have to embed effectively a mini-WebServer into itself. I don't think this is very practical (?)

Name Spaces - now this is on the right lines.  I don't need a Windows Explorer name space - I need a pluggable protocol - which is what I said in my original question.  Search on pluggable protocols in the VC6 help, and you'll find a short (but difficult for me to comprehend) article on this topic.  This is what I want the sample of.  The big advantage of the pluggable protocol, is it's (a) seems to be designed to do exactly what I want to do, (b) all relative links are in the pluggable protocol name space - so relative HREF= and IMG SRC= links should work, and (c) doesn't require any temporary files or me to write a mini-web-server

So I'm back at my original question - has anybody got, or want to write, a sample MFC EXE containing a demo of pluggable protocols
So, you want your data source to show HTML data, in the CHTMLView?

Where does that data come from? Why do you want to have your own protocol reproviding HTML data?  Just so that it can be served from a local source?

..B ekiM
Thanks for the interest Mike

>> So, you want your data source to show HTML data, in the CHTMLView?

Yes that's right


>> Where does that data come from?

Initially the data will come solely from a local data source [which happens to be a disk file - see below for details].  Eventually the types of data sources may expand, although in all cases I expect to be dealing with this type of file (I think).

The actual data is basically consists of a set up of HTML pages, plus associated GIFs, JPEGs, etc.  These are all packed together into one fat proprietary file format.

The data file is in a proprietary file format, and also includes things like expiring pages, password protection on pages, and stuff like that. The data file may also include it's own private scripting mechanism intended to generate total new HTML/Image files on the fly.

I wish to observe all the rules of the file format as I decode it and send it to the browser.

I do NOT wish to break the file apart into separate disk files and leave the stuff lying around all over the hard-disk (anyway if I did this, it leaves a bunch of problems such as the passworded/expired pages would be left on the disk unprotected, and there's no way to interpret the scripts "on-the-fly").

>> Just so that it can be served from a local source?

Hopefully the above explains why I think I need my own protocol.  If you have another suggestion please let me know.


AND FINALLY

There is a slight additional complication...the actual interpreter/pluggable protocol/and viewer needs to be packed together into one exe (NOT a self-unzipping or similar), for some rather complicated reasons relating to distribution/delivery.    

So basically, as I see it the way I should do this is:

1. Create a viewer using MFC and CHTMLView

2. Inside the viewer I have a pluggable protocol for accessing this data source , example myprotocol://

3. Hopefully the pluggable protocol can call back to a C++ function inside my EXE to "get-a-chunk-of-data" from "this-named-HTML-or-GIF-or-JPEG-page"

4. Inside this call-back function I go off an interpret the file, interpret the files internal scripting languages etc, and return the data [this is non-trivial but at least there are no conceptual problems here, it's just a plain hard slog].


Basically it's steps #2 and #3 that I'm having trouble with.  

An MFC sample of this or something close would save my life :)  

Basically the reason I suggest for the sample to popup a dialog or something for the file data, is that [if somebody's writing a new sample] they would be able to demonstrate the concept without having to write any file reading code.

Please help Mike, I *know* you're one of the few who can.  

> Please help Mike, I *know* you're one of the few who can.  

Thank you for your kind words. My problem is time, though. You have some very elaborate requirements. I'd probably accept the assignment for a thousand _dollars_, but 1000 points isn't enough for me to rearrange my schedule and work on writing a bunch of software.

Maybe you can find someone who's got more time to help.

..B ekiM
I might consider paying if that's a serious offer :)

I do realize constraints on your time, so I don't want to demand too much, so if you have any hints they would be very much appreciated.
I dunno if this might help but you can always add html content to a webbrowser control using the about: protocol.

however this is limited to 2 K of html text

other than that I think you can load HTML data into the control using IPersistStreamInit inteface which is available via the IHTMLDocument interface.

so what I see you doing is

seeing if it is your protocol in the address bar (if not just navigate straight to it)

get the content from the page using the wininet functions and/or monikers. (examples at the MS web-site)

processing the data and turning it into HTML content

sending the data to the page.

Unfortunately I Have no idea on how to get images etc to get into the web-browser control without coming from an external source
Thanks for the idea

tchalkov has actually sent me code which is closed to what I want (his version shows pluggable protocol in an ATL).  

Due to other commitments I haven't got around to seeing if I can hack it into what I want yet.

At the moment I consider the question STILL open.  However to get the points you will need to give me a closer match to what I want.  If nobody does that, and I can figure out tchalkov's sample, then he will get the points.

....So I am inviting anybody who wants 1000 X A grade = 4000 quality points to go for it soon.
ShawnWilde> I dunno if this might help but you can always add
 ShawnWilde> html content to a webbrowser control using the about: protocol.

 ShawnWilde> however this is limited to 2 K of html text  

That's the wrong way to do it. If you want to learn the correct approach, please see the HOLDER.ZIP sample on my webpage at http://www.nwlink.com/~mikeblas/samples/ .  (Note that my webpage will soon move to http://www.mooseboy.com/ .)

..B ekiM
the about: protocol is a lot simpler to use if you only have a small amount of HTML to display and want to avoid the 2 step process using IPersistStreamInit - however if you do have a lot of HTML it is the better way to go.

pWebBrowser->Navigate2(_T("about:<TITLE>Shaun say's</TITLE><BODY><H1>England will win the Six Nations</H1></BODY>"),...);

also beware of using CHtmlView as a base class as it leaks heavily see Q241750 (mainly due to leaking of BSTRs)
Avatar of DanRollins
I hope that if tchalkov's answer is good, it will be included here, so anyone who pays the 'archived answer fee' will get something for their money!

Here's an idea:
Pack all of your HTML and GIF files and BMPs, etc. into the resource fork of an EXE or DLL file (use any file extension you want), then use the res: protocol.

Visual Studio will work well as your development environment.  Use the GUI tools and html color-coded text editor, then drop down and edit the RC file as needed.

Your html file can contain references to AVI, WAV, GIF, BMP, and probably anything else you want -- all stored as HTML blobs in the resource.

//--- in MyBlob.rc

INDEX.HTM   HTML DISCARDABLE "blob\\index.htm"
mySound.wav HTML DISCARDABLE "blob\\mySound.wav"
myLogo.JPG  HTML DISCARDABLE "blob\\myLogo.jpg"
myMovie.avi AVI  DISCARDABLE "blob\\showtime.avi"
myScript.js AVI  DISCARDABLE "blob\\myScript.js"

//--------------------- in index.htm
<html><head>
<script src="myScript.js"></script>
<BGSOUND="mySound.wav">
<body>
<img src="myLogo.jpg">
.... whatever...

As long as the original HTM file is loaded from the res: protocol, all refs in it refer to the same source.

You may still want to write a handler for OnBeforeNavigate2() to provide actions for your own special protocol:

void CvwHtml::OnBeforeNavigate2(LPCTSTR lpszURL,...etc...,BOOL* pbCancel )
{
  CString sURL= lpszURL;
  if ( (sURL.GetLength() >= 3) && (sURL.Left(3)=="abc") ) {
    // process whatever is after the "abc:"
      *pbCancel= TRUE;
      return;
  }
  else {
    CHtmlView::OnBeforeNavigate2(lpszURL, etc...); // base class handles it
  }

}

This effectively provides a simple 'callback' mechanism into your C++ code.  For instance, in your HTML file...

<input value="klik hear" type=button onclick="document.location='abc:DoThatCoolThing');">

<a href="abc:DoThatWayCoolThing">Access the Franibulation Aspect</a>

----------------------
I too, thought I'd need to use a pluggable protocol, but it looked way too complicated and frankly turned out to be overkill.  

Another thought:
You might consider accessing the DOM and setting the innerHTML of say, the BODY object to an arbitrary string of text (which you generate using whatever means).  This does not solve what happens when that generated html contains a IMG tag or other things from external embedded files.  

However, if copying just image files into a temp directory would not be too much of a security risk -- and they'll end up in the IE cache anyway -- then this might work for you.

One last thought:
If the file: protocol will work with named pipes (I don't have a clue), you can supply the data source completely in memory.

-- dan

ASKER CERTIFIED SOLUTION
Avatar of tchalkov
tchalkov

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Sorry I have left the question open so long.  I have had a ton of distractions.

Dan your answer is good except that in order to work a new set of HTML files, an EXE/DLL must be compiled, which unless you have another trick up your sleeve means (a) a manual process for each new set of files, and (b) to create compiled EXE/DLL/HTML viewers, access is needed to the C++ compiler each time.

Dan - if you do have a trick to avoid these issues, let me know and I'll open a new question and give you points.

tchalkov - Thanks for your patience, I am sorry to have left it so long.  You get the points as promised, though I am not actually using your stuff (yet)

Coincidentally I am back on this project since yesterday, so expect some more IE/CHTMLView questions.  

I have like a thousand things to do, and as documention is sparse in this area, I am going to be throwing out questions that I need quick answers - and quick points for anybody interested
Sorry for the wait
Please read my comments in this Q
And look for some easy points in new Qs coming soon
Back on the original question, if you still need it: I'm told there's a sample that demonstrates writing a pluggable protocol. It's called "Etcetera", and the scheme is etc:// .

Thing is, though a pretty reliable source told me about it, I can't find it. Maybe you can find it if you have more time/patience for your searching.

..B ekiM
>>in order to work a new set of HTML files, an EXE/DLL must be compiled, which unless you have another trick up your sleeve means
>>(a) a manual process for each new set of files,

RC.Exe and Link.Exe are both command-line driven programs.  You can automate these as surely as you can whatever other blob-creation mechanism you roll.  You could even use nmake.Exe.

>>and (b) to create compiled EXE/DLL/HTML viewers, access is needed to the C++ compiler each time.

It doesn't seem so to me... You need to write one viewer that reads data from the resources of a separate DLL.  You create just the data source for each "new set of files."  

BTW, the HtmlHelp ActiveX control (in conjunction with the HTML Help Workshop) does most of what you're looking to accomplish, with the added benefit that the complied HTML file are less than half the size of raw html.


To mikeblas:
I, too, searched in vain for the etcetera pluggabl protocol source code.  If it still exists, it is well hidden.  I built it once over a year ago, but soon realized that if I used it I'd have great gobs of incomprehensible (read unmaintainable) code in my project :-)

-- dan


> It's called "Etcetera", and the scheme is etc:// .

Hi mike - I think what you mean is EtcProtocol and is referred to in Dino Esposito's Cutting Edge article

http://www.microsoft.com/mind/0199/cutting/cutting0199.htm

and

Q180367 FILE: EtcProtocol Demonstrates Pluggable Protocol Handler

However all of the MS links seem to be broken as regards this sample (has it been pulled?)

a sample one can be found at the code-guru web-site

http://www.codeguru.com/atl/asyncpp.shtml

however that took a little fiddling to get it to work - Missing registry entries :( .

Sorry for the late overkill of info - but I have just implemented one recently
using the above CodeGuru sample as a basis and I forgot this Question hadn't been answered (or accepted).

Now I have done this the Asynchronous pluggable protocol is the way to go (NOTE the MSDN library uses one called mk: - I think?) The above CodeGuru sample is quite easy to modify to talk to a custom source of data (like a database or memory block) and saves having to write thing to disk such as images in order to get them to display
> (has it been pulled?)

Yep, it has.  A replacement is forthcoming.

..B ekiM
> Yep, it has.  A replacement is forthcoming

when

why didn't they switch them at the same time?
> when

I was told it was in review, so it wouldn't be much longer.

 > why didn't they switch them at the same time?

I don't know.  You'd need to ask someone in PSS, obviously.

..B ekiM
** mikeblas **

It doesn't matter to me now.

I only required the sample as the codeguru sample had a bug/leak [IE wasn't releasing the object] which I had trouble tracking down - however I have since fixed it (and posted it to the site) and I have now put my own handler into production code. (similar to MSs use of the mk: one in the MSDN)

** tchalkov  **
> As soon as my answer is approved i'll post it here

where is it then ???

>and btw it is not so complicated to use a pluggable protocol

I bet it is :) - its even better than using the about: protocol or the IPersistStreamInit methods as you can get images into the webcontrol and other objects - without having to go via the disk or a web-site. I know you can use the res: protocol for this but having your own handler means you can generate your own images on-the-fly before adding them in.
**ShaunWilde**
i could not make a single file which contains the source so it will take too much space to post it here
anyone who wants the source(it is very simple and only shows the basics - I did it by using the information in MSDN only) - give me you e-mail and i'll send it to you. But as far as you have a working code I don't think that it will be of any use to you. It is written using VC++ 6.0 and ATL.
I don't pretend that the example is good.
And I said that it is not so complicated because I wrote the sample for about 30 min - including reading the help. There are a lot of things to take care for a real application , but the idea of a pluggable protocol is simple.