/** * These functions provide access to hitcounter for use in the HTML block. * * @param string $page_name * @param string[] $params * * @return string */ private function hitCountQuery($page_name, $params) { if (is_array($params) && isset($params[0]) && $params[0] != '') { $page_parameter = $params[0]; } else { $page_parameter = ''; } if ($page_name === null) { // index.php?ctype=gedcom $page_name = 'index.php'; $page_parameter = 'gedcom:' . ($page_parameter ? Tree::findByName($page_parameter)->getTreeId() : $this->tree->getTreeId()); } elseif ($page_name == 'index.php') { // index.php?ctype=user $user = User::findByIdentifier($page_parameter); $page_parameter = 'user:'******'<span class="odometer">' . I18N::digits(HitCounter::getCount($this->tree, $page_name, $page_parameter)) . '</span>'; }
$form_pass1 = Filter::post('form_pass1', WT_REGEX_PASSWORD); $form_pass2 = Filter::post('form_pass2', WT_REGEX_PASSWORD); $form_email = Filter::postEmail('form_email'); $form_rootid = Filter::post('form_rootid', WT_REGEX_XREF); $form_theme = Filter::post('form_theme'); $form_language = Filter::post('form_language'); $form_timezone = Filter::post('form_timezone'); $form_contact_method = Filter::post('form_contact_method'); $form_visible_online = Filter::postBool('form_visible_online'); // Respond to form action if ($form_action && Filter::checkCsrf()) { switch ($form_action) { case 'update': if ($form_username !== Auth::user()->getUserName() && User::findByIdentifier($form_username)) { FlashMessages::addMessage(I18N::translate('Duplicate user name. A user with that user name already exists. Please choose another user name.')); } elseif ($form_email !== Auth::user()->getEmail() && User::findByIdentifier($form_email)) { FlashMessages::addMessage(I18N::translate('Duplicate email address. A user with that email already exists.')); } else { // Change username if ($form_username !== Auth::user()->getUserName()) { Log::addAuthenticationLog('User ' . Auth::user()->getUserName() . ' renamed to ' . $form_username); Auth::user()->setUserName($form_username); } // Change password if ($form_pass1 && $form_pass1 === $form_pass2) { Auth::user()->setPassword($form_pass1); } // Change other settings Auth::user()->setRealName($form_realname)->setEmail($form_email)->setPreference('language', $form_language)->setPreference('TIMEZONE', $form_timezone)->setPreference('contactmethod', $form_contact_method)->setPreference('visibleonline', $form_visible_online ? '1' : '0'); if ($form_theme === null) { Auth::user()->deletePreference('theme');
/** * Print a fact record, for the individual/family/source/repository/etc. pages. * * Although a Fact has a parent object, we also need to know * the GedcomRecord for which we are printing it. For example, * we can show the death of X on the page of Y, or the marriage * of X+Y on the page of Z. We need to know both records to * calculate ages, relationships, etc. * * @param Fact $fact * @param GedcomRecord $record */ public static function printFact(Fact $fact, GedcomRecord $record) { static $n_chil = 0, $n_gchi = 0; $parent = $fact->getParent(); // Some facts don't get printed here ... switch ($fact->getTag()) { case 'NOTE': self::printMainNotes($fact, 1); return; case 'SOUR': self::printMainSources($fact, 1); return; case 'OBJE': self::printMainMedia($fact, 1); return; case 'FAMC': case 'FAMS': case 'CHIL': case 'HUSB': case 'WIFE': // These are internal links, not facts return; case '_WT_OBJE_SORT': // These links are used internally to record the sort order. return; default: // Hide unrecognized/custom tags? if ($fact->getParent()->getTree()->getPreference('HIDE_GEDCOM_ERRORS') && !GedcomTag::isTag($fact->getTag())) { return; } break; } // Who is this fact about? Need it to translate fact label correctly if ($parent instanceof Family && $record instanceof Individual) { // Family event $label_person = $fact->getParent()->getSpouse($record); } else { // Individual event $label_person = $parent; } // New or deleted facts need different styling $styleadd = ''; if ($fact->isPendingAddition()) { $styleadd = 'new'; } if ($fact->isPendingDeletion()) { $styleadd = 'old'; } // Event of close relative if (preg_match('/^_[A-Z_]{3,5}_[A-Z0-9]{4}$/', $fact->getTag())) { $styleadd = trim($styleadd . ' rela'); } // Event of close associates if ($fact->getFactId() == 'asso') { $styleadd = trim($styleadd . ' rela'); } // historical facts if ($fact->getFactId() == 'histo') { $styleadd = trim($styleadd . ' histo'); } // Does this fact have a type? if (preg_match('/\\n2 TYPE (.+)/', $fact->getGedcom(), $match)) { $type = $match[1]; } else { $type = ''; } switch ($fact->getTag()) { case 'EVEN': case 'FACT': if (GedcomTag::isTag($type)) { // Some users (just Meliza?) use "1 EVEN/2 TYPE BIRT". Translate the TYPE. $label = GedcomTag::getLabel($type, $label_person); $type = ''; // Do not print this again } elseif ($type) { // We don't have a translation for $type - but a custom translation might exist. $label = I18N::translate(Filter::escapeHtml($type)); $type = ''; // Do not print this again } else { // An unspecified fact/event $label = $fact->getLabel(); } break; case 'MARR': // This is a hack for a proprietory extension. Is it still used/needed? $utype = strtoupper($type); if ($utype == 'CIVIL' || $utype == 'PARTNERS' || $utype == 'RELIGIOUS') { $label = GedcomTag::getLabel('MARR_' . $utype, $label_person); $type = ''; // Do not print this again } else { $label = $fact->getLabel(); } break; default: // Normal fact/event $label = $fact->getLabel(); break; } echo '<tr class="', $styleadd, '">'; echo '<td class="descriptionbox width20">'; if ($fact->getParent()->getTree()->getPreference('SHOW_FACT_ICONS')) { echo Theme::theme()->icon($fact), ' '; } if ($fact->getFactId() != 'histo' && $fact->canEdit()) { ?> <a href="#" title="<?php echo I18N::translate('Edit'); ?> " onclick="return edit_record('<?php echo $parent->getXref(); ?> ', '<?php echo $fact->getFactId(); ?> ');" ><?php echo $label; ?> </a> <div class="editfacts"> <div class="editlink"> <a href="#" title="<?php echo I18N::translate('Edit'); ?> " class="editicon" onclick="return edit_record('<?php echo $parent->getXref(); ?> ', '<?php echo $fact->getFactId(); ?> ');" ><span class="link_text"><?php echo I18N::translate('Edit'); ?> </span></a> </div> <div class="copylink"> <a href="#" title="<?php echo I18N::translate('Copy'); ?> " class="copyicon" onclick="return copy_fact('<?php echo $parent->getXref(); ?> ', '<?php echo $fact->getFactId(); ?> ');" ><span class="link_text"><?php echo I18N::translate('Copy'); ?> </span></a> </div> <div class="deletelink"> <a href="#" title="<?php echo I18N::translate('Delete'); ?> " class="deleteicon" onclick="return delete_fact('<?php echo I18N::translate('Are you sure you want to delete this fact?'); ?> ', '<?php echo $parent->getXref(); ?> ', '<?php echo $fact->getFactId(); ?> ');" ><span class="link_text"><?php echo I18N::translate('Delete'); ?> </span></a> </div> </div> <?php } else { echo $label; } switch ($fact->getTag()) { case '_BIRT_CHIL': echo '<br>', I18N::translate('#%s', ++$n_chil); break; case '_BIRT_GCHI': case '_BIRT_GCH1': case '_BIRT_GCH2': echo '<br>', I18N::translate('#%s', ++$n_gchi); break; } echo '</td><td class="optionbox ', $styleadd, ' wrap">'; // Event from another record? if ($parent !== $record) { if ($parent instanceof Family) { foreach ($parent->getSpouses() as $spouse) { if ($record !== $spouse) { echo '<a href="', $spouse->getHtmlUrl(), '">', $spouse->getFullName(), '</a> — '; } } echo '<a href="', $parent->getHtmlUrl(), '">', I18N::translate('View family'), '</a><br>'; } elseif ($parent instanceof Individual) { echo '<a href="', $parent->getHtmlUrl(), '">', $parent->getFullName(), '</a><br>'; } } // Print the value of this fact/event switch ($fact->getTag()) { case 'ADDR': echo $fact->getValue(); break; case 'AFN': echo '<div class="field"><a href="https://familysearch.org/search/tree/results#count=20&query=afn:', rawurlencode($fact->getValue()), '" target="new">', Filter::escapeHtml($fact->getValue()), '</a></div>'; break; case 'ASSO': // we handle this later, in format_asso_rela_record() break; case 'EMAIL': case 'EMAI': case '_EMAIL': echo '<div class="field"><a href="mailto:', Filter::escapeHtml($fact->getValue()), '">', Filter::escapeHtml($fact->getValue()), '</a></div>'; break; case 'FILE': if (Auth::isEditor($fact->getParent()->getTree())) { echo '<div class="field">', Filter::escapeHtml($fact->getValue()), '</div>'; } break; case 'RESN': echo '<div class="field">'; switch ($fact->getValue()) { case 'none': // Note: "1 RESN none" is not valid gedcom. // However, webtrees privacy rules will interpret it as "show an otherwise private record to public". echo '<i class="icon-resn-none"></i> ', I18N::translate('Show to visitors'); break; case 'privacy': echo '<i class="icon-class-none"></i> ', I18N::translate('Show to members'); break; case 'confidential': echo '<i class="icon-confidential-none"></i> ', I18N::translate('Show to managers'); break; case 'locked': echo '<i class="icon-locked-none"></i> ', I18N::translate('Only managers can edit'); break; default: echo Filter::escapeHtml($fact->getValue()); break; } echo '</div>'; break; case 'PUBL': // Publication details might contain URLs. echo '<div class="field">', Filter::expandUrls($fact->getValue()), '</div>'; break; case 'REPO': if (preg_match('/^@(' . WT_REGEX_XREF . ')@$/', $fact->getValue(), $match)) { self::printRepositoryRecord($match[1]); } else { echo '<div class="error">', Filter::escapeHtml($fact->getValue()), '</div>'; } break; case 'URL': case '_URL': case 'WWW': echo '<div class="field"><a href="', Filter::escapeHtml($fact->getValue()), '">', Filter::escapeHtml($fact->getValue()), '</a></div>'; break; case 'TEXT': // 0 SOUR / 1 TEXT echo '<div class="field">', nl2br(Filter::escapeHtml($fact->getValue()), false), '</div>'; break; default: // Display the value for all other facts/events switch ($fact->getValue()) { case '': // Nothing to display break; case 'N': // Not valid GEDCOM echo '<div class="field">', I18N::translate('No'), '</div>'; break; case 'Y': // Do not display "Yes". break; default: if (preg_match('/^@(' . WT_REGEX_XREF . ')@$/', $fact->getValue(), $match)) { $target = GedcomRecord::getInstance($match[1], $fact->getParent()->getTree()); if ($target) { echo '<div><a href="', $target->getHtmlUrl(), '">', $target->getFullName(), '</a></div>'; } else { echo '<div class="error">', Filter::escapeHtml($fact->getValue()), '</div>'; } } else { echo '<div class="field"><span dir="auto">', Filter::escapeHtml($fact->getValue()), '</span></div>'; } break; } break; } // Print the type of this fact/event if ($type) { $utype = strtoupper($type); // Events of close relatives, e.g. _MARR_CHIL if (substr($fact->getTag(), 0, 6) == '_MARR_' && ($utype == 'CIVIL' || $utype == 'PARTNERS' || $utype == 'RELIGIOUS')) { // Translate MARR/TYPE using the code that supports MARR_CIVIL, etc. tags $type = GedcomTag::getLabel('MARR_' . $utype); } else { // Allow (custom) translations for other types $type = I18N::translate($type); } echo GedcomTag::getLabelValue('TYPE', Filter::escapeHtml($type)); } // Print the date of this fact/event echo FunctionsPrint::formatFactDate($fact, $record, true, true); // Print the place of this fact/event echo '<div class="place">', FunctionsPrint::formatFactPlace($fact, true, true, true), '</div>'; // A blank line between the primary attributes (value, date, place) and the secondary ones echo '<br>'; $addr = $fact->getAttribute('ADDR'); if ($addr) { echo GedcomTag::getLabelValue('ADDR', $addr); } // Print the associates of this fact/event if ($fact->getFactId() !== 'asso') { echo self::formatAssociateRelationship($fact); } // Print any other "2 XXXX" attributes, in the order in which they appear. preg_match_all('/\\n2 (' . WT_REGEX_TAG . ') (.+)/', $fact->getGedcom(), $matches, PREG_SET_ORDER); foreach ($matches as $match) { switch ($match[1]) { case 'DATE': case 'TIME': case 'AGE': case 'PLAC': case 'ADDR': case 'ALIA': case 'ASSO': case '_ASSO': case 'DESC': case 'RELA': case 'STAT': case 'TEMP': case 'TYPE': case 'FAMS': case 'CONT': // These were already shown at the beginning break; case 'NOTE': case 'OBJE': case 'SOUR': // These will be shown at the end break; case 'EVEN': // 0 SOUR / 1 DATA / 2 EVEN / 3 DATE / 3 PLAC $events = array(); foreach (preg_split('/ *, */', $match[2]) as $event) { $events[] = GedcomTag::getLabel($event); } if (count($events) == 1) { echo GedcomTag::getLabelValue('EVEN', $event); } else { echo GedcomTag::getLabelValue('EVEN', implode(I18N::$list_separator, $events)); } if (preg_match('/\\n3 DATE (.+)/', $fact->getGedcom(), $date_match)) { $date = new Date($date_match[1]); echo GedcomTag::getLabelValue('DATE', $date->display()); } if (preg_match('/\\n3 PLAC (.+)/', $fact->getGedcom(), $plac_match)) { echo GedcomTag::getLabelValue('PLAC', $plac_match[1]); } break; case 'FAMC': // 0 INDI / 1 ADOP / 2 FAMC / 3 ADOP $family = Family::getInstance(str_replace('@', '', $match[2]), $fact->getParent()->getTree()); if ($family) { echo GedcomTag::getLabelValue('FAM', '<a href="' . $family->getHtmlUrl() . '">' . $family->getFullName() . '</a>'); if (preg_match('/\\n3 ADOP (HUSB|WIFE|BOTH)/', $fact->getGedcom(), $match)) { echo GedcomTag::getLabelValue('ADOP', GedcomCodeAdop::getValue($match[1], $label_person)); } } else { echo GedcomTag::getLabelValue('FAM', '<span class="error">' . $match[2] . '</span>'); } break; case '_WT_USER': $user = User::findByIdentifier($match[2]); // may not exist if ($user) { echo GedcomTag::getLabelValue('_WT_USER', $user->getRealNameHtml()); } else { echo GedcomTag::getLabelValue('_WT_USER', Filter::escapeHtml($match[2])); } break; case 'RESN': switch ($match[2]) { case 'none': // Note: "2 RESN none" is not valid gedcom. // However, webtrees privacy rules will interpret it as "show an otherwise private fact to public". echo GedcomTag::getLabelValue('RESN', '<i class="icon-resn-none"></i> ' . I18N::translate('Show to visitors')); break; case 'privacy': echo GedcomTag::getLabelValue('RESN', '<i class="icon-resn-privacy"></i> ' . I18N::translate('Show to members')); break; case 'confidential': echo GedcomTag::getLabelValue('RESN', '<i class="icon-resn-confidential"></i> ' . I18N::translate('Show to managers')); break; case 'locked': echo GedcomTag::getLabelValue('RESN', '<i class="icon-resn-locked"></i> ' . I18N::translate('Only managers can edit')); break; default: echo GedcomTag::getLabelValue('RESN', Filter::escapeHtml($match[2])); break; } break; case 'CALN': echo GedcomTag::getLabelValue('CALN', Filter::expandUrls($match[2])); break; case 'FORM': // 0 OBJE / 1 FILE / 2 FORM / 3 TYPE echo GedcomTag::getLabelValue('FORM', $match[2]); if (preg_match('/\\n3 TYPE (.+)/', $fact->getGedcom(), $type_match)) { echo GedcomTag::getLabelValue('TYPE', GedcomTag::getFileFormTypeValue($type_match[1])); } break; case 'URL': case '_URL': case 'WWW': $link = '<a href="' . Filter::escapeHtml($match[2]) . '">' . Filter::escapeHtml($match[2]) . '</a>'; echo GedcomTag::getLabelValue($fact->getTag() . ':' . $match[1], $link); break; default: if (!$fact->getParent()->getTree()->getPreference('HIDE_GEDCOM_ERRORS') || GedcomTag::isTag($match[1])) { if (preg_match('/^@(' . WT_REGEX_XREF . ')@$/', $match[2], $xmatch)) { // Links $linked_record = GedcomRecord::getInstance($xmatch[1], $fact->getParent()->getTree()); if ($linked_record) { $link = '<a href="' . $linked_record->getHtmlUrl() . '">' . $linked_record->getFullName() . '</a>'; echo GedcomTag::getLabelValue($fact->getTag() . ':' . $match[1], $link); } else { echo GedcomTag::getLabelValue($fact->getTag() . ':' . $match[1], Filter::escapeHtml($match[2])); } } else { // Non links echo GedcomTag::getLabelValue($fact->getTag() . ':' . $match[1], Filter::escapeHtml($match[2])); } } break; } } echo self::printFactSources($fact->getGedcom(), 2); echo FunctionsPrint::printFactNotes($fact->getGedcom(), 2); self::printMediaLinks($fact->getGedcom(), 2); echo '</td></tr>'; }
<form id="new_passwd_form" name="new_passwd_form" action="' . WT_LOGIN_URL . '" method="post"> <input type="hidden" name="action" value="requestpw"> <h4>', I18N::translate('Lost password request'), '</h4> <div> <label for="new_passwd_username">', I18N::translate('Username or email address'), '<input type="text" id="new_passwd_username" name="new_passwd_username" value=""> </label> </div> <div><input type="submit" value="', I18N::translate('continue'), '"></div> </form> </div>'; echo '</div>'; echo '</div>'; break; case 'requestpw': $user_name = Filter::post('new_passwd_username'); $user = User::findByIdentifier($user_name); if ($user) { $passchars = 'abcdefghijklmnopqrstuvqxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $user_new_pw = ''; $max = strlen($passchars) - 1; for ($i = 0; $i < 8; $i++) { $index = rand(0, $max); $user_new_pw .= $passchars[$index]; } $user->setPassword($user_new_pw); Log::addAuthenticationLog('Password request was sent to user: '******'Lost password request'), I18N::translate('Hello %s…', $user->getRealNameHtml()) . Mail::EOL . Mail::EOL . I18N::translate('A new password has been requested for your user name.') . Mail::EOL . Mail::EOL . I18N::translate('Username') . ": " . Filter::escapeHtml($user->getUserName()) . Mail::EOL . I18N::translate('Password') . ": " . $user_new_pw . Mail::EOL . Mail::EOL . I18N::translate('After you have logged in, select the “My account” link under the “My page” menu and fill in the password fields to change your password.') . Mail::EOL . Mail::EOL . '<a href="' . WT_BASE_URL . 'login.php?ged=' . $WT_TREE->getNameUrl() . '">' . WT_BASE_URL . 'login.php?ged=' . $WT_TREE->getNameUrl() . '</a>'); FlashMessages::addMessage(I18N::translate('A new password has been created and emailed to %s. You can change this password after you login.', Filter::escapeHtml($user_name)), 'success'); } else { FlashMessages::addMessage(I18N::translate('There is no account with the username or email “%s”.', Filter::escapeHtml($user_name)), 'danger'); }
/** * Generate the HTML content of this block. * * @param int $block_id * @param bool $template * @param string[] $cfg * * @return string */ public function getBlock($block_id, $template = true, $cfg = array()) { global $ctype, $WT_TREE; $block = $this->getBlockSetting($block_id, 'block', '1'); foreach (array('block') as $name) { if (array_key_exists($name, $cfg)) { ${$name} = $cfg[$name]; } } $messages = Database::prepare("SELECT message_id, sender, subject, body, UNIX_TIMESTAMP(created) AS created FROM `##message` WHERE user_id=? ORDER BY message_id DESC")->execute(array(Auth::id()))->fetchAll(); $count = count($messages); $id = $this->getName() . $block_id; $class = $this->getName() . '_block'; $title = I18N::plural('%s message', '%s messages', $count, I18N::number($count)); $users = array_filter(User::all(), function (User $user) { return $user->getUserId() !== Auth::id() && $user->getPreference('verified_by_admin') && $user->getPreference('contactmethod') !== 'none'; }); $content = '<form id="messageform" name="messageform" method="post" action="module.php?mod=user_messages&mod_action=delete" onsubmit="return confirm(\'' . I18N::translate('Are you sure you want to delete this message? It cannot be retrieved later.') . '\');">'; $content .= '<input type="hidden" name="ged" value="' . $ctype . '">'; $content .= '<input type="hidden" name="ctype" value="' . $WT_TREE->getNameHtml() . '">'; if ($users) { $content .= '<label for="touser">' . I18N::translate('Send a message') . '</label>'; $content .= '<select id="touser" name="touser">'; $content .= '<option value="">' . I18N::translate('<select>') . '</option>'; foreach ($users as $user) { $content .= sprintf('<option value="%1$s">%2$s - %1$s</option>', Filter::escapeHtml($user->getUserName()), Filter::escapeHtml($user->getRealName())); } $content .= '</select>'; $content .= '<input type="button" value="' . I18N::translate('Send') . '" onclick="return message(document.messageform.touser.options[document.messageform.touser.selectedIndex].value, \'messaging2\', \'\');"><br><br>'; } if ($messages) { $content .= '<table class="list_table"><tr>'; $content .= '<th class="list_label">' . I18N::translate('Delete') . '<br><a href="#" onclick="jQuery(\'#' . $this->getName() . $block_id . ' :checkbox\').prop(\'checked\', true); return false;">' . I18N::translate('All') . '</a></th>'; $content .= '<th class="list_label">' . I18N::translate('Subject') . '</th>'; $content .= '<th class="list_label">' . I18N::translate('Date sent') . '</th>'; $content .= '<th class="list_label">' . I18N::translate('Email address') . '</th>'; $content .= '</tr>'; foreach ($messages as $message) { $content .= '<tr>'; $content .= '<td class="list_value_wrap"><input type="checkbox" name="message_id[]" value="' . $message->message_id . '" id="cb_message' . $message->message_id . '"></td>'; $content .= '<td class="list_value_wrap"><a href="#" onclick="return expand_layer(\'message' . $message->message_id . '\');"><i id="message' . $message->message_id . '_img" class="icon-plus"></i> <b dir="auto">' . Filter::escapeHtml($message->subject) . '</b></a></td>'; $content .= '<td class="list_value_wrap">' . FunctionsDate::formatTimestamp($message->created + WT_TIMESTAMP_OFFSET) . '</td>'; $content .= '<td class="list_value_wrap">'; $user = User::findByIdentifier($message->sender); if ($user) { $content .= $user->getRealNameHtml(); $content .= ' - <span dir="auto">' . $user->getEmail() . '</span>'; } else { $content .= '<a href="mailto:' . Filter::escapeHtml($message->sender) . '">' . Filter::escapeHtml($message->sender) . '</a>'; } $content .= '</td>'; $content .= '</tr>'; $content .= '<tr><td class="list_value_wrap" colspan="4"><div id="message' . $message->message_id . '" style="display:none;">'; $content .= '<div dir="auto" style="white-space: pre-wrap;">' . Filter::expandUrls($message->body) . '</div><br>'; if (strpos($message->subject, I18N::translate('RE: ')) !== 0) { $message->subject = I18N::translate('RE: ') . $message->subject; } if ($user) { $content .= '<button type="button" onclick="reply(\'' . Filter::escapeJs($message->sender) . '\', \'' . Filter::escapeJs($message->subject) . '\'); return false;">' . I18N::translate('Reply') . '</button> '; } $content .= '<button type="button" onclick="if (confirm(\'' . I18N::translate('Are you sure you want to delete this message? It cannot be retrieved later.') . '\')) {jQuery(\'#messageform :checkbox\').prop(\'checked\', false); jQuery(\'#cb_message' . $message->message_id . '\').prop(\'checked\', true); document.messageform.submit();}">' . I18N::translate('Delete') . '</button></div></td></tr>'; } $content .= '</table>'; $content .= '<p><button type="submit">' . I18N::translate('Delete selected messages') . '</button></p>'; } $content .= '</form>'; if ($template) { if ($block) { $class .= ' small_inner_block'; } return Theme::theme()->formatBlock($id, $title, $class, $content); } else { return $content; } }
/** * Add a message to a user's inbox * * @param string[] $message * * @return bool */ function addMessage($message) { global $WT_TREE; $success = true; $sender = User::findByIdentifier($message['from']); $recipient = User::findByIdentifier($message['to']); // Sender may not be a webtrees user if ($sender) { $sender_email = $sender->getEmail(); $sender_real_name = $sender->getRealName(); } else { $sender_email = $message['from']; $sender_real_name = $message['from_name']; } // Send a copy of the copy message back to the sender. if ($message['method'] !== 'messaging') { // Switch to the sender’s language. if ($sender) { I18N::init($sender->getPreference('language')); } $copy_email = $message['body']; if (!empty($message['url'])) { $copy_email .= Mail::EOL . Mail::EOL . '--------------------------------------' . Mail::EOL . I18N::translate('This message was sent while viewing the following URL: ') . $message['url'] . Mail::EOL; } if ($sender) { // Message from a logged-in user $copy_email = I18N::translate('You sent the following message to a webtrees user:'******' ' . $recipient->getRealNameHtml() . Mail::EOL . Mail::EOL . $copy_email; } else { // Message from a visitor $copy_email = I18N::translate('You sent the following message to a webtrees administrator:') . Mail::EOL . Mail::EOL . Mail::EOL . $copy_email; } $success = $success && Mail::send($WT_TREE, $sender_email, $sender_real_name, Site::getPreference('SMTP_FROM_NAME'), $WT_TREE->getPreference('title'), I18N::translate('webtrees message') . ' - ' . $message['subject'], $copy_email); } // Switch to the recipient’s language. I18N::init($recipient->getPreference('language')); if (isset($message['from_name'])) { $message['body'] = I18N::translate('Your name') . ' ' . $message['from_name'] . Mail::EOL . I18N::translate('Email address') . ' ' . $message['from_email'] . Mail::EOL . Mail::EOL . $message['body']; } // Add another footer - unless we are an admin if (!Auth::isAdmin()) { if (!empty($message['url'])) { $message['body'] .= Mail::EOL . Mail::EOL . '--------------------------------------' . Mail::EOL . I18N::translate('This message was sent while viewing the following URL: ') . $message['url'] . Mail::EOL; } } if (empty($message['created'])) { $message['created'] = gmdate("D, d M Y H:i:s T"); } if ($message['method'] !== 'messaging3' && $message['method'] !== 'mailto' && $message['method'] !== 'none') { Database::prepare("INSERT INTO `##message` (sender, ip_address, user_id, subject, body) VALUES (? ,? ,? ,? ,?)")->execute(array($message['from'], WT_CLIENT_IP, $recipient->getUserId(), $message['subject'], str_replace('<br>', '', $message['body']))); } if ($message['method'] !== 'messaging') { if ($sender) { $original_email = I18N::translate('The following message has been sent to your webtrees user account from '); $original_email .= $sender->getRealNameHtml(); } else { $original_email = I18N::translate('The following message has been sent to your webtrees user account from '); if (!empty($message['from_name'])) { $original_email .= $message['from_name']; } else { $original_email .= $message['from']; } } $original_email .= Mail::EOL . Mail::EOL . $message['body']; $success = $success && Mail::send($WT_TREE, $recipient->getEmail(), $recipient->getRealName(), $sender_email, $sender_real_name, I18N::translate('webtrees message') . ' - ' . $message['subject'], $original_email); } I18N::init(WT_LOCALE); // restore language settings if needed return $success; }
$pass2 = Filter::post('pass2', WT_REGEX_PASSWORD); $theme = Filter::post('theme', implode('|', array_keys(Theme::installedThemes())), ''); $language = Filter::post('language'); $timezone = Filter::post('timezone'); $contact_method = Filter::post('contact_method'); $comment = Filter::post('comment'); $auto_accept = Filter::postBool('auto_accept'); $canadmin = Filter::postBool('canadmin'); $visible_online = Filter::postBool('visible_online'); $verified = Filter::postBool('verified'); $approved = Filter::postBool('approved'); if ($user_id === 0) { // Create a new user if (User::findByIdentifier($username)) { FlashMessages::addMessage(I18N::translate('Duplicate user name. A user with that user name already exists. Please choose another user name.')); } elseif (User::findByIdentifier($email)) { FlashMessages::addMessage(I18N::translate('Duplicate email address. A user with that email already exists.')); } elseif ($pass1 !== $pass2) { FlashMessages::addMessage(I18N::translate('Passwords do not match.')); } else { $user = User::create($username, $real_name, $email, $pass1); $user->setPreference('reg_timestamp', date('U'))->setPreference('sessiontime', '0'); Log::addAuthenticationLog('User ->' . $username . '<- created'); } } else { $user = User::find($user_id); if ($user && $username && $real_name) { $user->setEmail($email); $user->setUserName($username); $user->setRealName($real_name); if ($pass1 !== null && $pass1 === $pass2) {
case 'themes/simplyblue/': case 'themes/simplygreen/': case 'themes/simplyred/': $stmt_gedcom_setting->execute(array($GED_DATA['id'], 'THEME_DIR', 'colors')); break; case 'themes/xenea/': $stmt_gedcom_setting->execute(array($GED_DATA['id'], 'THEME_DIR', 'xenea')); break; default: $stmt_gedcom_setting->execute(array($GED_DATA['id'], 'THEME_DIR', 'webtrees')); break; } $stmt_gedcom_setting->execute(array($GED_DATA['id'], 'THUMBNAIL_WIDTH', $THUMBNAIL_WIDTH)); $stmt_gedcom_setting->execute(array($GED_DATA['id'], 'USE_RELATIONSHIP_PRIVACY', $USE_RELATIONSHIP_PRIVACY)); $stmt_gedcom_setting->execute(array($GED_DATA['id'], 'WATERMARK_THUMB', $WATERMARK_THUMB)); $user = User::findByIdentifier($WEBMASTER_EMAIL); if ($user) { $stmt_gedcom_setting->execute(array($GED_DATA['id'], 'WEBMASTER_USER_ID', $user->getUserId())); } $stmt_gedcom_setting->execute(array($GED_DATA['id'], 'WORD_WRAPPED_NOTES', $WORD_WRAPPED_NOTES)); } Database::prepare("DELETE FROM `##gedcom_setting` WHERE setting_name IN ('config', 'privacy', 'path', 'pgv_ver', 'imported')")->execute(); // webtrees 1.0.5 combines user and gedcom settings for relationship privacy // into a combined user-gedcom setting, for more granular control Database::exec("INSERT IGNORE INTO `##user_gedcom_setting` (user_id, gedcom_id, setting_name, setting_value)" . " SELECT u.user_id, g.gedcom_id, 'RELATIONSHIP_PATH_LENGTH', LEAST(us1.setting_value, gs1.setting_value)" . " FROM `##user` u" . " CROSS JOIN `##gedcom` g" . " LEFT JOIN `##user_setting` us1 ON (u.user_id =us1.user_id AND us1.setting_name='max_relation_path')" . " LEFT JOIN `##user_setting` us2 ON (u.user_id =us2.user_id AND us2.setting_name='relationship_privacy')" . " LEFT JOIN `##gedcom_setting` gs1 ON (g.gedcom_id=gs1.gedcom_id AND gs1.setting_name='MAX_RELATION_PATH_LENGTH')" . " LEFT JOIN `##gedcom_setting` gs2 ON (g.gedcom_id=gs2.gedcom_id AND gs2.setting_name='USE_RELATIONSHIP_PRIVACY')" . " WHERE us2.setting_value AND gs2.setting_value"); Database::exec("DELETE FROM `##gedcom_setting` WHERE setting_name IN ('MAX_RELATION_PATH_LENGTH', 'USE_RELATIONSHIP_PRIVACY')"); Database::exec("DELETE FROM `##user_setting` WHERE setting_name IN ('relationship_privacy', 'max_relation_path_length')"); //////////////////////////////////////////////////////////////////////////////// // The PhpGedView blocks don't migrate easily. // Just give everybody and every tree default blocks ////////////////////////////////////////////////////////////////////////////////
case 'themes/simplygreen/': case 'themes/simplyred/': $stmt_gedcom_setting->execute(array($GED_DATA['id'], 'THEME_DIR', 'colors')); break; case 'themes/xenea/': $stmt_gedcom_setting->execute(array($GED_DATA['id'], 'THEME_DIR', 'xenea')); break; default: $stmt_gedcom_setting->execute(array($GED_DATA['id'], 'THEME_DIR', 'webtrees')); break; } $stmt_gedcom_setting->execute(array($GED_DATA['id'], 'THUMBNAIL_WIDTH', $THUMBNAIL_WIDTH)); $stmt_gedcom_setting->execute(array($GED_DATA['id'], 'USE_RELATIONSHIP_PRIVACY', $USE_RELATIONSHIP_PRIVACY)); $stmt_gedcom_setting->execute(array($GED_DATA['id'], 'USE_RIN', $USE_RIN)); $stmt_gedcom_setting->execute(array($GED_DATA['id'], 'WATERMARK_THUMB', $WATERMARK_THUMB)); $stmt_gedcom_setting->execute(array($GED_DATA['id'], 'WEBMASTER_USER_ID', User::findByIdentifier($WEBMASTER_EMAIL)->getUserId())); $stmt_gedcom_setting->execute(array($GED_DATA['id'], 'WORD_WRAPPED_NOTES', $WORD_WRAPPED_NOTES)); } Database::prepare("DELETE FROM `##gedcom_setting` WHERE setting_name IN ('config', 'privacy', 'path', 'pgv_ver', 'imported')")->execute(); // webtrees 1.0.5 combines user and gedcom settings for relationship privacy // into a combined user-gedcom setting, for more granular control Database::exec("INSERT IGNORE INTO `##user_gedcom_setting` (user_id, gedcom_id, setting_name, setting_value)" . " SELECT u.user_id, g.gedcom_id, 'RELATIONSHIP_PATH_LENGTH', LEAST(us1.setting_value, gs1.setting_value)" . " FROM `##user` u" . " CROSS JOIN `##gedcom` g" . " LEFT JOIN `##user_setting` us1 ON (u.user_id =us1.user_id AND us1.setting_name='max_relation_path')" . " LEFT JOIN `##user_setting` us2 ON (u.user_id =us2.user_id AND us2.setting_name='relationship_privacy')" . " LEFT JOIN `##gedcom_setting` gs1 ON (g.gedcom_id=gs1.gedcom_id AND gs1.setting_name='MAX_RELATION_PATH_LENGTH')" . " LEFT JOIN `##gedcom_setting` gs2 ON (g.gedcom_id=gs2.gedcom_id AND gs2.setting_name='USE_RELATIONSHIP_PRIVACY')" . " WHERE us2.setting_value AND gs2.setting_value"); Database::exec("DELETE FROM `##gedcom_setting` WHERE setting_name IN ('MAX_RELATION_PATH_LENGTH', 'USE_RELATIONSHIP_PRIVACY')"); Database::exec("DELETE FROM `##user_setting` WHERE setting_name IN ('relationship_privacy', 'max_relation_path_length')"); //////////////////////////////////////////////////////////////////////////////// // The PhpGedView blocks don't migrate easily. // Just give everybody and every tree default blocks //////////////////////////////////////////////////////////////////////////////// Database::prepare("INSERT INTO `##block` (user_id, location, block_order, module_name)" . " SELECT `##user`.user_id, location, block_order, module_name" . " FROM `##block`" . " JOIN `##user`" . " WHERE `##block`.user_id = -1" . " AND `##user`.user_id > 0")->execute(); Database::prepare("INSERT INTO `##block` (gedcom_id, location, block_order, module_name)" . " SELECT `##gedcom`.gedcom_id, location, block_order, module_name" . " FROM `##block`" . " JOIN `##gedcom`" . " WHERE `##block`.gedcom_id = -1" . " AND `##gedcom`.gedcom_id > 0")->execute(); ////////////////////////////////////////////////////////////////////////////////
echo '<input type="hidden" name="wtname" value="', Filter::escapeHtml($_POST['wtname']), '">'; echo '<input type="hidden" name="wtuser" value="', Filter::escapeHtml($_POST['wtuser']), '">'; echo '<input type="hidden" name="wtpass" value="', Filter::escapeHtml($_POST['wtpass']), '">'; echo '<input type="hidden" name="wtpass2" value="', Filter::escapeHtml($_POST['wtpass2']), '">'; echo '<input type="hidden" name="wtemail" value="', Filter::escapeHtml($_POST['wtemail']), '">'; } //////////////////////////////////////////////////////////////////////////////// // Step six We have a database connection and a writable folder. Do it! //////////////////////////////////////////////////////////////////////////////// try { // Create/update the database tables. Database::updateSchema('\\Fisharebest\\Webtrees\\Schema', 'WT_SCHEMA_VERSION', 30); // If we are re-installing, then this user may already exist. $admin = User::findByIdentifier($_POST['wtemail']); if ($admin === null) { $admin = User::findByIdentifier($_POST['wtuser']); } // Create the user if ($admin === null) { $admin = User::create($_POST['wtuser'], $_POST['wtname'], $_POST['wtemail'], $_POST['wtpass'])->setPreference('language', WT_LOCALE)->setPreference('visibleonline', '1'); } else { $admin->setPassword($_POST['wtpass']); } // Make the user an administrator $admin->setPreference('canadmin', '1')->setPreference('verified', '1')->setPreference('verified_by_admin', '1'); // Write the config file. We already checked that this would work. $config_ini_php = '; <' . '?php exit; ?' . '> DO NOT DELETE THIS LINE' . PHP_EOL . 'dbhost="' . addcslashes($_POST['dbhost'], '"') . '"' . PHP_EOL . 'dbport="' . addcslashes($_POST['dbport'], '"') . '"' . PHP_EOL . 'dbuser="******"') . '"' . PHP_EOL . 'dbpass="******"') . '"' . PHP_EOL . 'dbname="' . addcslashes($_POST['dbname'], '"') . '"' . PHP_EOL . 'tblpfx="' . addcslashes($_POST['tblpfx'], '"') . '"' . PHP_EOL; file_put_contents(WT_DATA_DIR . 'config.ini.php', $config_ini_php); // Done - start using webtrees! echo '<script>document.location=document.location;</script>'; echo '</form></body></html>';