Skip to content
Snippets Groups Projects
Commit 9d518405 authored by Dariusz Janny's avatar Dariusz Janny
Browse files

[edugain/faas#33] faas-registry - shibboleth DS added.

parent 101f735a
Branches
Tags
1 merge request!5Master
Showing
with 3356 additions and 8 deletions
...@@ -15,7 +15,8 @@ RUN apt-get -q update && \ ...@@ -15,7 +15,8 @@ RUN apt-get -q update && \
apt-get -y autoremove && \ apt-get -y autoremove && \
apt-get -y clean apt-get -y clean
RUN a2enmod rewrite RUN a2enmod rewrite && \
a2enmod shib
#RUN git clone https://github.com/Edugate/Jagger /opt/rr3 && cd /opt/rr3 && git checkout v1.8.0 #RUN git clone https://github.com/Edugate/Jagger /opt/rr3 && cd /opt/rr3 && git checkout v1.8.0
RUN git clone https://github.com/Edugate/Jagger /opt/rr3 RUN git clone https://github.com/Edugate/Jagger /opt/rr3
...@@ -25,6 +26,9 @@ RUN cd /opt/rr3 && bash install.sh && \ ...@@ -25,6 +26,9 @@ RUN cd /opt/rr3 && bash install.sh && \
cd /opt/rr3/application/config && \ cd /opt/rr3/application/config && \
cp memcached-default.php memcached.php cp memcached-default.php memcached.php
COPY ./conf/etc/shibboleth/keygen.sh /etc/shibboleth/keygen.sh
COPY ./conf/etc/shibboleth-ds/ /etc/shibboleth-ds/
COPY ./conf/etc/registry/application/config/config.php /opt/rr3/application/config/config.php COPY ./conf/etc/registry/application/config/config.php /opt/rr3/application/config/config.php
COPY ./conf/etc/registry/application/config/config_rr.php /opt/rr3/application/config/config_rr.php COPY ./conf/etc/registry/application/config/config_rr.php /opt/rr3/application/config/config_rr.php
COPY ./conf/etc/registry/application/config/database.php /opt/rr3/application/config/database.php COPY ./conf/etc/registry/application/config/database.php /opt/rr3/application/config/database.php
......
...@@ -9,19 +9,19 @@ ...@@ -9,19 +9,19 @@
#ServerName www.example.com #ServerName www.example.com
ServerAdmin webmaster@localhost ServerAdmin webmaster@localhost
DocumentRoot /opt/rr3 DocumentRoot /opt/rr3/
ErrorLog ${APACHE_LOG_DIR}/error.log ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined CustomLog ${APACHE_LOG_DIR}/access.log combined
Alias /rr3 /opt/rr3 Alias / /opt/rr3/
<Directory /opt/rr3> <Directory /opt/rr3/>
Require all granted Require all granted
RewriteEngine On RewriteEngine On
RewriteBase /rr3 RewriteBase /
RewriteCond $1 !^(Shibboleth\.sso|index\.php|logos|signedmetadata|flags|images|app|schemas|fonts|styles|images|js|robots\.txt|pub|includes) RewriteCond $1 !^(Shibboleth\.sso|index\.php|logos|signedmetadata|flags|images|app|schemas|fonts|styles|images|js|robots\.txt|pub|includes)
RewriteRule ^(.*)$ /rr3/index.php?/$1 [L] RewriteRule ^(.*)$ /index.php?/$1 [L]
</Directory> </Directory>
<Directory /opt/rr3/application> <Directory /opt/rr3/application>
...@@ -34,6 +34,24 @@ ...@@ -34,6 +34,24 @@
require valid-user require valid-user
</Location> </Location>
<Location /shibboleth-ds>
Require all granted
<IfModule mod_shib.c>
AuthType shibboleth
ShibRequestSetting requireSession false
require shibboleth
</IfModule>
</Location>
<Directory /etc/shibboleth-ds/>
Require all granted
</Directory>
Alias /shibboleth-ds/idpselect_config.js /etc/shibboleth-ds/idpselect_config.js
Alias /shibboleth-ds/idpselect.js /etc/shibboleth-ds/idpselect.js
Alias /shibboleth-ds/idpselect.css /etc/shibboleth-ds/idpselect.css
Alias /shibboleth-ds/index.html /etc/shibboleth-ds/index.html
Alias /shibboleth-ds/blank.gif /etc/shibboleth-ds/blank.gif
# For most configuration files from conf-available/, which are # For most configuration files from conf-available/, which are
# enabled or disabled at a global level, it is possible to # enabled or disabled at a global level, it is possible to
# include a line for only one particular virtual host. For example the # include a line for only one particular virtual host. For example the
......
...@@ -45,4 +45,9 @@ cd /opt/rr3/application ...@@ -45,4 +45,9 @@ cd /opt/rr3/application
./doctrine orm:generate-proxies ./doctrine orm:generate-proxies
cd /etc/shibboleth/
./keygen.sh -n "sp-signing" -h ${FAAS_REGISTRY_HOSTNAME}
cp /etc/shibboleth/sp-signing-cert.pem /etc/shibboleth/sp-encrypt-cert.pem
cp /etc/shibboleth/sp-signing-key.pem /etc/shibboleth/sp-encrypt-key.pem
exec supervisord -c /etc/supervisord.conf exec supervisord -c /etc/supervisord.conf
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
conf/etc/shibboleth-ds/blank.gif

43 B

/* Top level is idpSelectIdPSelector */
#idpSelectIdPSelector
{
width: 389px;
text-align: left;
background-color: #FFFFFF;
border: 2px #A40000 solid;
padding: 10px;
}
/* Next down are the idpSelectPreferredIdPTile, idpSelectIdPEntryTile & idpSelectIdPListTile */
/**
* The preferred IdP tile (if present) has a specified height, so
* we can fit the preselected * IdPs in there
*/
#idpSelectPreferredIdPTile
{
height:138px; /* Force the height so that the selector box
* goes below when there is only one preslect
*/
}
#idpSelectPreferredIdPTileNoImg
{
height:60px;
}
/***
* The preselect buttons
*/
div.IdPSelectPreferredIdPButton
{
margin: 3px;
width: 120px; /* Make absolute because 3 of these must fit inside
div.IdPSelect{width} with not much each side. */
float: left;
}
/*
* Make the entire box look like a hyperlink
*/
div.IdPSelectPreferredIdPButton a
{
float: left;
width: 99%; /* Need a specified width otherwise we'll fit
the contents which we don't want because
they have auto margins */
}
div.IdPSelectTextDiv{
height: 3.5ex; /* Add some height to separate the text from the boxes */
font-size: 15px;
clear: left;
}
div.IdPSelectPreferredIdPImg
{
/* max-width: 95%; */
height: 69px; /* We need the absolute height to force all buttons to the same size */
margin: 2px;
}
img.IdPSelectIdPImg {
width:auto;
}
div.IdPSelectautoDispatchTile {
display: block;
}
div.IdPSelectautoDispatchArea {
margin-top: 30px ;
}
div.IdPSelectPreferredIdPButton img
{
display: block; /* Block display to allow auto centring */
max-width: 114px; /* Specify max to allow scaling, percent does work */
max-height: 64px; /* Specify max to allow scaling, percent doesn't work */
margin-top: 3px ;
margin-bottom: 3px ;
border: solid 0px #000000; /* Strip any embellishments the brower may give us */
margin-left: auto; /* Auto centring */
margin-right: auto; /* Auto centring */
}
div.IdPSelectPreferredIdPButton div.IdPSelectTextDiv
{
text-align: center;
font-size: 12px;
font-weight: normal;
max-width: 95%;
height: 30px; /* Specify max height to allow two lines. The
* Javascript controlls the max length of the
* strings
*/
}
/*
* Force the size of the selectors and the buttons
*/
#idpSelectInput, #idpSelectSelector
{
width: 80%;
}
/*
* For some reason a <select> width includes the border and an
* <input> doesn't hence we have to force a margin onto the <select>
*/
#idpSelectSelector
{
margin-left: 2px;
margin-right: 2px;
}
#idpSelectSelectButton, #idpSelectListButton
{
margin-left: 5px;
width: 16%;
}
#idpSelectSelectButton
{
padding-left: 2px;
padding-right: 2px;
}
/*
* change underlining of HREFS
*/
#idpSelectIdPSelector a:link
{
text-decoration: none;
}
#idpSelectIdPSelector a:visited
{
text-decoration: none;
}
#idpSelectIdPSelector a:hover
{
text-decoration: underline;
}
/*
* Arrange to have the dropdown/list aref on the left and the
* help button on the right
*/
a.IdPSelectDropDownToggle
{
display: inline-block;
width: 80%;
}
a.IdPSelectHelpButton
{
display: inline-block;
text-align: right;
width: 20%;
}
/**
* Drop down (incremental search) stuff - see the associated javascript for reference
*/
ul.IdPSelectDropDown {
-moz-box-sizing: border-box;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: small;
box-sizing: border-box;
list-style: none;
padding-left: 0px;
border: 1px solid black;
z-index: 6;
position: absolute;
}
ul.IdPSelectDropDown li {
background-color: white;
cursor: default;
padding: 0px 3px;
}
ul.IdPSelectDropDown li.IdPSelectCurrent {
background-color: #3366cc;
color: white;
}
/* Legacy */
div.IdPSelectDropDown {
-moz-box-sizing: border-box;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: small;
box-sizing: border-box;
border: 1px solid black;
z-index: 6;
position: absolute;
}
div.IdPSelectDropDown div {
background-color: white;
cursor: default;
padding: 0px 3px;
}
div.IdPSelectDropDown div.IdPSelectCurrent {
background-color: #3366cc;
color: white;
}
/* END */
This diff is collapsed.
/** @class IdP Selector UI */
function IdPSelectUIParms(){
//
// Adjust the following to fit into your local configuration
//
this.alwaysShow = true; // If true, this will show results as soon as you start typing
this.dataSource = '/Shibboleth.sso/DiscoFeed'; // Where to get the data from
this.defaultLanguage = 'en'; // Language to use if the browser local doesnt have a bundle
this.defaultLogo = 'blank.gif'; // Replace with your own logo
this.defaultLogoWidth = 1;
this.defaultLogoHeight = 1 ;
this.defaultReturn = null; // If non null, then the default place to send users who are not
// Approaching via the Discovery Protocol for example
//this.defaultReturn = "https://example.org/Shibboleth.sso/DS?SAMLDS=1&target=https://example.org/secure";
this.defaultReturnIDParam = null;
this.returnWhiteList = [ "^https:\/\/example\.org\/Shibboleth\.sso\/Login.*$" , "^https:\/\/example\.com\/Shibboleth\.sso\/Login.*$" ];
this.helpURL = 'https://wiki.shibboleth.net/confluence/display/SHIB2/DSRoadmap';
this.ie6Hack = null; // An array of structures to disable when drawing the pull down (needed to
// handle the ie6 z axis problem
this.insertAtDiv = 'idpSelect'; // The div where we will insert the data
this.maxResults = 10; // How many results to show at once or the number at which to
// start showing if alwaysShow is false
this.myEntityID = null; // If non null then this string must match the string provided in the DS parms
this.preferredIdP = null; // Array of entityIds to always show
this.hiddenIdPs = null; // Array of entityIds to delete
this.ignoreKeywords = false; // Do we ignore the <mdui:Keywords/> when looking for candidates
this.showListFirst = false; // Do we start with a list of IdPs or just the dropdown
this.samlIdPCookieTTL = 730; // in days
this.setFocusTextBox = true; // Set to false to supress focus
this.testGUI = false;
this.autoFollowCookie = null; // If you want auto-dispatch, set this to the cookie name to use
this.autoFollowCookieTTLs = [ 1, 60, 270 ]; // Cookie life (in days). Changing this requires changes to idp_select_languages
//
// Language support.
//
// The minified source provides "en", "de", "pt-br" and "jp".
//
// Override any of these below, or provide your own language
//
//this.langBundles = {
//'en': {
// 'fatal.divMissing': '<div> specified as "insertAtDiv" could not be located in the HTML',
// 'fatal.noXMLHttpRequest': 'Browser does not support XMLHttpRequest, unable to load IdP selection data',
// 'fatal.wrongProtocol' : 'Policy supplied to DS was not "urn:oasis:names:tc:SAML:profiles:SSO:idpdiscovery-protocol:single"',
// 'fatal.wrongEntityId' : 'entityId supplied by SP did not match configuration',
// 'fatal.noData' : 'Metadata download returned no data',
// 'fatal.loadFailed': 'Failed to download metadata from ',
// 'fatal.noparms' : 'No parameters to discovery session and no defaultReturn parameter configured',
// 'fatal.noReturnURL' : "No URL return parameter provided",
// 'fatal.badProtocol' : "Return request must start with https:// or http://",
// 'idpPreferred.label': 'Use a suggested selection:',
// 'idpEntry.label': 'Or enter your organization\'s name',
// 'idpEntry.NoPreferred.label': 'Enter your organization\'s name',
// 'idpList.label': 'Or select your organization from the list below',
// 'idpList.NoPreferred.label': 'Select your organization from the list below',
// 'idpList.defaultOptionLabel': 'Please select your organization...',
// 'idpList.showList' : 'Allow me to pick from a list',
// 'idpList.showSearch' : 'Allow me to specify the site',
// 'submitButton.label': 'Continue',
// 'helpText': 'Help',
// 'defaultLogoAlt' : 'DefaultLogo'
//}
//};
//
// The following should not be changed without changes to the css. Consider them as mandatory defaults
//
this.maxPreferredIdPs = 3;
this.maxIdPCharsButton = 33;
this.maxIdPCharsDropDown = 58;
this.maxIdPCharsAltTxt = 60;
this.minWidth = 20;
this.minHeight = 20;
this.maxWidth = 115;
this.maxHeight = 69;
this.bestRatio = Math.log(80 / 60);
}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
<title>IDP select test bed</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-5" />
<link rel="stylesheet" type="text/css" href="idpselect.css" />
</head>
<body>
<div id="idpSelect"></div>
<script src="idpselect_config.js" type="text/javascript" language="javascript"></script>
<script src="idpselect.js" type="text/javascript" language="javascript"></script>
<noscript>
<!-- If you need to care about non javascript browsers you will need to
generate a hyperlink to a non-js DS.
To build you will need:
- URL: The base URL of the DS you use
- EI: Your entityId, URLencoded. You can get this from the line that
this page is called with.
- RET: Your return address dlib-adidp.ucs.ed.ac.uk. Again you can get
this from the page this is called with, but beware of the
target%3Dcookie%253A5269905f bit..
< href=${URL}?entityID=${EI}&return=${RET}
-->
Your Browser does not support javascript. Please use
<a href="http://federation.org/DS/DS?entityID=https%3A%2F%2FyourentityId.edu.edu%2Fshibboleth&return=https%3A%2F%2Fyourreturn.edu%2FShibboleth.sso%2FDS%3FSAMLDS%3D1%26target%3Dhttps%3A%2F%2Fyourreturn.edu%2F">this link</a>.
</noscript>
</body>
</html>
This diff is collapsed.
/** @class IdP Selector UI */
function IdPSelectUIParms(){
//
// Adjust the following to fit into your local configuration
//
this.alwaysShow = true; // If true, this will show results as soon as you start typing
this.dataSource = '/Shibboleth.sso/DiscoFeed'; // Where to get the data from
this.defaultLanguage = 'en'; // Language to use if the browser local doesnt have a bundle
this.defaultLogo = 'blank.gif'; // Replace with your own logo
this.defaultLogoWidth = 1;
this.defaultLogoHeight = 1 ;
this.defaultReturn = null; // If non null, then the default place to send users who are not
// Approaching via the Discovery Protocol for example
//this.defaultReturn = "https://example.org/Shibboleth.sso/DS?SAMLDS=1&target=https://example.org/secure";
this.defaultReturnIDParam = null;
this.returnWhiteList = [ "^https:\/\/example\.org\/Shibboleth\.sso\/Login.*$" , "^https:\/\/example\.com\/Shibboleth\.sso\/Login.*$" ];
this.helpURL = 'https://wiki.shibboleth.net/confluence/display/SHIB2/DSRoadmap';
this.ie6Hack = null; // An array of structures to disable when drawing the pull down (needed to
// handle the ie6 z axis problem
this.insertAtDiv = 'idpSelect'; // The div where we will insert the data
this.maxResults = 10; // How many results to show at once or the number at which to
// start showing if alwaysShow is false
this.myEntityID = null; // If non null then this string must match the string provided in the DS parms
this.preferredIdP = null; // Array of entityIds to always show
this.hiddenIdPs = null; // Array of entityIds to delete
this.ignoreKeywords = false; // Do we ignore the <mdui:Keywords/> when looking for candidates
this.showListFirst = false; // Do we start with a list of IdPs or just the dropdown
this.samlIdPCookieTTL = 730; // in days
this.setFocusTextBox = true; // Set to false to supress focus
this.testGUI = false;
this.autoFollowCookie = null; // If you want auto-dispatch, set this to the cookie name to use
this.autoFollowCookieTTLs = [ 1, 60, 270 ]; // Cookie life (in days). Changing this requires changes to idp_select_languages
//
// Language support.
//
// The minified source provides "en", "de", "pt-br" and "jp".
//
// Override any of these below, or provide your own language
//
//this.langBundles = {
//'en': {
// 'fatal.divMissing': '<div> specified as "insertAtDiv" could not be located in the HTML',
// 'fatal.noXMLHttpRequest': 'Browser does not support XMLHttpRequest, unable to load IdP selection data',
// 'fatal.wrongProtocol' : 'Policy supplied to DS was not "urn:oasis:names:tc:SAML:profiles:SSO:idpdiscovery-protocol:single"',
// 'fatal.wrongEntityId' : 'entityId supplied by SP did not match configuration',
// 'fatal.noData' : 'Metadata download returned no data',
// 'fatal.loadFailed': 'Failed to download metadata from ',
// 'fatal.noparms' : 'No parameters to discovery session and no defaultReturn parameter configured',
// 'fatal.noReturnURL' : "No URL return parameter provided",
// 'fatal.badProtocol' : "Return request must start with https:// or http://",
// 'idpPreferred.label': 'Use a suggested selection:',
// 'idpEntry.label': 'Or enter your organization\'s name',
// 'idpEntry.NoPreferred.label': 'Enter your organization\'s name',
// 'idpList.label': 'Or select your organization from the list below',
// 'idpList.NoPreferred.label': 'Select your organization from the list below',
// 'idpList.defaultOptionLabel': 'Please select your organization...',
// 'idpList.showList' : 'Allow me to pick from a list',
// 'idpList.showSearch' : 'Allow me to specify the site',
// 'submitButton.label': 'Continue',
// 'helpText': 'Help',
// 'defaultLogoAlt' : 'DefaultLogo'
//}
//};
//
// The following should not be changed without changes to the css. Consider them as mandatory defaults
//
this.maxPreferredIdPs = 3;
this.maxIdPCharsButton = 33;
this.maxIdPCharsDropDown = 58;
this.maxIdPCharsAltTxt = 60;
this.minWidth = 20;
this.minHeight = 20;
this.maxWidth = 115;
this.maxHeight = 69;
this.bestRatio = Math.log(80 / 60);
}
/** @class IdP Selector UI */
function IdPSelectLanguages(){
//
// Globalization stuff
//
this.langBundles = {
'en': {
'fatal.divMissing': '<div> specified as "insertAtDiv" could not be located in the HTML',
'fatal.noXMLHttpRequest': 'Browser does not support XMLHttpRequest, unable to load IdP selection data',
'fatal.wrongProtocol' : 'Policy supplied to DS was not "urn:oasis:names:tc:SAML:profiles:SSO:idpdiscovery-protocol:single"',
'fatal.wrongEntityId' : 'entityId supplied by SP did not match configuration',
'fatal.noData' : 'Metadata download returned no data',
'fatal.loadFailed': 'Failed to download metadata from ',
'fatal.noparms' : 'No parameters to discovery session and no defaultReturn parameter configured',
'fatal.noReturnURL' : "No URL return parameter provided",
'fatal.badProtocol' : "Return parameter must start with https:// or http://",
'fatal.badReturnString' : "Return parameter is not whitelisted",
'idpPreferred.label': 'Use a suggested selection:',
'idpEntry.label': 'Or enter your organization\'s name',
'idpEntry.NoPreferred.label': 'Enter your organization\'s name',
'idpList.label': 'Or select your organization from the list below',
'idpList.NoPreferred.label': 'Select your organization from the list below',
'idpList.defaultOptionLabel': 'Please select your organization...',
'idpList.showList' : 'Allow me to pick from a list',
'idpList.showSearch' : 'Allow me to specify the site',
'submitButton.label': 'Continue',
'helpText': 'Help',
'defaultLogoAlt' : 'DefaultLogo',
'autoFollow.message' : 'Always follows this selection',
'autoFollow.never' : 'Never',
'autoFollow.time0' : 'One day',
'autoFollow.time1' : '3 months',
'autoFollow.time2' : '9 months'
},
'de': {
'fatal.divMissing': 'Das notwendige Div Element fehlt',
'fatal.noXMLHttpRequest': 'Ihr Webbrowser unterst\u00fctzt keine XMLHttpRequests, IdP-Auswahl kann nicht geladen werden',
'fatal.wrongProtocol' : 'DS bekam eine andere Policy als "urn:oasis:names:tc:SAML:profiles:SSO:idpdiscovery-protocol:single"',
'fatal.wrongEntityId' : 'Die entityId ist nicht korrekt',
'fatal.noData' : 'Heruntergeladene Metadata waren leer',
'fatal.loadFailed': 'Metadaten konnten nicht heruntergeladen werden: ',
'fatal.noparms' : 'Parameter f\u00fcr das Discovery Service oder \'defaultReturn\' fehlen',
'fatal.noReturnURL' : "URL return Parmeter fehlt",
'fatal.badProtocol' : "return Request muss mit https:// oder http:// beginnen",
'fatal.badReturnString' : "Return Parameter ist nicht auf Positivliste enthalten",
'idpPreferred.label': 'Vorherige Auswahl:',
'idpEntry.label': 'Oder geben Sie den Namen (oder Teile davon) an:',
'idpEntry.NoPreferred.label': 'Namen (oder Teile davon) der Institution angeben:',
'idpList.label': 'Oder w\u00e4hlen Sie Ihre Institution aus einer Liste:',
'idpList.NoPreferred.label': 'Institution aus folgender Liste w\u00e4hlen:',
'idpList.defaultOptionLabel': 'W\u00e4hlen Sie Ihre Institution aus...',
'idpList.showList' : 'Institution aus einer Liste w\u00e4hlen',
'idpList.showSearch' : 'Institution selbst angeben',
'submitButton.label': 'OK',
'helpText': 'Hilfe',
'defaultLogoAlt' : 'Standard logo',
'autoFollow.message' : 'Auswahl merken und diesen Dialog nicht mehr anzeigen',
'autoFollow.never' : 'Nicht merken',
'autoFollow.time0' : 'Nur f\u00fcr Heute',
'autoFollow.time1' : 'Drei Monate lang',
'autoFollow.time2' : 'Neun Monate lang'
},
'ja': {
'fatal.divMissing': '"insertAtDiv" の ID を持つ <div> が HTML 中に存在しません',
'fatal.noXMLHttpRequest': 'ブラウザが XMLHttpRequest をサポートしていないので IdP 情報を取得できません',
'fatal.wrongProtocol' : 'DSへ渡された Policy パラメータが "urn:oasis:names:tc:SAML:profiles:SSO:idpdiscovery-protocol:single" ではありません',
'fatal.wrongEntityId' : 'SP から渡された entityId が設定値と異なります',
'fatal.noData' : 'メタデータが空です',
'fatal.loadFailed': '次の URL からメタデータをダウンロードできませんでした: ',
'fatal.noparms' : 'DSにパラメータが渡されておらず defaultReturn も設定されていません',
'fatal.noReturnURL' : "戻り URL が指定されていません",
'fatal.badProtocol' : "戻り URL は https:// か http:// で始まらなければなりません",
'idpPreferred.label': '選択候補の IdP:',
'idpEntry.label': 'もしくはあなたの所属機関名を入力してください',
'idpEntry.NoPreferred.label': 'あなたの所属機関名を入力してください',
'idpList.label': 'もしくはあなたの所属機関を選択してください',
'idpList.NoPreferred.label': 'あなたの所属機関を一覧から選択してください',
'idpList.defaultOptionLabel': '所属機関を選択してください...',
'idpList.showList' : '一覧から選択する',
'idpList.showSearch' : '機関名を入力する',
'submitButton.label': '選択',
'autoFollow.message' : '次の期間選択した機関に自動的に遷移する:',
'autoFollow.never' : '自動遷移しない',
'autoFollow.time0' : '1日',
'autoFollow.time1' : '3か月',
'autoFollow.time2' : '9か月',
'fatal.badReturnString' : "戻り URL が不正です",
'helpText': 'ヘルプ',
'defaultLogoAlt' : 'ロゴ未設定'
},
'pt-br': {
'fatal.divMissing': 'A tag <div> com "insertAtDiv" não foi encontrada no arquivo HTML',
'fatal.noXMLHttpRequest': 'Seu navegador não suporta "XMLHttpRequest", impossível de carregador os dados do IdP selecionado',
'fatal.wrongProtocol' : 'A política "Policy" fornecida para o DS não foi "urn:oasis:names:tc:SAML:profiles:SSO:idpdiscovery-protocol:single"',
'fatal.wrongEntityId' : 'entityId oferecido pelo SP não confere com o da configuração',
'fatal.noData' : 'O arquivo de metadados não retornou nada;',
'fatal.loadFailed': 'Falhou ao realizar download do metadado de ',
'fatal.noparms' : 'Sem parâmetros para sessão de descoberta e sem parâmetro "defaultReturn" configurado',
'fatal.noReturnURL' : "Não foi definida um endereço (URL) de retorno no parâmetro",
'fatal.badProtocol' : "Retorno do endereço requisitado deve começar com https:// ou http://",
'idpPreferred.label': 'Use estas Instituições sugeridas: ',
'idpEntry.label': 'Ou informe o nome da sua Instituição',
'idpEntry.NoPreferred.label': 'Informe o nome da sua Instituição',
'idpList.label': 'Ou selecione sua Instituição através da lista abaixo',
'idpList.NoPreferred.label': 'Selecione sua Instituição através da lista abaixo',
'idpList.defaultOptionLabel': 'Por favor, selecione sua Instituição: ',
'idpList.showList' : 'Permitir que eu escolha um IdP através de uma lista',
'idpList.showSearch' : 'Permitir que eu especifique o IdP',
'submitButton.label': 'Continuar ',
'helpText': 'Ajuda',
'defaultLogoAlt' : 'Logo padrão'
}
};
}
/*
http://www.JSON.org/json2.js
2011-02-23
Public Domain.
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
See http://www.JSON.org/js.html
This code should be minified before deployment.
See http://javascript.crockford.com/jsmin.html
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
NOT CONTROL.
This file creates a global JSON object containing two methods: stringify
and parse.
JSON.stringify(value, replacer, space)
value any JavaScript value, usually an object or array.
replacer an optional parameter that determines how object
values are stringified for objects. It can be a
function or an array of strings.
space an optional parameter that specifies the indentation
of nested structures. If it is omitted, the text will
be packed without extra whitespace. If it is a number,
it will specify the number of spaces to indent at each
level. If it is a string (such as '\t' or '&nbsp;'),
it contains the characters used to indent at each level.
This method produces a JSON text from a JavaScript value.
When an object value is found, if the object contains a toJSON
method, its toJSON method will be called and the result will be
stringified. A toJSON method does not serialize: it returns the
value represented by the name/value pair that should be serialized,
or undefined if nothing should be serialized. The toJSON method
will be passed the key associated with the value, and this will be
bound to the value
For example, this would serialize Dates as ISO strings.
Date.prototype.toJSON = function (key) {
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
}
return this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z';
};
You can provide an optional replacer method. It will be passed the
key and value of each member, with this bound to the containing
object. The value that is returned from your method will be
serialized. If your method returns undefined, then the member will
be excluded from the serialization.
If the replacer parameter is an array of strings, then it will be
used to select the members to be serialized. It filters the results
such that only members with keys listed in the replacer array are
stringified.
Values that do not have JSON representations, such as undefined or
functions, will not be serialized. Such values in objects will be
dropped; in arrays they will be replaced with null. You can use
a replacer function to replace those with JSON values.
JSON.stringify(undefined) returns undefined.
The optional space parameter produces a stringification of the
value that is filled with line breaks and indentation to make it
easier to read.
If the space parameter is a non-empty string, then that string will
be used for indentation. If the space parameter is a number, then
the indentation will be that many spaces.
Example:
text = JSON.stringify(['e', {pluribus: 'unum'}]);
// text is '["e",{"pluribus":"unum"}]'
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
text = JSON.stringify([new Date()], function (key, value) {
return this[key] instanceof Date ?
'Date(' + this[key] + ')' : value;
});
// text is '["Date(---current time---)"]'
JSON.parse(text, reviver)
This method parses a JSON text to produce an object or array.
It can throw a SyntaxError exception.
The optional reviver parameter is a function that can filter and
transform the results. It receives each of the keys and values,
and its return value is used instead of the original value.
If it returns what it received, then the structure is not modified.
If it returns undefined then the member is deleted.
Example:
// Parse the text. Values that look like ISO date strings will
// be converted to Date objects.
myData = JSON.parse(text, function (key, value) {
var a;
if (typeof value === 'string') {
a =
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
if (a) {
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
+a[5], +a[6]));
}
}
return value;
});
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
var d;
if (typeof value === 'string' &&
value.slice(0, 5) === 'Date(' &&
value.slice(-1) === ')') {
d = new Date(value.slice(5, -1));
if (d) {
return d;
}
}
return value;
});
This is a reference implementation. You are free to copy, modify, or
redistribute.
*/
/*jslint evil: true, strict: false, regexp: false */
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
lastIndex, length, parse, prototype, push, replace, slice, stringify,
test, toJSON, toString, valueOf
*/
// Create a JSON object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.
var JSON;
if (!JSON) {
JSON = {};
}
(function () {
"use strict";
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
}
if (typeof Date.prototype.toJSON !== 'function') {
Date.prototype.toJSON = function (key) {
return isFinite(this.valueOf()) ?
this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z' : null;
};
String.prototype.toJSON =
Number.prototype.toJSON =
Boolean.prototype.toJSON = function (key) {
return this.valueOf();
};
}
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
gap,
indent,
meta = { // table of character substitutions
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'\\': '\\\\'
},
rep;
function quote(string) {
// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.
escapable.lastIndex = 0;
return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
var c = meta[a];
return typeof c === 'string' ? c :
'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
}) + '"' : '"' + string + '"';
}
function str(key, holder) {
// Produce a string from holder[key].
var i, // The loop counter.
k, // The member key.
v, // The member value.
length,
mind = gap,
partial,
value = holder[key];
// If the value has a toJSON method, call it to obtain a replacement value.
if (value && typeof value === 'object' &&
typeof value.toJSON === 'function') {
value = value.toJSON(key);
}
// If we were called with a replacer function, then call the replacer to
// obtain a replacement value.
if (typeof rep === 'function') {
value = rep.call(holder, key, value);
}
// What happens next depends on the value's type.
switch (typeof value) {
case 'string':
return quote(value);
case 'number':
// JSON numbers must be finite. Encode non-finite numbers as null.
return isFinite(value) ? String(value) : 'null';
case 'boolean':
case 'null':
// If the value is a boolean or null, convert it to a string. Note:
// typeof null does not produce 'null'. The case is included here in
// the remote chance that this gets fixed someday.
return String(value);
// If the type is 'object', we might be dealing with an object or an array or
// null.
case 'object':
// Due to a specification blunder in ECMAScript, typeof null is 'object',
// so watch out for that case.
if (!value) {
return 'null';
}
// Make an array to hold the partial results of stringifying this object value.
gap += indent;
partial = [];
// Is the value an array?
if (Object.prototype.toString.apply(value) === '[object Array]') {
// The value is an array. Stringify every element. Use null as a placeholder
// for non-JSON values.
length = value.length;
for (i = 0; i < length; i += 1) {
partial[i] = str(i, value) || 'null';
}
// Join all of the elements together, separated with commas, and wrap them in
// brackets.
v = partial.length === 0 ? '[]' : gap ?
'[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
'[' + partial.join(',') + ']';
gap = mind;
return v;
}
// If the replacer is an array, use it to select the members to be stringified.
if (rep && typeof rep === 'object') {
length = rep.length;
for (i = 0; i < length; i += 1) {
if (typeof rep[i] === 'string') {
k = rep[i];
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
} else {
// Otherwise, iterate through all of the keys in the object.
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
}
// Join all of the member texts together, separated with commas,
// and wrap them in braces.
v = partial.length === 0 ? '{}' : gap ?
'{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
'{' + partial.join(',') + '}';
gap = mind;
return v;
}
}
// If the JSON object does not yet have a stringify method, give it one.
if (typeof JSON.stringify !== 'function') {
JSON.stringify = function (value, replacer, space) {
// The stringify method takes a value and an optional replacer, and an optional
// space parameter, and returns a JSON text. The replacer can be a function
// that can replace values, or an array of strings that will select the keys.
// A default replacer method can be provided. Use of the space parameter can
// produce text that is more easily readable.
var i;
gap = '';
indent = '';
// If the space parameter is a number, make an indent string containing that
// many spaces.
if (typeof space === 'number') {
for (i = 0; i < space; i += 1) {
indent += ' ';
}
// If the space parameter is a string, it will be used as the indent string.
} else if (typeof space === 'string') {
indent = space;
}
// If there is a replacer, it must be a function or an array.
// Otherwise, throw an error.
rep = replacer;
if (replacer && typeof replacer !== 'function' &&
(typeof replacer !== 'object' ||
typeof replacer.length !== 'number')) {
throw new Error('JSON.stringify');
}
// Make a fake root object containing our value under the key of ''.
// Return the result of stringifying the value.
return str('', {'': value});
};
}
// If the JSON object does not yet have a parse method, give it one.
if (typeof JSON.parse !== 'function') {
JSON.parse = function (text, reviver) {
// The parse method takes a text and an optional reviver function, and returns
// a JavaScript value if the text is a valid JSON text.
var j;
function walk(holder, key) {
// The walk method is used to recursively walk the resulting structure so
// that modifications can be made.
var k, v, value = holder[key];
if (value && typeof value === 'object') {
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = walk(value, k);
if (v !== undefined) {
value[k] = v;
} else {
delete value[k];
}
}
}
}
return reviver.call(holder, key, value);
}
// Parsing happens in four stages. In the first stage, we replace certain
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.
text = String(text);
cx.lastIndex = 0;
if (cx.test(text)) {
text = text.replace(cx, function (a) {
return '\\u' +
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
});
}
// In the second stage, we run the text against regular expressions that look
// for non-JSON patterns. We are especially concerned with '()' and 'new'
// because they can cause invocation, and '=' because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.
// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
// replace all simple value tokens with ']' characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
if (/^[\],:{}\s]*$/
.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.
j = eval('(' + text + ')');
// In the optional fourth stage, we recursively walk the new structure, passing
// each name/value pair to a reviver function for possible transformation.
return typeof reviver === 'function' ?
walk({'': j}, '') : j;
}
// If the text is not JSON parseable, then a SyntaxError is thrown.
throw new SyntaxError('JSON.parse');
};
}
}());
function TypeAheadControl(jsonObj, box, orig, submit, maxchars, getName, getEntityId, geticon, ie6hack, alwaysShow, maxResults, getKeywords)
{
//
// Squirrel away the parameters we were given
//
this.elementList = jsonObj;
this.textBox = box;
this.origin = orig;
this.submit = submit;
this.results = 0;
this.alwaysShow = alwaysShow;
this.maxResults = maxResults;
this.ie6hack = ie6hack;
this.maxchars = maxchars;
this.getName = getName;
this.getEntityId = getEntityId;
this.geticon = geticon;
this.getKeywords = getKeywords;
}
TypeAheadControl.prototype.draw = function(setFocus) {
//
// Make a closure on this so that the embedded functions
// get access to it.
//
var myThis = this;
//
// Set up the 'dropDown'
//
this.dropDown = document.createElement('ul');
this.dropDown.className = 'IdPSelectDropDown';
this.dropDown.style.visibility = 'hidden';
this.dropDown.style.width = this.textBox.offsetWidth;
this.dropDown.current = -1;
this.textBox.setAttribute('role', 'listbox');
document.body.appendChild(this.dropDown);
//
// Set ARIA on the input
//
this.textBox.setAttribute('role', 'combobox');
this.textBox.setAttribute('aria-controls', 'IdPSelectDropDown');
this.textBox.setAttribute('aria-owns', 'IdPSelectDropDown');
//
// mouse listeners for the dropdown box
//
this.dropDown.onmouseover = function(event) {
if (!event) {
event = window.event;
}
var target;
if (event.target){
target = event.target;
}
if (typeof target == 'undefined') {
target = event.srcElement;
}
myThis.select(target);
};
this.dropDown.onmousedown = function(event) {
if (-1 != myThis.dropDown.current) {
myThis.textBox.value = myThis.results[myThis.dropDown.current][0];
}
};
//
// Add the listeners to the text box
//
this.textBox.onkeyup = function(event) {
//
// get window event if needed (because of browser oddities)
//
if (!event) {
event = window.event;
}
myThis.handleKeyUp(event);
};
this.textBox.onkeydown = function(event) {
if (!event) {
event = window.event;
}
myThis.handleKeyDown(event);
};
this.textBox.onblur = function() {
myThis.hideDrop();
};
this.textBox.onfocus = function() {
myThis.handleChange();
};
if (null == setFocus || setFocus) {
this.textBox.focus();
}
};
//
// Given a name return the first maxresults, or all possibles
//
TypeAheadControl.prototype.getPossible = function(name) {
var possibles = [];
var inIndex = 0;
var outIndex = 0;
var strIndex = 0;
var str;
var ostr;
name = name.toLowerCase();
while (outIndex <= this.maxResults && inIndex < this.elementList.length) {
var hit = false;
var thisName = this.getName(this.elementList[inIndex]);
//
// Check name
//
if (thisName.toLowerCase().indexOf(name) != -1) {
hit = true;
}
//
// Check entityID
//
if (!hit && this.getEntityId(this.elementList[inIndex]).toLowerCase().indexOf(name) != -1) {
hit = true;
}
if (!hit) {
var thisKeywords = this.getKeywords(this.elementList[inIndex]);
if (null != thisKeywords &&
thisKeywords.toLowerCase().indexOf(name) != -1) {
hit = true;
}
}
if (hit) {
possibles[outIndex] = [thisName, this.getEntityId(this.elementList[inIndex]), this.geticon(this.elementList[inIndex])];
outIndex ++;
}
inIndex ++;
}
//
// reset the cursor to the top
//
this.dropDown.current = -1;
return possibles;
};
TypeAheadControl.prototype.handleKeyUp = function(event) {
var key = event.keyCode;
if (27 == key) {
//
// Escape - clear
//
this.textBox.value = '';
this.handleChange();
} else if (8 == key || 32 == key || (key >= 46 && key < 112) || key > 123) {
//
// Backspace, Space and >=Del to <F1 and > F12
//
this.handleChange();
}
};
TypeAheadControl.prototype.handleKeyDown = function(event) {
var key = event.keyCode;
if (38 == key) {
//
// up arrow
//
this.upSelect();
} else if (40 == key) {
//
// down arrow
//
this.downSelect();
}
};
TypeAheadControl.prototype.hideDrop = function() {
var i = 0;
if (null !== this.ie6hack) {
while (i < this.ie6hack.length) {
this.ie6hack[i].style.visibility = 'visible';
i++;
}
}
this.dropDown.style.visibility = 'hidden';
this.textBox.setAttribute('aria-expanded', 'false');
if (-1 == this.dropDown.current) {
this.doUnselected();
}
};
TypeAheadControl.prototype.showDrop = function() {
var i = 0;
if (null !== this.ie6hack) {
while (i < this.ie6hack.length) {
this.ie6hack[i].style.visibility = 'hidden';
i++;
}
}
this.dropDown.style.visibility = 'visible';
this.dropDown.style.width = this.textBox.offsetWidth +"px";
this.textBox.setAttribute('aria-expanded', 'true');
};
TypeAheadControl.prototype.doSelected = function() {
this.submit.disabled = false;
};
TypeAheadControl.prototype.doUnselected = function() {
this.submit.disabled = true;
this.textBox.setAttribute('aria-activedescendant', '');
};
TypeAheadControl.prototype.handleChange = function() {
var val = this.textBox.value;
var res = this.getPossible(val);
if (0 === val.length ||
0 === res.length ||
(!this.alwaysShow && this.maxResults < res.length)) {
this.hideDrop();
this.doUnselected();
this.results = [];
this.dropDown.current = -1;
} else {
this.results = res;
this.populateDropDown(res);
if (1 == res.length) {
this.select(this.dropDown.childNodes[0]);
this.doSelected();
} else {
this.doUnselected();
}
}
};
//
// A lot of the stuff below comes from
// http://www.webreference.com/programming/javascript/ncz/column2
//
// With thanks to Nicholas C Zakas
//
TypeAheadControl.prototype.populateDropDown = function(list) {
this.dropDown.innerHTML = '';
var i = 0;
var li;
var img;
var str;
while (i < list.length) {
li = document.createElement('li');
li.id='IdPSelectOption' + i;
str = list[i][0];
if (null !== list[i][2]) {
img = document.createElement('img');
img.src = list[i][2];
img.width = 16;
img.height = 16;
img.alt = '';
li.appendChild(img);
//
// trim string back further in this case
//
if (str.length > this.maxchars - 2) {
str = str.substring(0, this.maxchars - 2);
}
str = ' ' + str;
} else {
if (str.length > this.maxchars) {
str = str.substring(0, this.maxchars);
}
}
li.appendChild(document.createTextNode(str));
li.setAttribute('role', 'option');
this.dropDown.appendChild(li);
i++;
}
var off = this.getXY();
this.dropDown.style.left = off[0] + 'px';
this.dropDown.style.top = off[1] + 'px';
this.showDrop();
};
TypeAheadControl.prototype.getXY = function() {
var node = this.textBox;
var sumX = 0;
var sumY = node.offsetHeight;
while(node.tagName != 'BODY') {
sumX += node.offsetLeft;
sumY += node.offsetTop;
node = node.offsetParent;
}
//
// And add in the offset for the Body
//
sumX += node.offsetLeft;
sumY += node.offsetTop;
return [sumX, sumY];
};
TypeAheadControl.prototype.select = function(selected) {
var i = 0;
var node;
this.dropDown.current = -1;
this.doUnselected();
while (i < this.dropDown.childNodes.length) {
node = this.dropDown.childNodes[i];
if (node == selected) {
//
// Highlight it
//
node.className = 'IdPSelectCurrent';
node.setAttribute('aria-selected', 'true');
this.textBox.setAttribute('aria-activedescendant', 'IdPSelectOption' + i);
//
// turn on the button
//
this.doSelected();
//
// setup the cursor
//
this.dropDown.current = i;
//
// and the value for the Server
//
this.origin.value = this.results[i][1];
this.origin.textValue = this.results[i][0];
} else {
node.setAttribute('aria-selected', 'false');
node.className = '';
}
i++;
}
this.textBox.focus();
};
TypeAheadControl.prototype.downSelect = function() {
if (this.results.length > 0) {
if (-1 == this.dropDown.current) {
//
// mimic a select()
//
this.dropDown.current = 0;
this.dropDown.childNodes[0].className = 'IdPSelectCurrent';
this.dropDown.childNodes[0].setAttribute('aria-selected', 'true');
this.textBox.setAttribute('aria-activedescendant', 'IdPSelectOption' + 0);
this.doSelected();
this.origin.value = this.results[0][1];
this.origin.textValue = this.results[0][0];
} else if (this.dropDown.current < (this.results.length-1)) {
//
// turn off highlight
//
this.dropDown.childNodes[this.dropDown.current].className = '';
//
// move cursor
//
this.dropDown.current++;
//
// and 'select'
//
this.dropDown.childNodes[this.dropDown.current].className = 'IdPSelectCurrent';
this.dropDown.childNodes[this.dropDown.current].setAttribute('aria-selected', 'true');
this.textBox.setAttribute('aria-activedescendant', 'IdPSelectOption' + this.dropDown.current);
this.doSelected();
this.origin.value = this.results[this.dropDown.current][1];
this.origin.textValue = this.results[this.dropDown.current][0];
}
}
};
TypeAheadControl.prototype.upSelect = function() {
if ((this.results.length > 0) &&
(this.dropDown.current > 0)) {
//
// turn off highlight
//
this.dropDown.childNodes[this.dropDown.current].className = '';
//
// move cursor
//
this.dropDown.current--;
//
// and 'select'
//
this.dropDown.childNodes[this.dropDown.current].className = 'IdPSelectCurrent';
this.dropDown.childNodes[this.dropDown.current].setAttribute('aria-selected', 'true');
this.textBox.setAttribute('aria-activedescendant', 'IdPSelectOption' + this.dropDown.current);
this.doSelected();
this.origin.value = this.results[this.dropDown.current][1];
this.origin.textValue = this.results[this.dropDown.current][0];
}
};
#! /bin/sh
while getopts n:h:u:g:o:e:y:bf c
do
case $c in
u) USER=$OPTARG;;
g) GROUP=$OPTARG;;
o) OUT=$OPTARG;;
b) BATCH=1;;
f) FORCE=1;;
h) FQDN=$OPTARG;;
e) ENTITYID=$OPTARG;;
y) YEARS=$OPTARG;;
n) PREFIX=$OPTARG;;
\?) echo "keygen [-o output directory (default .)] [-u username to own keypair] [-g owning groupname] [-h hostname for cert] [-y years to issue cert] [-e entityID to embed in cert] [-n filename prefix (default 'sp')]"
exit 1;;
esac
done
if [ -z "$OUT" ] ; then
OUT=.
fi
if [ -z "$PREFIX" ]; then
PREFIX="sp"
fi
if [ -n "$FORCE" ] ; then
rm $OUT/${PREFIX}-key.pem $OUT/${PREFIX}-cert.pem
fi
if [ -s $OUT/${PREFIX}-key.pem -o -s $OUT/${PREFIX}-cert.pem ] ; then
if [ -z "$BATCH" ] ; then
echo The files $OUT/${PREFIX}-key.pem and/or $OUT/${PREFIX}-cert.pem already exist!
echo Use -f option to force recreation of keypair.
exit 2
fi
exit 0
fi
if [ -z "$FQDN" ] ; then
FQDN=`hostname`
fi
if [ -z "$YEARS" ] ; then
YEARS=10
fi
DAYS=`expr $YEARS \* 365`
if [ -z "$ENTITYID" ] ; then
ALTNAME=DNS:$FQDN
else
ALTNAME=DNS:$FQDN,URI:$ENTITYID
fi
SSLCNF=$OUT/${PREFIX}-cert.cnf
cat >$SSLCNF <<EOF
# OpenSSL configuration file for creating keypair
[req]
prompt=no
default_bits=3072
encrypt_key=no
default_md=sha256
distinguished_name=dn
# PrintableStrings only
string_mask=MASK:0002
x509_extensions=ext
[dn]
CN=$FQDN
[ext]
subjectAltName=$ALTNAME
subjectKeyIdentifier=hash
EOF
touch $OUT/${PREFIX}-key.pem
chmod 600 $OUT/${PREFIX}-key.pem
if [ -z "$BATCH" ] ; then
openssl req -config $SSLCNF -new -x509 -days $DAYS -keyout $OUT/${PREFIX}-key.pem -out $OUT/${PREFIX}-cert.pem
else
openssl req -config $SSLCNF -new -x509 -days $DAYS -keyout $OUT/${PREFIX}-key.pem -out $OUT/${PREFIX}-cert.pem 2> /dev/null
fi
rm $SSLCNF
if [ -s $OUT/${PREFIX}-key.pem -a -n "$USER" ] ; then
chown $USER $OUT/${PREFIX}-key.pem $OUT/${PREFIX}-cert.pem
fi
if [ -s $OUT/${PREFIX}-key.pem -a -n "$GROUP" ] ; then
chgrp $GROUP $OUT/${PREFIX}-key.pem $OUT/${PREFIX}-cert.pem
fi
...@@ -4,7 +4,8 @@ FAAS_REGISTRY_VERSION=1.0-SNAPSHOT ...@@ -4,7 +4,8 @@ FAAS_REGISTRY_VERSION=1.0-SNAPSHOT
FAAS_REGISTRY_PORT=9080 FAAS_REGISTRY_PORT=9080
FAAS_REGISTRY_BASE_URL=http://localhost:9080/rr3/ FAAS_REGISTRY_HOSTNAME=localhost
FAAS_REGISTRY_BASE_URL=http://localhost:9080
FAAS_REGISTRY_COOKIE_SECURE=FALSE FAAS_REGISTRY_COOKIE_SECURE=FALSE
FAAS_REGISTRY_TIMEZONE=Europe/Warsaw FAAS_REGISTRY_TIMEZONE=Europe/Warsaw
......
...@@ -48,4 +48,5 @@ services: ...@@ -48,4 +48,5 @@ services:
FAAS_REGISTRY_RR_SMTP_PORT: 25 FAAS_REGISTRY_RR_SMTP_PORT: 25
FAAS_REGISTRY_RR_MAIL_USER: ${FAAS_REGISTRY_RR_MAIL_USER} FAAS_REGISTRY_RR_MAIL_USER: ${FAAS_REGISTRY_RR_MAIL_USER}
FAAS_REGISTRY_RR_MAIL_PASS: ${FAAS_REGISTRY_RR_MAIL_PASS} FAAS_REGISTRY_RR_MAIL_PASS: ${FAAS_REGISTRY_RR_MAIL_PASS}
FAAS_REGISTRY_RR_MAIL_FROM: ${FAAS_REGISTRY_RR_MAIL_FROM} FAAS_REGISTRY_RR_MAIL_FROM: ${FAAS_REGISTRY_RR_MAIL_FROM}
\ No newline at end of file FAAS_REGISTRY_HOSTNAME: ${FAAS_REGISTRY_HOSTNAME}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment