Package blackberry.web.widget.policy

Source Code of blackberry.web.widget.policy.WidgetPolicy

/*
* Copyright 2010-2011 Research In Motion Limited.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package blackberry.web.widget.policy;

import java.util.Hashtable;

import net.rim.device.api.io.MalformedURIException;
import net.rim.device.api.io.URI;
import net.rim.device.api.web.WidgetAccess;

import blackberry.web.widget.util.WidgetUtil;

/**
*
*/
public class WidgetPolicy {

    private Hashtable _authorityCollection;
    private WidgetAccess _localAccess;

    /**
     * Apply widget security model to the requested URI to retrieve the corresponding <access> element from array.
     * http://www.w3.org/TR/2009/WD-widgets-access-20090618/#rfc3987
     *
     * @param request
     *            The requested URI.
     * @param accessList
     *            WidgetAccess array to loop through to find matching request.
     * @return Return true if the request should be allowed based on WebWorks' config.xml; false otherwise.
     */
    public WidgetAccess getElement( String request, WidgetAccess[] accessList ) {
        try {
            URI requestURI = URI.create( request.trim() );
            // require absolute URI's
            if( requestURI.isAbsolute() ) {

                // Initialize authority collection if it does not yet exist
                initializeAuthCollection( accessList );

                // Start with the full authority path and check if a WidgetAccess set exists for that path
                // If it does not exist, remove the first section of the authority path and try again
                String authString = getAuthorityFromString( request );
                String schemeString = getSchemeFromString( request );

                // Check for an authority string that has an existing key
                // Special case: Allow file protocol to proceed without an authority
                // Special case: Allow local protocol which is always without an authority
                // Special case: Allow data protocol which is always without an authority (let isMatch handle it)
                authString = authorityCheck( schemeString, authString );
                if( authString.equals( "" ) && !( schemeString.equals( "file" ) || schemeString.equals( "local" ) || schemeString.equals( "data" ) ) ) {
                    return null;
                }

                WidgetWebFolderAccess folderAccess;
                WidgetAccess fetchedAccess = null;

                // Retrieve WidgetAccess set for the specified authority
                folderAccess = (WidgetWebFolderAccess) _authorityCollection.get( schemeString + "://" + authString );

                // Special case: no access element was found for a file protocol request.
                // This is added since file protocol was allowed through the above check
                if( schemeString.equals( "file" ) && folderAccess == null ) {
                    return null;
                }
               
                // If no access element is found with local URI, use local access for this request
                if ( schemeString.equals( "local" ) && folderAccess == null ) {
                    return _localAccess;
                }
               
                if(folderAccess != null) {
                    fetchedAccess = folderAccess.getWidgetAccess( requestURI.getPath() + parseNull( requestURI.getQuery() ) );
                }
                if( !isMatch( fetchedAccess, requestURI ) ) {
                    fetchedAccess = folderAccess.getWidgetAccess( requestURI.getPath() + "*" );
                }

                boolean failedToFindAccess = false;
                // Make sure we've got the right one
                while( fetchedAccess == null || !isMatch( fetchedAccess, requestURI ) ) {

                    // There was an auth url that matched, but didnt match the folder structure
                    // Try the next level up
                    authString = authString.substring( authString.indexOf( '.' ) + 1 );

                    // Check for an authority string that has an existing key
                    authString = authorityCheck( schemeString, authString );
                    if( authString.equals( "" ) ) {
                        failedToFindAccess = true;
                        break;
                    }

                    // Retrieve WidgetAccess set for the specified authority
                    folderAccess = (WidgetWebFolderAccess) _authorityCollection.get( schemeString + "://" + authString );

                    // Special case: no access element was found for a file protocol request.
                    // This is added since file protocol was allowed through the above check
                    if( schemeString.equals( "file" ) && folderAccess == null ) {
                        return null;
                    }

                    fetchedAccess = folderAccess.getWidgetAccess( requestURI.getPath() + parseNull( requestURI.getQuery() ) );
                }
               
                if( !failedToFindAccess ) {
                    return fetchedAccess;
                } else if ( isMatch( _localAccess, requestURI ) ) {
                  // If we cannot find a more specific access for this local URI, use local access
                  return _localAccess;
                }
            }
        } catch( MalformedURIException mue ) {
            // invalid request URI - return null
        }
        return null;
    }

