Category Archives: Programming - Page 2

Protecting PDFs using FlexPaper

Download the compiled ReadOnly FlexPaperViewer.swf
*Note: Limited Functionality – see http://www.vigrond.com/flexpaper for ‘what you get’ – See tutorial below for which parameters work

Click here for Example

_____

Once Scribd made their switch to HTML5 for greater compatibility, it actually lost its great function to protect PDFs from being downloaded or printed.

On the search for some new technology, I found FlexPaper.

FlexPaper, in their own words, “… displays documents in your favorite browser using flash. Its way of reusing display containers makes it possible to view large documents and books.”

FlexPaper is programmed using a mix of Flash’s Flex & JavaScript, and is open-source under the GNU GPL license v3.

Natively, FlexPaper does not protect PDFs from being printed or copied.  It actually lacks options for doing so on the JavaScript front-end.  However in its Commercial License (to take the branding off for 1 domain) contains a ReadOnly parameter to disable printing & copying.

I am going to show you how to re-enable that ReadOnly parameter in the free GPL version using Flash Builder 4, disable the Flash container’s print option in the right-click context menu, and basically recompile the Flex build in the same original fashion as the Pre-compiled build of FlexPaper.

Note: This is not a hack.  It is actually suggested by FlexPaper’s developer (Eric) as a solution, albeit undocumented.

  1. Download both the Flex 4.0 & Pre-compiled (Flash) versions of FlexPaper:
    http://flexpaper.devaldi.com/download/
  2. Create a new Flex Project in Flash Builder 4 with default options (application type: Web)
  3. Once you get to the Library Path in the creation wizard, add the SWC file you got from FlexPaper’s Flex 4.0 build.
  4. Set “Framework linkage” to Merged into Code
    This will compile everything into a compacted SWF file, instead of having many different library files.
  5. Hit Finish
  6. Now you should be seeing your mxml file that looks something like this:
    <?xml version="1.0" encoding="utf-8"?>
    <s:Application 
    	xmlns:fx="http://ns.adobe.com/mxml/2009" 
    	xmlns:s="library://ns.adobe.com/flex/spark"
    	xmlns:mx="library://ns.adobe.com/flex/mx" width="100%" height="100%"
    	xmlns:flexpaper="com.devaldi.controls.flexpaper.*">
    	<fx:Declarations>
    		<!-- Place non-visual elements (e.g., services, value objects) here -->
    	</fx:Declarations>

     

  7. First we need to add the FlexPaperViewer component.  With your mxml file open, go into “Design” mode.  Then at the bottom left open up the Components tab.  Under the “Custom” folder drag  the FlexPaperView component into the project.
  8. Go back into “Source” mode.  You will now see your tag.
    Go ahead and set the following attributes

    <flexpaper:FlexPaperViewer id="viewer" ReadOnly="true" width="100%" height="100%" x="0" y="0">
    </flexpaper:FlexPaperViewer>

    id:

    our id variable we can reference later to set parameters

    ReadOnly:

    Set to “true” to disable Printing & Copying.  Note:  It is not recommended to set this parameter in the JavaScript as it presents a security hole on the client side.  If you have PDF files you want people to be able to print as well, create two versions – one with and one without ReadOnly

    width:

    Set to 100% to fill our HTML Element container

    height:

    Set to 100% to fill our HTML Element container

    x:

    set x-coordinate position to zero

    y:

    set y-coordinate position to zero

  9. Next we will create an Event Handler to read in flashvars from the JavaScript
  10. In our Application tag, add a creationComplete event handler
    <s:Application 
    	xmlns:fx="http://ns.adobe.com/mxml/2009" 
    	xmlns:s="library://ns.adobe.com/flex/spark" creationComplete="init()" 
    	xmlns:mx="library://ns.adobe.com/flex/mx" width="100%" height="100%"
    	xmlns:flexpaper="com.devaldi.controls.flexpaper.*">
    </s:Application>
  11. Now add a <fx:Script> tag, import the flashvars, and create the init() function for our event handler:
    	<fx:Script>
    		<![CDATA[
    			//import flashvars
    			import mx.core.FlexGlobals;	
     
    			//set our viewer parameters to the flashvars (not all included)
    			private function init():void{
     
                            }
                    ]]>
            </fx:Script>
  12. Inside this init() function is where the magic happens.  We will set all the parameters for our FlexPaperViewer depending on the flashvars.  We will also disable the Print option in the Flash context menu.Set the FlashPaperViewer parameters in this style:
    viewer.SwfFile = FlexGlobals.topLevelApplication.parameters.SwfFile;
    viewer.Scale = FlexGlobals.topLevelApplication.parameters.Scale;
    viewer.ZoomTransition = FlexGlobals.topLevelApplication.parameters.ZoomTransition;	
    viewer.ZoomTime = FlexGlobals.topLevelApplication.parameters.ZoomTime;	
    viewer.ZoomInterval = FlexGlobals.topLevelApplication.parameters.ZoomInterval;	
    viewer.FitPageOnLoad = FlexGlobals.topLevelApplication.parameters.FitPageOnLoad;	
    viewer.FitWidthOnLoad = FlexGlobals.topLevelApplication.parameters.FitWidthOnLoad;	
    viewer.FullScreenAsMaxWindow = FlexGlobals.topLevelApplication.parameters.FullScreenAsMaxWindow;	
    viewer.ProgressiveLoading = FlexGlobals.topLevelApplication.parameters.ProgressiveLoading;	
    viewer.switchMode(FlexGlobals.topLevelApplication.parameters.InitViewMode);

    This format will work for the following parameters:

    • SwfFile
    • Scale
    • ZoomTransition
    • ZoomTime
    • ZoomInterval
    • FitPageOnLoad
    • FitWidthOnLoad
    • FullScreenAsMaxWindow
    • ProgressiveLoading

    Non-native parameters (will have to be programmed into JavaScript flexpaper_flash.js library):

    • ReadOnly *Not recommended due to security hole presented by giving the client control
    • width / height *Setting to anything other than 100% will break Fullscreen mode

    Note: Other parameters and Event Handler methods for the Pre-Compiled Flash Build’s javascript functions are NOT provided here.  These are undocumented and will have to be additionally discovered.  It should not be hard given a look at the function list for the FlexPaperViewer component.  Connecting Flex applications to Javascript is also well-documented on Adobe’s site.

  13. To disable the Print option in the Flash container’s right-click Context menu is pretty easy:
    var customContextMenu:ContextMenu = new ContextMenu();
    //disable the default options
    customContextMenu.hideBuiltInItems();
    this.contextMenu = customContextMenu;
  14. Go to Project->Export Release Build, and now you got your project SWF in the bin-release folder, all-inclusive.  Flash Builder also includes a playerProductInstall.swf & an unneeded html container file to test with.
  15. Remember the Pre-Compiled Flash Build of FlexPaper we downloaded?  Go ahead and extract that.  Replace FlexPaperViewer.swf with the new one.
  16. Congratulations, now you have a read-only flash PDF viewer. Full Code:
    <!--?xml version="1.0" encoding="utf-8"?-->
     
    <?xml version="1.0" encoding="utf-8"?>
    <s:Application 
    	xmlns:fx="http://ns.adobe.com/mxml/2009" 
    	xmlns:s="library://ns.adobe.com/flex/spark" creationComplete="init()" 
    	xmlns:mx="library://ns.adobe.com/flex/mx" width="100%" height="100%"
    	xmlns:flexpaper="com.devaldi.controls.flexpaper.*">
    	<fx:Declarations>
    		<!-- Place non-visual elements (e.g., services, value objects) here -->
    	</fx:Declarations>
    	<flexpaper:FlexPaperViewer id="viewer" ReadOnly="true" width="100%" height="100%" x="0" y="0">
    	</flexpaper:FlexPaperViewer>
     
    	<fx:Script>
    		<![CDATA[
    			//import flashvars
    			import mx.core.FlexGlobals;	
     
    			//set our viewer parameters to the flashvars (not all included)
    			private function init():void{
    				viewer.SwfFile = FlexGlobals.topLevelApplication.parameters.SwfFile;
    				viewer.Scale = FlexGlobals.topLevelApplication.parameters.Scale;
    				viewer.ZoomTransition = FlexGlobals.topLevelApplication.parameters.ZoomTransition;	
    				viewer.ZoomTime = FlexGlobals.topLevelApplication.parameters.ZoomTime;	
    				viewer.ZoomInterval = FlexGlobals.topLevelApplication.parameters.ZoomInterval;	
    				viewer.FitPageOnLoad = FlexGlobals.topLevelApplication.parameters.FitPageOnLoad;	
    				viewer.FitWidthOnLoad = FlexGlobals.topLevelApplication.parameters.FitWidthOnLoad;	
    				viewer.FullScreenAsMaxWindow = FlexGlobals.topLevelApplication.parameters.FullScreenAsMaxWindow;	
    				viewer.ProgressiveLoading = FlexGlobals.topLevelApplication.parameters.ProgressiveLoading;	
    				viewer.switchMode(FlexGlobals.topLevelApplication.parameters.InitViewMode);
     
    				//disable Print option in Flash Context Menu
    				var customContextMenu:ContextMenu = new ContextMenu();
    				//disable the default menu options
    				customContextMenu.hideBuiltInItems();
    				this.contextMenu = customContextMenu;
     
    			}
     
    		]]>
    	</fx:Script>
     
    </s:Application>
  17. If there’s anyone out there who would just like the readonly SWF, just comment below and I’ll update the article