plugins/Yubikey.php
author Dan
Sun, 01 Mar 2009 20:41:27 -0500
changeset 6 4f85ab095cc8
parent 5 2114640729a5
child 8 032ca892b9a2
permissions -rw-r--r--
Added visual feedback for key entry
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
     1
<?php
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
     2
/**!info**
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
     3
{
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
     4
  "Plugin Name"  : "Yubikey authentication",
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
     5
  "Plugin URI"   : "http://enanocms.org/plugin/yubikey",
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
     6
  "Description"  : "Allows authentication to Enano via Yubico's Yubikey, a one-time password device.",
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
     7
  "Author"       : "Dan Fuhry",
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
     8
  "Version"      : "1.1.6",
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
     9
  "Author URI"   : "http://enanocms.org/"
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    10
}
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    11
**!*/
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    12
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    13
// Include files
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    14
require( ENANO_ROOT . '/plugins/yubikey/corelib.php' );
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    15
require( ENANO_ROOT . '/plugins/yubikey/admincp.php' );
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    16
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    17
if ( getConfig('yubikey_enable', '1') == '1' )
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    18
{
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    19
  require( ENANO_ROOT . '/plugins/yubikey/auth.php' );
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    20
  require( ENANO_ROOT . '/plugins/yubikey/usercp.php' );
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    21
}
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    22
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    23
// Install schema: MySQL
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    24
/**!install dbms="mysql"; **
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    25
CREATE TABLE {{TABLE_PREFIX}}yubikey(
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    26
  yubi_id int(12) NOT NULL auto_increment,
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    27
  user_id mediumint(8) NOT NULL DEFAULT 1,
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    28
  yubi_uid char(12) NOT NULL DEFAULT '____________',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    29
  PRIMARY KEY ( yubi_id )
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    30
) ENGINE `MyISAM` CHARACTER SET `utf8` COLLATE `utf8_bin`;
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    31
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    32
ALTER TABLE {{TABLE_PREFIX}}users ADD COLUMN user_yubikey_flags smallint(3) NOT NULL DEFAULT 0;
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    33
**!*/
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    34
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    35
// Install schema: PostgreSQL
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    36
/**!install dbms="postgresql"; **
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    37
CREATE TABLE {{TABLE_PREFIX}}yubikey(
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    38
  yubi_id SERIAL,
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    39
  user_id int NOT NULL DEFAULT 1,
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    40
  yubi_uid char(12) NOT NULL DEFAULT '____________',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    41
  PRIMARY KEY ( yubi_id )
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    42
);
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    43
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    44
ALTER TABLE {{TABLE_PREFIX}}users ADD COLUMN user_yubikey_flags smallint NOT NULL DEFAULT 0;
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    45
**!*/
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    46
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    47
// Uninstall schema
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    48
/**!uninstall**
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    49
DROP TABLE {{TABLE_PREFIX}}yubikey;
1
86d41fd204a0 Typo! STOP -> DROP. See Spot run. Spot runs to the house. Spot licks Dick. Dick pets Spot.
Dan
parents: 0
diff changeset
    50
ALTER TABLE {{TABLE_PREFIX}}users DROP user_yubikey_flags;
0
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    51
**!*/
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    52
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    53
/**!language**
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    54
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    55
The following text up to the closing comment tag is JSON language data.
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    56
It is not PHP code but your editor or IDE may highlight it as such. This
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    57
data is imported when the plugin is loaded for the first time; it provides
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    58
the strings displayed by this plugin's interface.
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    59
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    60
You should copy and paste this block when you create your own plugins so
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    61
that these comments and the basic structure of the language data is
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    62
preserved. All language data is in the same format as the Enano core
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    63
language files in the /language/* directories. See the Enano Localization
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    64
Guide and Enano API Documentation for further information on the format of
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    65
language files.
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    66
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    67
The exception in plugin language file format is that multiple languages
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    68
may be specified in the language block. This should be done by way of making
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    69
the top-level elements each a JSON language object, with elements named
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    70
according to the ISO-639-1 language they are representing. The path should be:
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    71
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    72
  root => language ID => categories array, ( strings object => category \
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    73
  objects => strings )
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    74
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    75
All text leading up to first curly brace is stripped by the parser; using
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    76
a code tag makes jEdit and other editors do automatic indentation and
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    77
syntax highlighting on the language data. The use of the code tag is not
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    78
necessary; it is only included as a tool for development.
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    79
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    80
<code>
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    81
{
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    82
  // english
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    83
  eng: {
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    84
    categories: [ 'meta', 'yubiauth', 'yubiucp', 'yubiacp' ],
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    85
    strings: {
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    86
      meta: {
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    87
        yubiauth: 'Yubikey authentication messages',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    88
        yubiucp: 'Yubikey user CP',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    89
        yubiacp: 'Yubikey admin CP',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    90
      },
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    91
      yubiauth: {
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    92
        msg_please_touch_key: 'Please touch your Yubikey',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    93
        msg_close_instructions: 'Press <tt>Esc</tt> to cancel',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    94
        msg_invalid_chars: 'OTP contains invalid characters',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    95
        msg_validating_otp: 'Validating OTP...',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    96
        msg_otp_valid: 'OTP validated',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    97
        btn_enter_otp: 'Enter a Yubikey OTP',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    98
        lbl_otp_field: 'Yubikey OTP:',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
    99
        
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   100
        ctl_btn_change_key: 'Change key',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   101
        ctl_btn_clear: 'Clear',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   102
        ctl_btn_enroll: 'Enroll',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   103
        ctl_status_enrolled_pending: 'Enrolled (pending)',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   104
        ctl_status_empty: 'Not enrolled',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   105
        ctl_status_remove_pending: 'Removed (pending)',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   106
        ctl_status_enrolled: 'Enrolled',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   107
        
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   108
        err_invalid_otp: 'Your login was rejected because the Yubikey OTP you entered contains invalid characters.',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   109
        err_invalid_auth_url: 'Login with Yubikey was rejected because the URL to the authentication server is not valid.',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   110
        err_nothing_provided: 'You did not provide a Yubikey OTP or a username. One of these is required for login to work.',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   111
        err_must_have_otp: 'Please provide a Yubikey OTP to log in to this account.',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   112
        err_must_have_username: 'Please provide your username.',
5
2114640729a5 Auth: added string for pass required
Dan
parents: 1
diff changeset
   113
        err_must_have_password: 'Please enter your password in addition to your username and Yubikey.',
0
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   114
        err_key_not_authorized: 'This Yubikey is not authorized on this site.',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   115
        err_otp_invalid_chars: '%this.yubiauth_err_invalid_otp%',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   116
        err_missing_api_key: 'Your OTP could not be validated because no Yubico API key is registered on this site.',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   117
        err_http_response_error: 'Your OTP could not be validated because the Yubico authentication server reported an error.',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   118
        err_malformed_response: 'Your OTP could not be validated because the Yubico authentication server returned an unexpected response.',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   119
        err_response_missing_sig: 'Your OTP could not be validated because the Yubico authentication server did not sign its response.',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   120
        err_response_invalid_sig: 'Your OTP could not be validated because the signature of the authentication response was invalid.',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   121
        err_response_missing_status: '%this.yubiauth_err_malformed_response%',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   122
        err_response_ok: 'OTP is OK',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   123
        err_response_bad_otp: 'Authentication failed because the Yubikey OTP is invalid.',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   124
        err_response_replayed_otp: 'Authentication failed because the Yubikey OTP you entered has been used before.',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   125
        err_response_bad_signature: 'Authentication failed because the Yubico authentication server reported an invalid signature.',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   126
        err_response_missing_parameter: 'Authentication failed because of a Dan Fuhry error.',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   127
        err_response_no_such_client: 'Authentication failed because the Yubikey you used is not registered with Yubico.',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   128
        err_response_operation_not_allowed: 'Authentication failed because the Enano server was denied the request to validate the OTP.',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   129
        err_response_backend_error: 'Authentication failed because an unexpected problem happened with the Yubico server.',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   130
        err_response_security_error: 'Authentication failed because the Yubico authentication server reported an unknown security error.',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   131
        
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   132
        specialpage_yubikey: 'Yubikey API'
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   133
      },
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   134
      yubiucp: {
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   135
        panel_title: 'Yubikey settings',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   136
        
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   137
        field_enable_title: 'Enable Yubikey support on my account:',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   138
        field_enable_hint: 'Disabling support will remove any keys that are enrolled for your account.',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   139
        field_enable: 'Enabled',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   140
        field_keys_title: 'Enrolled Yubikeys:',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   141
        field_keys_hint: 'Enroll a Yubikey to allow it to log into your account.',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   142
        field_keys_maximum: 'You can enroll up to %max% Yubikeys.',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   143
        field_normal_flags: 'When logging in:',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   144
        field_elev_flags: 'When performing sensitive operations:',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   145
        field_flags_keyonly: 'Only require my Yubikey',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   146
        field_flags_username: 'Require a username',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   147
        field_flags_userandpw: 'Require a username and password',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   148
        field_allow_plain_login: 'Allow me to log in without my Yubikey',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   149
        field_allow_plain_login_hint: 'If this option is turned off, you will be unable to access your account if all of your enrolled Yubikeys become lost or broken. However, turning this option off provides greater security.',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   150
        err_double_enrollment: 'One of the Yubikeys you tried to enroll is already enrolled on another account on this website. A single Yubikey can only be associated with one account at a time.',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   151
      },
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   152
      yubiacp: {
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   153
        th: 'Yubikey authentication',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   154
        field_enable_title: 'Yubikey support:',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   155
        field_enable: 'Enable Yubikey authentication',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   156
        field_api_key: 'Yubico API key:',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   157
        field_api_key_id: 'Yubico numeric ID:',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   158
        field_auth_server: 'Authentication server URL:',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   159
        field_enroll_limit: 'Number of enrolled keys permitted per account:',
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   160
        
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   161
        err_invalid_auth_server: 'The URL to the Yubikey authentication server that you entered is invalid.'
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   162
      }
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   163
    }
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   164
  }
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   165
}
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   166
</code>
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   167
**!*/
9d2c4f04a0d0 First commit! Hoping everything works.
Dan
parents:
diff changeset
   168