    private boolean isMatch( WidgetAccess access, URI toMatchURI ) {
        if( access == null ) {
            return false;
        }

        // Look for local first
        if( WidgetUtil.isLocalURI( toMatchURI ) && access.isLocal() ) {
            // local access always allowed
            return true;
        }
        // Check for data url
        else if( WidgetUtil.isDataURI( toMatchURI ) ) {
            // data urls are allowed
            return true;
        } else if( access.isLocal() ) {
            return false;
        }

        // Based on widgets 1.0 (access control)
        // http://www.w3.org/TR/2009/WD-widgets-access-20090618/#rfc3987
        URI referenceURI = access.getURI();
        boolean allowSub = access.allowSubDomain();

        // Start comparison based on widgets spec.
        // 1. Compare scheme
        if( !referenceURI.getScheme().equalsIgnoreCase( toMatchURI.getScheme() ) ) {
            return false;
        }
        // 2. Compare host - if subdoman is false, host must match exactly
        // (referenceURI MUST HAVE host specified - not null.)
        String refHost = referenceURI.getHost();
        String matchHost = toMatchURI.getHost();
        if( matchHost == null ) {
            return false;
        }
        if( !allowSub && !( refHost.equalsIgnoreCase( matchHost ) ) ) {
            return false;
        }
        // 3. Compare host - if subdomain is true, check for subdomain or match
        if( allowSub && !matchHost.toLowerCase().endsWith( "." + refHost.toLowerCase() ) && !matchHost.equalsIgnoreCase( refHost ) ) {
            return false;
        }
        // 4. Compare port
        String refPort = parseNull( referenceURI.getPort() );
        String toMatchPort = parseNull( toMatchURI.getPort() );
        if( !refPort.equals( toMatchPort ) ) {
            return false;
        }
        // 5. Compare path+query
        String refPath = referenceURI.getPath() + parseNull( referenceURI.getQuery() );
        String toMatchPath = toMatchURI.getPath() + parseNull( toMatchURI.getQuery() );
        if( refPath.endsWith( "*" ) ) {
            refPath = refPath.substring( 0, refPath.length() - 1 );
        }
        if( !toMatchPath.startsWith( refPath ) ) {
            return false;
        }
        return true;
    }

    private String parseNull( String toParse ) {
        return toParse == null ? "" : toParse;
    }

    /**
     * Initalizes the collection of authority urls with their proper WidgetAccess elements
     *
     * @param accessList
     *            List of WidgetAccess elements to add into the collection
     */
    private void initializeAuthCollection( WidgetAccess[] accessList ) {

        // Initialize collection if it does not yet exist
        if( _authorityCollection == null ) {
            _authorityCollection = new Hashtable();

            // Loop access elements and add them to the authority collection
            for( int i = 0; i < accessList.length; i++ ) {
                WidgetAccess currentAccess = accessList[ i ];
                URI currentURI = currentAccess.getURI();

                // Special case: local access does not go into the collection because it has no URI
                if( currentAccess.isLocal() ) {
                    _localAccess = currentAccess;
                } else {
                    WidgetWebFolderAccess folderAccess;

                    // Check the authority collection to see if the authority item we want already exists
                    if( _authorityCollection.containsKey( currentURI.getScheme() + "://" + currentURI.getAuthority() ) ) {
                        folderAccess = (WidgetWebFolderAccess) _authorityCollection.get( currentURI.getScheme() + "://"
                                + currentURI.getAuthority() );
                    } else {
                        // Create web folder access
                        folderAccess = new WidgetWebFolderAccess();
                    }

                    // Add folder path access to the authority item
                    folderAccess.addWidgetAccess( currentURI.getPath() + parseNull( currentURI.getQuery() ), currentAccess );
                    _authorityCollection.put( currentURI.getScheme() + "://" + currentURI.getAuthority(), folderAccess );

                }
            }
        }

    }

    /**
     * Retrieves the authority portion of a URL string
     *
     * @param url
     *            URL to parse for authority
     * @return authority URL
     */
    private String getAuthorityFromString( String url ) {
        try {
            URI uriObject = URI.create( url );
            return uriObject.getAuthority();
        } catch( MalformedURIException mue ) {
            // invalid request URI - return null
            return null;
        }
    }

    /**
     * Retrieves the scheme portion of a URL string
     *
     * @param url
     *            URL to parse for authority
     * @return scheme of the URL
     */
    private String getSchemeFromString( String url ) {
        try {
            URI uriObject = URI.create( url );
            return uriObject.getScheme();
        } catch( MalformedURIException mue ) {
            // invalid request URI - return null
            return null;
        }
    }

    /**
     * Process the given scheme and authority and returns an authority which exists in the authority collection
     *
     * @param scheme
     *            Scheme of the request url
     * @param authString
     *            Authority of the request url
     * @return Authority which exists in the authority collection
     */
    private String authorityCheck( String scheme, String authString ) {
        if(authString == null) {
            authString = "";
        }

        boolean firstPass = true;
        while( !_authorityCollection.containsKey( scheme + "://" + authString ) ) {

            // If the authority is empty string, then no access element exists for that subdomain
            // Also, if the auth becomes a top level domain and is not found, then stop as well
            // First pass will allow computer names to be used
            if( authString.equals( "" ) || ( ( authString.indexOf( '.' ) == -1 ) && !firstPass ) ) {
                return "";
            }
            authString = authString.substring( authString.indexOf( '.' ) + 1 );

            // Set the flag
            if( firstPass ) {
                firstPass = false;
            }
        }
        return authString;
    }
}
TOP

Related Classes of blackberry.web.widget.policy.WidgetPolicy

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.