4 * StatusNet - the distributed open-source microblogging tool
5 * Copyright (C) 2009, StatusNet, Inc.
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * @category Installation
21 * @package Installation
23 * @author Adrian Lang <mail@adrianlang.de>
24 * @author Brenda Wallace <shiny@cpan.org>
25 * @author Brett Taylor <brett@webfroot.co.nz>
26 * @author Brion Vibber <brion@pobox.com>
27 * @author CiaranG <ciaran@ciarang.com>
28 * @author Craig Andrews <candrews@integralblue.com>
29 * @author Eric Helgeson <helfire@Erics-MBP.local>
30 * @author Evan Prodromou <evan@status.net>
31 * @author Robin Millette <millette@controlyourself.ca>
32 * @author Sarven Capadisli <csarven@status.net>
33 * @author Tom Adams <tom@holizz.com>
34 * @author Zach Copley <zach@status.net>
35 * @license GNU Affero General Public License http://www.gnu.org/licenses/
37 * @link http://status.net
40 define('INSTALLDIR', dirname(__FILE__));
42 $external_libraries=array(
45 'url'=>'http://us.php.net/manual/en/book.gettext.php',
46 'check_function'=>'gettext'
50 'url'=>'http://pear.php.net/',
52 'include'=>'PEAR.php',
58 'url'=>'http://pear.php.net/package/DB',
60 'include'=>'DB/common.php',
61 'check_class'=>'DB_common'
64 'name'=>'DB_DataObject',
65 'pear'=>'DB_DataObject',
66 'url'=>'http://pear.php.net/package/DB_DataObject',
67 'include'=>'DB/DataObject.php',
68 'check_class'=>'DB_DataObject'
71 'name'=>'Console_Getopt',
72 'pear'=>'Console_Getopt',
73 'url'=>'http://pear.php.net/package/Console_Getopt',
74 'include'=>'Console/Getopt.php',
75 'check_class'=>'Console_Getopt'
78 'name'=>'Facebook API',
79 'url'=>'http://developers.facebook.com/',
80 'include'=>'facebook/facebook.php',
81 'check_class'=>'Facebook'
85 'url'=>'http://www.bioinformatics.org/phplabware/internal_utilities/htmLawed',
86 'include'=>'htmLawed/htmLawed.php',
87 'check_function'=>'htmLawed'
90 'name'=>'HTTP_Request',
91 'pear'=>'HTTP_Request',
92 'url'=>'http://pear.php.net/package/HTTP_Request',
93 'deb'=>'php-http-request',
94 'include'=>'HTTP/Request.php',
95 'check_class'=>'HTTP_Request'
98 'name'=>'HTTP_Request2',
99 'pear'=>'HTTP_Request2',
100 'url'=>'http://pear.php.net/package/HTTP_Request2',
101 'include'=>'HTTP/Request2.php',
102 'check_class'=>'HTTP_Request2'
107 'url'=>'http://pear.php.net/package/Mail',
109 'include'=>'Mail.php',
110 'check_class'=>'Mail'
113 'name'=>'Mail_mimeDecode',
114 'pear'=>'Mail_mimeDecode',
115 'url'=>'http://pear.php.net/package/Mail_mimeDecode',
116 'deb'=>'php-mail-mimedecode',
117 'include'=>'Mail/mimeDecode.php',
118 'check_class'=>'Mail_mimeDecode'
123 'url'=>'http://pear.php.net/package/Mime_Type',
124 'include'=>'MIME/Type.php',
125 'check_class'=>'Mime_Type'
128 'name'=>'Net_URL_Mapper',
129 'pear'=>'Net_URL_Mapper',
130 'url'=>'http://pear.php.net/package/Net_URL_Mapper',
131 'include'=>'Net/URL/Mapper.php',
132 'check_class'=>'Net_URL_Mapper'
137 'url'=>'http://pear.php.net/package/Net_LDAP2',
138 'deb'=>'php-net-ldap2',
139 'include'=>'Net/LDAP2.php',
140 'check_class'=>'Net_LDAP2'
143 'name'=>'Net_Socket',
144 'pear'=>'Net_Socket',
145 'url'=>'http://pear.php.net/package/Net_Socket',
146 'deb'=>'php-net-socket',
147 'include'=>'Net/Socket.php',
148 'check_class'=>'Net_Socket'
153 'url'=>'http://pear.php.net/package/Net_SMTP',
154 'deb'=>'php-net-smtp',
155 'include'=>'Net/SMTP.php',
156 'check_class'=>'Net_SMTP'
161 'url'=>'http://pear.php.net/package/Net_URL',
162 'deb'=>'php-net-url',
163 'include'=>'Net/URL.php',
164 'check_class'=>'Net_URL'
169 'url'=>'http://pear.php.net/package/Net_URL2',
170 'include'=>'Net/URL2.php',
171 'check_class'=>'Net_URL2'
174 'name'=>'Services_oEmbed',
175 'pear'=>'Services_oEmbed',
176 'url'=>'http://pear.php.net/package/Services_oEmbed',
177 'include'=>'Services/oEmbed.php',
178 'check_class'=>'Services_oEmbed'
182 'url'=>'http://stomp.codehaus.org/PHP',
183 'include'=>'Stomp.php',
184 'check_class'=>'Stomp'
187 'name'=>'System_Command',
188 'pear'=>'System_Command',
189 'url'=>'http://pear.php.net/package/System_Command',
190 'include'=>'System/Command.php',
191 'check_class'=>'System_Command'
195 'url'=>'http://code.google.com/p/xmpphp',
196 'include'=>'XMPPHP/XMPP.php',
197 'check_class'=>'XMPPHP_XMPP'
200 'name'=>'PHP Markdown',
201 'url'=>'http://www.michelf.com/projects/php-markdown/',
202 'include'=>'markdown.php',
203 'check_class'=>'Markdown_Parser'
207 'url'=>'http://code.google.com/p/oauth-php',
208 'include'=>'OAuth.php',
209 'check_class'=>'OAuthRequest'
214 'url'=>'http://pear.php.net/package/Validate',
215 'include'=>'Validate.php',
216 'check_class'=>'Validate'
222 'check_module' => 'mysql', // mysqli?
223 'installer' => 'mysql_db_installer',
226 'name' => 'PostgreSQL',
227 'check_module' => 'pgsql',
228 'installer' => 'pgsql_db_installer',
233 * the actual installation.
234 * If call libraries are present, then install
240 if (!checkPrereqs()) {
244 if (!empty($_GET['checklibs'])) {
247 if ($_SERVER['REQUEST_METHOD'] == 'POST') {
256 * checks if an external libary is present
258 * @param string $external_library Name of library
260 * @return boolean indicates if library present
262 function haveExternalLibrary($external_library)
264 if (isset($external_library['include']) && !haveIncludeFile($external_library['include'])) {
267 if (isset($external_library['check_function']) && ! function_exists($external_library['check_function'])) {
270 if (isset($external_library['check_class']) && ! class_exists($external_library['check_class'])) {
276 // Attempt to include a PHP file and report if it worked, while
277 // suppressing the annoying warning messages on failure.
278 function haveIncludeFile($filename) {
279 $old = error_reporting(error_reporting() & ~E_WARNING);
280 $ok = include_once($filename);
281 error_reporting($old);
286 * Check if all is ready for installation
290 function checkPrereqs()
294 if (file_exists(INSTALLDIR.'/config.php')) {
295 printf('<p class="error">Config file "config.php" already exists.</p>');
299 if (version_compare(PHP_VERSION, '5.2.3', '<')) {
300 printf('<p class="error">Require PHP version 5.2.3 or greater.</p>');
304 // Look for known library bugs
305 $str = "abcdefghijklmnopqrstuvwxyz";
306 $replaced = preg_replace('/[\p{Cc}\p{Cs}]/u', '*', $str);
307 if ($str != $replaced) {
308 printf('<p class="error">PHP is linked to a version of the PCRE library ' .
309 'that does not support Unicode properties. ' .
310 'If you are running Red Hat Enterprise Linux / ' .
311 'CentOS 5.4 or earlier, see <a href="' .
312 'http://status.net/wiki/Red_Hat_Enterprise_Linux#PCRE_library' .
313 '">our documentation page</a> on fixing this.</p>');
317 $reqs = array('gd', 'curl',
318 'xmlwriter', 'mbstring', 'xml', 'dom', 'simplexml');
320 foreach ($reqs as $req) {
321 if (!checkExtension($req)) {
322 printf('<p class="error">Cannot load required extension: <code>%s</code></p>', $req);
326 // Make sure we have at least one database module available
328 $missingExtensions = array();
329 foreach ($dbModules as $type => $info) {
330 if (!checkExtension($info['check_module'])) {
331 $missingExtensions[] = $info['check_module'];
335 if (count($missingExtensions) == count($dbModules)) {
336 $req = implode(', ', $missingExtensions);
337 printf('<p class="error">Cannot find mysql or pgsql extension. You need one or the other.');
341 if (!is_writable(INSTALLDIR)) {
342 printf('<p class="error">Cannot write config file to: <code>%s</code></p>', INSTALLDIR);
343 printf('<p>On your server, try this command: <code>chmod a+w %s</code>', INSTALLDIR);
347 // Check the subdirs used for file uploads
348 $fileSubdirs = array('avatar', 'background', 'file');
349 foreach ($fileSubdirs as $fileSubdir) {
350 $fileFullPath = INSTALLDIR."/$fileSubdir/";
351 if (!is_writable($fileFullPath)) {
352 printf('<p class="error">Cannot write to %s directory: <code>%s</code></p>', $fileSubdir, $fileFullPath);
353 printf('<p>On your server, try this command: <code>chmod a+w %s</code></p>', $fileFullPath);
362 * Checks if a php extension is both installed and loaded
364 * @param string $name of extension to check
366 * @return boolean whether extension is installed and loaded
368 function checkExtension($name)
370 if (extension_loaded($name)) {
372 } elseif (function_exists('dl') && ini_get('enable_dl') && !ini_get('safe_mode')) {
373 // dl will throw a fatal error if it's disabled or we're in safe mode.
374 // More fun, it may not even exist under some SAPIs in 5.3.0 or later...
375 $soname = $name . '.' . PHP_SHLIB_SUFFIX;
376 if (PHP_SHLIB_SUFFIX == 'dll') {
377 $soname = "php_" . $soname;
386 * Show list of libraries
392 global $external_libraries;
393 $present_libraries=array();
394 $absent_libraries=array();
395 foreach ($external_libraries as $external_library) {
396 if (haveExternalLibrary($external_library)) {
397 $present_libraries[]=$external_library;
399 $absent_libraries[]=$external_library;
403 <div class="instructions">
404 <p>StatusNet comes bundled with a number of libraries required for the application to work. However, it is best that you use PEAR or you distribution to manage
405 libraries instead, as they tend to provide security updates faster, and may offer improved performance.</p>
406 <p>On Debian based distributions, such as Ubuntu, use a package manager (such as "aptitude", "apt-get", and "synaptic") to install the package listed.</p>
407 <p>On RPM based distributions, such as Red Hat, Fedora, CentOS, Scientific Linux, Yellow Dog Linux and Oracle Enterprise Linux, use a package manager (such as "yum", "apt-rpm", and "up2date") to install the package listed.</p>
408 <p>On servers without a package manager (such as Windows), or if the library is not packaged for your distribution, you can use PHP's PEAR to install the library. Simply run "pear install <name>".</p>
410 <h2>Absent Libraries</h2>
411 <ul id="absent_libraries">
413 foreach ($absent_libraries as $library) {
415 if (isset($library['url'])) {
416 echo '<a href="'.$library['url'].'">'.htmlentities($library['name']).'</a>';
418 echo htmlentities($library['name']);
421 if (isset($library['deb'])) {
422 echo '<li class="deb package">deb: <a href="apt:' . urlencode($library['deb']) . '">' . htmlentities($library['deb']) . '</a></li>';
424 if (isset($library['rpm'])) {
425 echo '<li class="rpm package">rpm: ' . htmlentities($library['rpm']) . '</li>';
427 if (isset($library['pear'])) {
428 echo '<li class="pear package">pear: ' . htmlentities($library['pear']) . '</li>';
434 <h2>Installed Libraries</h2>
435 <ul id="present_libraries">
437 foreach ($present_libraries as $library) {
439 if (isset($library['url'])) {
440 echo '<a href="'.$library['url'].'">'.htmlentities($library['name']).'</a>';
442 echo htmlentities($library['name']);
452 * Helper class for building form
455 function value($name)
457 if (isset($_POST[$name])) {
458 return htmlspecialchars(strval($_POST[$name]));
468 $post = new Posted();
470 if (isset($_POST['dbtype'])) {
471 $dbtype = $_POST['dbtype'];
475 foreach ($dbModules as $type => $info) {
476 if (checkExtension($info['check_module'])) {
477 if ($dbtype == null || $dbtype == $type) {
478 $checked = 'checked="checked" ';
479 $dbtype = $type; // if we didn't have one checked, hit the first
483 $dbRadios .= "<input type=\"radio\" name=\"dbtype\" id=\"dbtype-$type\" value=\"$type\" $checked/> $info[name]<br />\n";
491 <form method="post" action="install.php" class="form_settings" id="form_install">
493 <fieldset id="settings_site">
494 <legend>Site settings</legend>
495 <ul class="form_data">
497 <label for="sitename">Site name</label>
498 <input type="text" id="sitename" name="sitename" value="{$post->value('sitename')}" />
499 <p class="form_guide">The name of your site</p>
502 <label for="fancy-enable">Fancy URLs</label>
503 <input type="radio" name="fancy" id="fancy-enable" value="enable" checked='checked' /> enable<br />
504 <input type="radio" name="fancy" id="fancy-disable" value="" /> disable<br />
505 <p class="form_guide" id='fancy-form_guide'>Enable fancy (pretty) URLs. Auto-detection failed, it depends on Javascript.</p>
510 <fieldset id="settings_db">
511 <legend>Database settings</legend>
512 <ul class="form_data">
514 <label for="host">Hostname</label>
515 <input type="text" id="host" name="host" value="{$post->value('host')}" />
516 <p class="form_guide">Database hostname</p>
519 <label for="dbtype">Type</label>
521 <p class="form_guide">Database type</p>
524 <label for="database">Name</label>
525 <input type="text" id="database" name="database" value="{$post->value('database')}" />
526 <p class="form_guide">Database name</p>
529 <label for="dbusername">DB username</label>
530 <input type="text" id="dbusername" name="dbusername" value="{$post->value('dbusername')}" />
531 <p class="form_guide">Database username</p>
534 <label for="dbpassword">DB password</label>
535 <input type="password" id="dbpassword" name="dbpassword" value="{$post->value('dbpassword')}" />
536 <p class="form_guide">Database password (optional)</p>
541 <fieldset id="settings_admin">
542 <legend>Administrator settings</legend>
543 <ul class="form_data">
545 <label for="admin_nickname">Administrator nickname</label>
546 <input type="text" id="admin_nickname" name="admin_nickname" value="{$post->value('admin_nickname')}" />
547 <p class="form_guide">Nickname for the initial StatusNet user (administrator)</p>
550 <label for="admin_password">Administrator password</label>
551 <input type="password" id="admin_password" name="admin_password" value="{$post->value('admin_password')}" />
552 <p class="form_guide">Password for the initial StatusNet user (administrator)</p>
555 <label for="admin_password2">Confirm password</label>
556 <input type="password" id="admin_password2" name="admin_password2" value="{$post->value('admin_password2')}" />
559 <label for="admin_email">Administrator e-mail</label>
560 <input id="admin_email" name="admin_email" value="{$post->value('admin_email')}" />
561 <p class="form_guide">Optional email address for the initial StatusNet user (administrator)</p>
564 <label for="admin_updates">Subscribe to announcements</label>
565 <input type="checkbox" id="admin_updates" name="admin_updates" value="true" checked="checked" />
566 <p class="form_guide">Release and security feed from <a href="http://update.status.net/">update@status.net</a> (recommended)</p>
570 <input type="submit" name="submit" class="submit" value="Submit" />
577 function updateStatus($status, $error=false)
579 echo '<li' . ($error ? ' class="error"': '' ) . ">$status</li>";
582 function handlePost()
584 $host = $_POST['host'];
585 $dbtype = $_POST['dbtype'];
586 $database = $_POST['database'];
587 $username = $_POST['dbusername'];
588 $password = $_POST['dbpassword'];
589 $sitename = $_POST['sitename'];
590 $fancy = !empty($_POST['fancy']);
592 $adminNick = strtolower($_POST['admin_nickname']);
593 $adminPass = $_POST['admin_password'];
594 $adminPass2 = $_POST['admin_password2'];
595 $adminEmail = $_POST['admin_email'];
596 $adminUpdates = $_POST['admin_updates'];
598 $server = $_SERVER['HTTP_HOST'];
599 $path = substr(dirname($_SERVER['PHP_SELF']), 1);
602 <dl class="system_notice">
610 updateStatus("No hostname specified.", true);
614 if (empty($database)) {
615 updateStatus("No database specified.", true);
619 if (empty($username)) {
620 updateStatus("No username specified.", true);
624 if (empty($sitename)) {
625 updateStatus("No sitename specified.", true);
629 if (empty($adminNick)) {
630 updateStatus("No initial StatusNet user nickname specified.", true);
633 if ($adminNick && !preg_match('/^[0-9a-z]{1,64}$/', $adminNick)) {
634 updateStatus('The user nickname "' . htmlspecialchars($adminNick) .
635 '" is invalid; should be plain letters and numbers no longer than 64 characters.', true);
638 // @fixme hardcoded list; should use User::allowed_nickname()
639 // if/when it's safe to have loaded the infrastructure here
640 $blacklist = array('main', 'admin', 'twitter', 'settings', 'rsd.xml', 'favorited', 'featured', 'favoritedrss', 'featuredrss', 'rss', 'getfile', 'api', 'groups', 'group', 'peopletag', 'tag', 'user', 'message', 'conversation', 'bookmarklet', 'notice', 'attachment', 'search', 'index.php', 'doc', 'opensearch', 'robots.txt', 'xd_receiver.html', 'facebook');
641 if (in_array($adminNick, $blacklist)) {
642 updateStatus('The user nickname "' . htmlspecialchars($adminNick) .
643 '" is reserved.', true);
647 if (empty($adminPass)) {
648 updateStatus("No initial StatusNet user password specified.", true);
652 if ($adminPass != $adminPass2) {
653 updateStatus("Administrator passwords do not match. Did you mistype?", true);
663 $db = call_user_func($dbModules[$dbtype]['installer'], $host, $database, $username, $password);
666 // database connection failed, do not move on to create config file.
670 updateStatus("Writing config file...");
671 $res = writeConf($sitename, $server, $path, $fancy, $db);
674 updateStatus("Can't write config file.", true);
679 // Okay, cross fingers and try to register an initial user
680 if (registerInitialUser($adminNick, $adminPass, $adminEmail, $adminUpdates)) {
682 "An initial user with the administrator role has been created."
686 "Could not create initial StatusNet user (administrator).",
694 TODO https needs to be considered
696 $link = "http://".$server.'/'.$path;
698 updateStatus("StatusNet has been installed at $link");
700 "<strong>DONE!</strong> You can visit your <a href='$link'>new StatusNet site</a> (login as '$adminNick'). If this is your first StatusNet install, you may want to poke around our <a href='http://status.net/wiki/Getting_started'>Getting Started guide</a>."
704 function Pgsql_Db_installer($host, $database, $username, $password)
706 $connstring = "dbname=$database host=$host user=$username";
708 //No password would mean trust authentication used.
709 if (!empty($password)) {
710 $connstring .= " password=$password";
712 updateStatus("Starting installation...");
713 updateStatus("Checking database...");
714 $conn = pg_connect($connstring);
716 if ($conn ===false) {
717 updateStatus("Failed to connect to database: $connstring");
722 //ensure database encoding is UTF8
723 $record = pg_fetch_object(pg_query($conn, 'SHOW server_encoding'));
724 if ($record->server_encoding != 'UTF8') {
725 updateStatus("StatusNet requires UTF8 character encoding. Your database is ". htmlentities($record->server_encoding));
730 updateStatus("Running database script...");
731 //wrap in transaction;
732 pg_query($conn, 'BEGIN');
733 $res = runDbScript(INSTALLDIR.'/db/statusnet_pg.sql', $conn, 'pgsql');
735 if ($res === false) {
736 updateStatus("Can't run database script.", true);
740 foreach (array('sms_carrier' => 'SMS carrier',
741 'notice_source' => 'notice source',
742 'foreign_services' => 'foreign service')
744 updateStatus(sprintf("Adding %s data to database...", $name));
745 $res = runDbScript(INSTALLDIR.'/db/'.$scr.'.sql', $conn, 'pgsql');
746 if ($res === false) {
747 updateStatus(sprintf("Can't run %d script.", $name), true);
752 pg_query($conn, 'COMMIT');
754 if (empty($password)) {
755 $sqlUrl = "pgsql://$username@$host/$database";
757 $sqlUrl = "pgsql://$username:$password@$host/$database";
760 $db = array('type' => 'pgsql', 'database' => $sqlUrl);
765 function Mysql_Db_installer($host, $database, $username, $password)
767 updateStatus("Starting installation...");
768 updateStatus("Checking database...");
770 $conn = mysql_connect($host, $username, $password);
772 updateStatus("Can't connect to server '$host' as '$username'.", true);
776 updateStatus("Changing to database...");
777 $res = mysql_select_db($database, $conn);
779 updateStatus("Can't change to database.", true);
783 updateStatus("Running database script...");
784 $res = runDbScript(INSTALLDIR.'/db/statusnet.sql', $conn);
785 if ($res === false) {
786 updateStatus("Can't run database script.", true);
790 foreach (array('sms_carrier' => 'SMS carrier',
791 'notice_source' => 'notice source',
792 'foreign_services' => 'foreign service')
794 updateStatus(sprintf("Adding %s data to database...", $name));
795 $res = runDbScript(INSTALLDIR.'/db/'.$scr.'.sql', $conn);
796 if ($res === false) {
797 updateStatus(sprintf("Can't run %d script.", $name), true);
803 $sqlUrl = "mysqli://$username:$password@$host/$database";
804 $db = array('type' => 'mysql', 'database' => $sqlUrl);
808 function writeConf($sitename, $server, $path, $fancy, $db)
810 // assemble configuration file in a string
812 "if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }\n\n".
815 "\$config['site']['name'] = '$sitename';\n\n".
818 "\$config['site']['server'] = '$server';\n".
819 "\$config['site']['path'] = '$path'; \n\n".
821 // checks if fancy URLs are enabled
822 ($fancy ? "\$config['site']['fancy'] = true;\n\n":'').
825 "\$config['db']['database'] = '{$db['database']}';\n\n".
826 ($db['type'] == 'pgsql' ? "\$config['db']['quote_identifiers'] = true;\n\n":'').
827 "\$config['db']['type'] = '{$db['type']}';\n\n";
828 // write configuration file out to install directory
829 $res = file_put_contents(INSTALLDIR.'/config.php', $cfg);
835 * Install schema into the database
837 * @param string $filename location of database schema file
838 * @param dbconn $conn connection to database
839 * @param string $type type of database, currently mysql or pgsql
841 * @return boolean - indicating success or failure
843 function runDbScript($filename, $conn, $type = 'mysqli')
845 $sql = trim(file_get_contents($filename));
846 $stmts = explode(';', $sql);
847 foreach ($stmts as $stmt) {
849 if (!mb_strlen($stmt)) {
852 // FIXME: use PEAR::DB or PDO instead of our own switch
855 $res = mysql_query($stmt, $conn);
856 if ($res === false) {
857 $error = mysql_error();
861 $res = pg_query($conn, $stmt);
862 if ($res === false) {
863 $error = pg_last_error();
867 updateStatus("runDbScript() error: unknown database type ". $type ." provided.");
869 if ($res === false) {
870 updateStatus("ERROR ($error) for SQL '$stmt'");
877 function registerInitialUser($nickname, $password, $email, $adminUpdates)
879 define('STATUSNET', true);
880 define('LACONICA', true); // compatibility
882 require_once INSTALLDIR . '/lib/common.php';
884 $data = array('nickname' => $nickname,
885 'password' => $password,
886 'fullname' => $nickname);
888 $data['email'] = $email;
890 $user = User::register($data);
896 // give initial user carte blanche
898 $user->grantRole('owner');
899 $user->grantRole('moderator');
900 $user->grantRole('administrator');
902 // Attempt to do a remote subscribe to update@status.net
903 // Will fail if instance is on a private network.
905 if (class_exists('Ostatus_profile') && $adminUpdates) {
907 $oprofile = Ostatus_profile::ensureProfile('http://update.status.net/');
908 Subscription::start($user->getProfile(), $oprofile->localProfile());
909 updateStatus("Set up subscription to <a href='http://update.status.net/'>update@status.net</a>.");
910 } catch (Exception $e) {
911 updateStatus("Could not set up subscription to <a href='http://update.status.net/'>update@status.net</a>.");
919 <?php echo"<?"; ?> xml version="1.0" encoding="UTF-8" <?php echo "?>"; ?>
921 PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
922 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
923 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en_US" lang="en_US">
925 <title>Install StatusNet</title>
926 <link rel="shortcut icon" href="favicon.ico"/>
927 <link rel="stylesheet" type="text/css" href="theme/default/css/display.css" media="screen, projection, tv"/>
928 <!--[if IE]><link rel="stylesheet" type="text/css" href="theme/base/css/ie.css" /><![endif]-->
929 <!--[if lte IE 6]><link rel="stylesheet" type="text/css" theme/base/css/ie6.css" /><![endif]-->
930 <!--[if IE]><link rel="stylesheet" type="text/css" href="theme/default/css/ie.css" /><![endif]-->
931 <script src="js/jquery.min.js"></script>
932 <script src="js/install.js"></script>
937 <address id="site_contact" class="vcard">
938 <a class="url home bookmark" href=".">
939 <img class="logo photo" src="theme/default/logo.png" alt="StatusNet"/>
940 <span class="fn org">StatusNet</span>
946 <div id="content_inner">
947 <h1>Install StatusNet</h1>