/** * Create resources for the colors theme. */ public function hookAfterInit() { $this->palettes = array('aquamarine' => I18N::translate('Aqua Marine'), 'ash' => I18N::translate('Ash'), 'belgianchocolate' => I18N::translate('Belgian Chocolate'), 'bluelagoon' => I18N::translate('Blue Lagoon'), 'bluemarine' => I18N::translate('Blue Marine'), 'coffeeandcream' => I18N::translate('Coffee and Cream'), 'coldday' => I18N::translate('Cold Day'), 'greenbeam' => I18N::translate('Green Beam'), 'mediterranio' => I18N::translate('Mediterranio'), 'mercury' => I18N::translate('Mercury'), 'nocturnal' => I18N::translate('Nocturnal'), 'olivia' => I18N::translate('Olivia'), 'pinkplastic' => I18N::translate('Pink Plastic'), 'sage' => I18N::translate('Sage'), 'shinytomato' => I18N::translate('Shiny Tomato'), 'tealtop' => I18N::translate('Teal Top')); uasort($this->palettes, '\\Fisharebest\\Webtrees\\I18N::strcasecmp'); // If we've selected a new palette, and we are logged in, set this value as a default. if (isset($_GET['themecolor']) && array_key_exists($_GET['themecolor'], $this->palettes)) { // Request to change color $this->palette = $_GET['themecolor']; Auth::user()->setPreference('themecolor', $this->palette); if (Auth::isAdmin()) { Site::setPreference('DEFAULT_COLOR_PALETTE', $this->palette); } unset($_GET['themecolor']); // Rember that we have selected a value Session::put('subColor', $this->palette); } // If we are logged in, use our preference $this->palette = Auth::user()->getPreference('themecolor'); // If not logged in or no preference, use one we selected earlier in the session? if (!$this->palette) { $this->palette = Session::get('subColor'); } // We haven't selected one this session? Use the site default if (!$this->palette) { $this->palette = Site::getPreference('DEFAULT_COLOR_PALETTE'); } // Make sure our selected palette actually exists if (!array_key_exists($this->palette, $this->palettes)) { $this->palette = 'ash'; } }
/** * Print a new fact box on details pages * * @param string $id the id of the person, family, source etc the fact will be added to * @param array $usedfacts an array of facts already used in this record * @param string $type the type of record INDI, FAM, SOUR etc */ public static function printAddNewFact($id, $usedfacts, $type) { global $WT_TREE; // -- Add from clipboard if (is_array(Session::get('clipboard'))) { $newRow = true; foreach (array_reverse(Session::get('clipboard'), true) as $fact_id => $fact) { if ($fact["type"] == $type || $fact["type"] == 'all') { if ($newRow) { $newRow = false; echo '<tr><td class="descriptionbox">'; echo I18N::translate('Add from clipboard'), '</td>'; echo '<td class="optionbox wrap"><form method="get" name="newFromClipboard" action="?" onsubmit="return false;">'; echo '<select id="newClipboardFact">'; } echo '<option value="', Filter::escapeHtml($fact_id), '">', GedcomTag::getLabel($fact['fact']); // TODO use the event class to store/parse the clipboard events if (preg_match('/^2 DATE (.+)/m', $fact['factrec'], $match)) { $tmp = new Date($match[1]); echo '; ', $tmp->minimumDate()->format('%Y'); } if (preg_match('/^2 PLAC ([^,\\n]+)/m', $fact['factrec'], $match)) { echo '; ', $match[1]; } echo '</option>'; } } if (!$newRow) { echo '</select>'; echo ' <input type="button" value="', I18N::translate('Add'), "\" onclick=\"return paste_fact('{$id}', '#newClipboardFact');\"> "; echo '</form></td></tr>', "\n"; } } // -- Add from pick list switch ($type) { case "INDI": $addfacts = preg_split("/[, ;:]+/", $WT_TREE->getPreference('INDI_FACTS_ADD'), -1, PREG_SPLIT_NO_EMPTY); $uniquefacts = preg_split("/[, ;:]+/", $WT_TREE->getPreference('INDI_FACTS_UNIQUE'), -1, PREG_SPLIT_NO_EMPTY); $quickfacts = preg_split("/[, ;:]+/", $WT_TREE->getPreference('INDI_FACTS_QUICK'), -1, PREG_SPLIT_NO_EMPTY); break; case "FAM": $addfacts = preg_split("/[, ;:]+/", $WT_TREE->getPreference('FAM_FACTS_ADD'), -1, PREG_SPLIT_NO_EMPTY); $uniquefacts = preg_split("/[, ;:]+/", $WT_TREE->getPreference('FAM_FACTS_UNIQUE'), -1, PREG_SPLIT_NO_EMPTY); $quickfacts = preg_split("/[, ;:]+/", $WT_TREE->getPreference('FAM_FACTS_QUICK'), -1, PREG_SPLIT_NO_EMPTY); break; case "SOUR": $addfacts = preg_split("/[, ;:]+/", $WT_TREE->getPreference('SOUR_FACTS_ADD'), -1, PREG_SPLIT_NO_EMPTY); $uniquefacts = preg_split("/[, ;:]+/", $WT_TREE->getPreference('SOUR_FACTS_UNIQUE'), -1, PREG_SPLIT_NO_EMPTY); $quickfacts = preg_split("/[, ;:]+/", $WT_TREE->getPreference('SOUR_FACTS_QUICK'), -1, PREG_SPLIT_NO_EMPTY); break; case "NOTE": $addfacts = preg_split("/[, ;:]+/", $WT_TREE->getPreference('NOTE_FACTS_ADD'), -1, PREG_SPLIT_NO_EMPTY); $uniquefacts = preg_split("/[, ;:]+/", $WT_TREE->getPreference('NOTE_FACTS_UNIQUE'), -1, PREG_SPLIT_NO_EMPTY); $quickfacts = preg_split("/[, ;:]+/", $WT_TREE->getPreference('NOTE_FACTS_QUICK'), -1, PREG_SPLIT_NO_EMPTY); break; case "REPO": $addfacts = preg_split("/[, ;:]+/", $WT_TREE->getPreference('REPO_FACTS_ADD'), -1, PREG_SPLIT_NO_EMPTY); $uniquefacts = preg_split("/[, ;:]+/", $WT_TREE->getPreference('REPO_FACTS_UNIQUE'), -1, PREG_SPLIT_NO_EMPTY); $quickfacts = preg_split("/[, ;:]+/", $WT_TREE->getPreference('REPO_FACTS_QUICK'), -1, PREG_SPLIT_NO_EMPTY); break; default: return; } $addfacts = array_merge(self::checkFactUnique($uniquefacts, $usedfacts, $type), $addfacts); $quickfacts = array_intersect($quickfacts, $addfacts); $translated_addfacts = array(); foreach ($addfacts as $addfact) { $translated_addfacts[$addfact] = GedcomTag::getLabel($addfact); } uasort($translated_addfacts, function ($x, $y) { return I18N::strcasecmp(I18N::translate($x), I18N::translate($y)); }); echo '<tr><td class="descriptionbox">'; echo I18N::translate('Fact or event'); echo '</td>'; echo '<td class="optionbox wrap">'; echo '<form method="get" name="newfactform" action="?" onsubmit="return false;">'; echo '<select id="newfact" name="newfact">'; echo '<option value="" disabled selected>' . I18N::translate('<select>') . '</option>'; foreach ($translated_addfacts as $fact => $fact_name) { echo '<option value="', $fact, '">', $fact_name, '</option>'; } if ($type == 'INDI' || $type == 'FAM') { echo '<option value="FACT">', I18N::translate('Custom fact'), '</option>'; echo '<option value="EVEN">', I18N::translate('Custom event'), '</option>'; } echo '</select>'; echo '<input type="button" value="', I18N::translate('Add'), '" onclick="add_record(\'' . $id . '\', \'newfact\');">'; echo '<span class="quickfacts">'; foreach ($quickfacts as $fact) { echo '<a href="#" onclick="add_new_record(\'' . $id . '\', \'' . $fact . '\');return false;">', GedcomTag::getLabel($fact), '</a>'; } echo '</span></form>'; echo '</td></tr>'; }
/** * Startup activity */ public function __construct() { global $WT_TREE; parent::__construct(); $this->setPageTitle(I18N::translate('Lifespans')); $this->facts = explode('|', WT_EVENTS_BIRT . '|' . WT_EVENTS_DEAT . '|' . WT_EVENTS_MARR . '|' . WT_EVENTS_DIV); $tmp = explode('\\', get_class(I18N::defaultCalendar())); $cal = strtolower(array_pop($tmp)); $this->defaultCalendar = str_replace('calendar', '', $cal); $filterPids = false; // Request parameters $clear = Filter::getBool('clear'); $newpid = Filter::get('newpid', WT_REGEX_XREF); $addfam = Filter::getBool('addFamily'); $this->place = Filter::get('place'); $this->beginYear = Filter::getInteger('beginYear', 0, PHP_INT_MAX, null); $this->endYear = Filter::getInteger('endYear', 0, PHP_INT_MAX, null); $this->calendar = Filter::get('calendar', null, $this->defaultCalendar); $this->strictDate = Filter::getBool('strictDate'); // Set up base color parameters $this->colors['M'] = new ColorGenerator(240, self::SATURATION, self::LIGHTNESS, self::ALPHA, self::RANGE * -1); $this->colors['F'] = new ColorGenerator(00, self::SATURATION, self::LIGHTNESS, self::ALPHA, self::RANGE); // Build a list of people based on the input parameters if ($clear) { // Empty list & reset form $xrefs = array(); $this->place = null; $this->beginYear = null; $this->endYear = null; $this->calendar = $this->defaultCalendar; } elseif ($this->place) { // Get all individual & family records found for a place $this->place_obj = new Place($this->place, $WT_TREE); $xrefs = Database::prepare("SELECT DISTINCT `i_id` FROM `##placelinks`" . " JOIN `##individuals` ON `pl_gid`=`i_id` AND `pl_file`=`i_file`" . " WHERE `i_file`=:tree_id" . " AND `pl_p_id`=:place_id" . " UNION" . " SELECT DISTINCT `f_id` FROM `##placelinks`" . " JOIN `##families` ON `pl_gid`=`f_id` AND `pl_file`=`f_file`" . " WHERE `f_file`=:tree_id" . " AND `pl_p_id`=:place_id")->execute(array('tree_id' => $WT_TREE->getTreeId(), 'place_id' => $this->place_obj->getPlaceId()))->fetchOneColumn(); } else { // Modify an existing list of records $xrefs = Session::get(self::SESSION_DATA, array()); if ($newpid) { $xrefs = array_merge($xrefs, $this->addFamily(Individual::getInstance($newpid, $WT_TREE), $addfam)); $xrefs = array_unique($xrefs); } elseif (!$xrefs) { $xrefs = $this->addFamily($this->getSignificantIndividual(), false); } } $tmp = $this->getCalendarDate(unixtojd()); $this->currentYear = $tmp->today()->y; $tmp = strtoupper(strtr($this->calendar, array('jewish' => 'hebrew', 'french' => 'french r'))); $this->calendarEscape = sprintf('@#D%s@', $tmp); if ($xrefs) { // ensure date ranges are valid in preparation for filtering list if ($this->beginYear || $this->endYear) { $filterPids = true; if (!$this->beginYear) { $tmp = new Date($this->calendarEscape . ' 1'); $this->beginYear = $tmp->minimumDate()->y; } if (!$this->endYear) { $this->endYear = $this->currentYear; } $this->startDate = new Date($this->calendarEscape . $this->beginYear); $this->endDate = new Date($this->calendarEscape . $this->endYear); } // Test each xref to see if the search criteria are met foreach ($xrefs as $key => $xref) { $valid = false; $person = Individual::getInstance($xref, $WT_TREE); if ($person) { if ($person->canShow()) { foreach ($person->getFacts() as $fact) { if ($this->checkFact($fact)) { $this->people[] = $person; $valid = true; break; } } } } else { $family = Family::getInstance($xref, $WT_TREE); if ($family && $family->canShow() && $this->checkFact($family->getMarriage())) { $valid = true; $this->people[] = $family->getHusband(); $this->people[] = $family->getWife(); } } if (!$valid) { unset($xrefs[$key]); // no point in storing a xref if we can't use it } } Session::put(self::SESSION_DATA, $xrefs); } else { Session::forget(self::SESSION_DATA); } $this->people = array_filter(array_unique($this->people)); $count = count($this->people); if ($count) { // Build the subtitle if ($this->place && $filterPids) { $this->subtitle = I18N::plural('%s individual with events in %s between %s and %s', '%s individuals with events in %s between %s and %s', $count, I18N::number($count), $this->place, $this->startDate->display(false, '%Y'), $this->endDate->display(false, '%Y')); } elseif ($this->place) { $this->subtitle = I18N::plural('%s individual with events in %s', '%s individuals with events in %s', $count, I18N::number($count), $this->place); } elseif ($filterPids) { $this->subtitle = I18N::plural('%s individual with events between %s and %s', '%s individuals with events between %s and %s', $count, I18N::number($count), $this->startDate->display(false, '%Y'), $this->endDate->display(false, '%Y')); } else { $this->subtitle = I18N::plural('%s individual', '%s individuals', $count, I18N::number($count)); } // Sort the array in order of birth year usort($this->people, function (Individual $a, Individual $b) { return Date::compare($a->getEstimatedBirthDate(), $b->getEstimatedBirthDate()); }); //Find the mimimum birth year and maximum death year from the individuals in the array. $bdate = $this->getCalendarDate($this->people[0]->getEstimatedBirthDate()->minimumJulianDay()); $minyear = $bdate->y; $that = $this; // PHP5.3 cannot access $this inside a closure $maxyear = array_reduce($this->people, function ($carry, Individual $item) use($that) { $date = $that->getCalendarDate($item->getEstimatedDeathDate()->maximumJulianDay()); return max($carry, $date->y); }, 0); } elseif ($filterPids) { $minyear = $this->endYear; $maxyear = $this->endYear; } else { $minyear = $this->currentYear; $maxyear = $this->currentYear; } $maxyear = min($maxyear, $this->currentYear); // Limit maximum year to current year as we can't forecast the future $minyear = min($minyear, $maxyear - $WT_TREE->getPreference('MAX_ALIVE_AGE')); // Set default minimum chart length $this->timelineMinYear = (int) floor($minyear / 10) * 10; // round down to start of the decade $this->timelineMaxYear = (int) ceil($maxyear / 10) * 10; // round up to start of next decade }
while (count($clipboard) > 10) { array_shift($clipboard); } Session::put('clipboard', $clipboard); FlashMessages::addMessage(I18N::translate('The record has been copied to the clipboard.')); break 2; } } } break; case 'paste-fact': // Paste a fact from the clipboard $xref = Filter::post('xref', WT_REGEX_XREF); $fact_id = Filter::post('fact_id'); $record = GedcomRecord::getInstance($xref, $WT_TREE); $clipboard = Session::get('clipboard'); if ($record && $record->canEdit() && isset($clipboard[$fact_id])) { $record->createFact($clipboard[$fact_id]['factrec'], true); } break; case 'delete-fact': $xref = Filter::post('xref', WT_REGEX_XREF); $fact_id = Filter::post('fact_id'); $record = GedcomRecord::getInstance($xref, $WT_TREE); if ($record && $record->canShow() && $record->canEdit()) { foreach ($record->getFacts() as $fact) { if ($fact->getFactId() == $fact_id && $fact->canShow() && $fact->canEdit()) { $record->deleteFact($fact_id, true); break 2; } }
/** * A list for the side bar. * * @return string */ public function getCartList() { global $WT_TREE; $cart = Session::get('cart', array()); if (!array_key_exists($WT_TREE->getTreeId(), $cart)) { $cart[$WT_TREE->getTreeId()] = array(); } $pid = Filter::get('pid', WT_REGEX_XREF); if (!$cart[$WT_TREE->getTreeId()]) { $out = I18N::translate('Your clippings cart is empty.'); } else { $out = '<ul>'; foreach (array_keys($cart[$WT_TREE->getTreeId()]) as $xref) { $record = GedcomRecord::getInstance($xref, $WT_TREE); if ($record instanceof Individual || $record instanceof Family) { switch ($record::RECORD_TYPE) { case 'INDI': $icon = 'icon-indis'; break; case 'FAM': $icon = 'icon-sfamily'; break; } $out .= '<li>'; if (!empty($icon)) { $out .= '<i class="' . $icon . '"></i>'; } $out .= '<a href="' . $record->getHtmlUrl() . '">'; if ($record instanceof Individual) { $out .= $record->getSexImage(); } $out .= ' ' . $record->getFullName() . ' '; if ($record instanceof Individual && $record->canShow()) { $out .= ' (' . $record->getLifeSpan() . ')'; } $out .= '</a>'; $out .= '<a class="icon-remove remove_cart" href="module.php?mod=' . $this->getName() . '&mod_action=ajax&sb_action=clippings&remove=' . $xref . '&pid=' . $pid . '" title="' . I18N::translate('Remove') . '"></a>'; $out .= '</li>'; } } $out .= '</ul>'; } if ($cart[$WT_TREE->getTreeId()]) { $out .= '<br><a href="module.php?mod=' . $this->getName() . '&mod_action=ajax&sb_action=clippings&empty=true&pid=' . $pid . '" class="remove_cart">' . I18N::translate('Empty the clippings cart') . '</a>' . '<br>' . '<a href="module.php?mod=' . $this->getName() . '&mod_action=ajax&sb_action=clippings&download=true&pid=' . $pid . '" class="add_cart">' . I18N::translate('Download') . '</a>'; } $record = Individual::getInstance($pid, $WT_TREE); if ($record && !array_key_exists($record->getXref(), $cart[$WT_TREE->getTreeId()])) { $out .= '<br><a href="module.php?mod=' . $this->getName() . '&mod_action=ajax&sb_action=clippings&add=' . $pid . '&pid=' . $pid . '" class="add_cart"><i class="icon-clippings"></i> ' . I18N::translate('Add %s to the clippings cart', $record->getFullName()) . '</a>'; } return $out; }
Mail::systemMessage($WT_TREE, $user, I18N::translate('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'); } header('Location: ' . WT_BASE_URL . WT_SCRIPT_NAME); return; break; case 'register': if (!Site::getPreference('USE_REGISTRATION_MODULE')) { header('Location: ' . WT_BASE_URL); return; } $controller->setPageTitle(I18N::translate('Request new user account')); // The form parameters are mandatory, and the validation errors are shown in the client. if (Session::get('good_to_send') && $user_name && $user_password01 && $user_password01 == $user_password02 && $user_realname && $user_email && $user_comments) { // These validation errors cannot be shown in the client. if (User::findByUserName($user_name)) { FlashMessages::addMessage(I18N::translate('Duplicate user name. A user with that user name already exists. Please choose another user name.')); } elseif (User::findByEmail($user_email)) { FlashMessages::addMessage(I18N::translate('Duplicate email address. A user with that email already exists.')); } elseif (preg_match('/(?!' . preg_quote(WT_BASE_URL, '/') . ')(((?:ftp|http|https):\\/\\/)[a-zA-Z0-9.-]+)/', $user_comments, $match)) { FlashMessages::addMessage(I18N::translate('You are not allowed to send messages that contain external links.') . ' ' . I18N::translate('You should delete the “%1$s” from “%2$s” and try again.', $match[2], $match[1])); Log::addAuthenticationLog('Possible spam registration from "' . $user_name . '"/"' . $user_email . '" comments="' . $user_comments . '"'); } else { // Everything looks good - create the user $controller->pageHeader(); Log::addAuthenticationLog('User registration requested for: ' . $user_name); $user = User::create($user_name, $user_realname, $user_email, $user_password01); $user->setPreference('language', WT_LOCALE)->setPreference('verified', '0')->setPreference('verified_by_admin', 0)->setPreference('reg_timestamp', date('U'))->setPreference('reg_hashcode', md5(Uuid::uuid4()))->setPreference('contactmethod', 'messaging2')->setPreference('comment', $user_comments)->setPreference('visibleonline', '1')->setPreference('auto_accept', '0')->setPreference('canadmin', '0')->setPreference('sessiontime', '0'); // Generate an email in the admin’s language
// Do not allow anonymous visitors to include links to external sites if (preg_match('/(?!' . preg_quote(WT_BASE_URL, '/') . ')(((?:ftp|http|https):\\/\\/)[a-zA-Z0-9.-]+)/', $subject . $body, $match)) { $errors .= '<p class="ui-state-error">' . I18N::translate('You are not allowed to send messages that contain external links.') . '</p>' . '<p class="ui-state-highlight">' . I18N::translate('You should delete the “%1$s” from “%2$s” and try again.', $match[2], $match[1]) . '</p>' . Log::addAuthenticationLog('Possible spam message from "' . $from_name . '"/"' . $from_email . '", subject="' . $subject . '", body="' . $body . '"'); $action = 'compose'; } $from = $from_email; } // Ensure the user always visits this page twice - once to compose it and again to send it. // This makes it harder for spammers. switch ($action) { case 'compose': Session::put('good_to_send', true); break; case 'send': // Only send messages if we've come straight from the compose page. if (!Session::get('good_to_send')) { Log::addAuthenticationLog('Attempt to send a message without visiting the compose page. Spam attack?'); $action = 'compose'; } if (!Filter::checkCsrf()) { $action = 'compose'; } Session::forget('good_to_send'); break; } switch ($action) { case 'compose': $controller->pageHeader()->addInlineJavascript(' function checkForm(frm) { if (frm.subject.value === "") { alert("' . I18N::translate('Please enter a message subject.') . '");
/** * Initialise the translation adapter with a locale setting. * * @param string|null $code Use this locale/language code, or choose one automatically * * @return string $string */ public static function init($code = null) { global $WT_TREE; mb_internal_encoding('UTF-8'); if ($code !== null) { // Create the specified locale self::$locale = Locale::create($code); } else { // Negotiate a locale, but if we can't then use a failsafe self::$locale = new LocaleEnUs(); if (Session::has('locale')) { // Previously used self::$locale = Locale::create(Session::get('locale')); } else { // Browser negotiation $default_locale = new LocaleEnUs(); try { if ($WT_TREE) { $default_locale = Locale::create($WT_TREE->getPreference('LANGUAGE')); } } catch (\Exception $ex) { } self::$locale = Locale::httpAcceptLanguage($_SERVER, self::installedLocales(), $default_locale); } } $cache_dir_exists = File::mkdir(WT_DATA_DIR . 'cache'); $cache_file = WT_DATA_DIR . 'cache/language-' . self::$locale->languageTag() . '-cache.php'; if (file_exists($cache_file)) { $filemtime = filemtime($cache_file); } else { $filemtime = 0; } // Load the translation file(s) // Note that glob() returns false instead of an empty array when open_basedir_restriction // is in force and no files are found. See PHP bug #47358. if (defined('GLOB_BRACE')) { $translation_files = array_merge(array(WT_ROOT . 'language/' . self::$locale->languageTag() . '.mo'), glob(WT_MODULES_DIR . '*/language/' . self::$locale->languageTag() . '.{csv,php,mo}', GLOB_BRACE) ?: array(), glob(WT_DATA_DIR . 'language/' . self::$locale->languageTag() . '.{csv,php,mo}', GLOB_BRACE) ?: array()); } else { // Some servers do not have GLOB_BRACE - see http://php.net/manual/en/function.glob.php $translation_files = array_merge(array(WT_ROOT . 'language/' . self::$locale->languageTag() . '.mo'), glob(WT_MODULES_DIR . '*/language/' . self::$locale->languageTag() . '.csv') ?: array(), glob(WT_MODULES_DIR . '*/language/' . self::$locale->languageTag() . '.php') ?: array(), glob(WT_MODULES_DIR . '*/language/' . self::$locale->languageTag() . '.mo') ?: array(), glob(WT_DATA_DIR . 'language/' . self::$locale->languageTag() . '.csv') ?: array(), glob(WT_DATA_DIR . 'language/' . self::$locale->languageTag() . '.php') ?: array(), glob(WT_DATA_DIR . 'language/' . self::$locale->languageTag() . '.mo') ?: array()); } // Rebuild files after one hour $rebuild_cache = time() > $filemtime + 3600; // Rebuild files if any translation file has been updated foreach ($translation_files as $translation_file) { if (filemtime($translation_file) > $filemtime) { $rebuild_cache = true; break; } } if ($rebuild_cache) { $translations = array(); foreach ($translation_files as $translation_file) { $translation = new Translation($translation_file); $translations = array_merge($translations, $translation->asArray()); } if ($cache_dir_exists) { // During setup, we may not have been able to create it. file_put_contents($cache_file, '<' . '?php return ' . var_export($translations, true) . ';'); } } else { $translations = (include $cache_file); } // Create a translator self::$translator = new Translator($translations, self::$locale->pluralRule()); // Alphabetic sorting sequence (upper-case letters), used by webtrees to sort strings list(, self::$alphabet_upper) = explode('=', self::$translator->translate('ALPHABET_upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ')); // Alphabetic sorting sequence (lower-case letters), used by webtrees to sort strings list(, self::$alphabet_lower) = explode('=', self::$translator->translate('ALPHABET_lower=abcdefghijklmnopqrstuvwxyz')); self::$list_separator = self::translate(', '); return self::$locale->languageTag(); }
} exit; } } // Update the last-login time no more than once a minute if (WT_TIMESTAMP - Session::get('activity_time') >= 60) { Auth::user()->setPreference('sessiontime', WT_TIMESTAMP); Session::put('activity_time', WT_TIMESTAMP); } // Set the theme if (substr(WT_SCRIPT_NAME, 0, 5) === 'admin' || WT_SCRIPT_NAME === 'module.php' && substr(Filter::get('mod_action'), 0, 5) === 'admin') { // Administration scripts begin with “admin” and use a special administration theme Theme::theme(new AdministrationTheme())->init($WT_TREE); } else { // Last theme used? $theme_id = Session::get('theme_id'); // Default for tree if (!array_key_exists($theme_id, Theme::themeNames()) && $WT_TREE) { $theme_id = $WT_TREE->getPreference('THEME_DIR'); } // Default for site if (!array_key_exists($theme_id, Theme::themeNames())) { $theme_id = Site::getPreference('THEME_DIR'); } // Default if (!array_key_exists($theme_id, Theme::themeNames())) { $theme_id = 'webtrees'; } foreach (Theme::installedThemes() as $theme) { if ($theme->themeId() === $theme_id) { Theme::theme($theme)->init($WT_TREE);
/** * Cross-Site Request Forgery tokens - ensure that the user is submitting * a form that was generated by the current session. * * @return string */ public static function getCsrfToken() { if (!Session::has('CSRF_TOKEN')) { $charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcedfghijklmnopqrstuvwxyz0123456789'; $csrf_token = ''; for ($n = 0; $n < 32; ++$n) { $csrf_token .= substr($charset, mt_rand(0, 61), 1); } Session::put('CSRF_TOKEN', $csrf_token); } return Session::get('CSRF_TOKEN'); }
/** * Create the clippings controller */ public function __construct() { global $WT_TREE; // Our cart is an array of items in the session $this->cart = Session::get('cart', array()); if (!array_key_exists($WT_TREE->getTreeId(), $this->cart)) { $this->cart[$WT_TREE->getTreeId()] = array(); } $this->action = Filter::get('action'); $this->id = Filter::get('id'); $convert = Filter::get('convert', 'yes|no', 'no'); $this->Zip = Filter::get('Zip'); $this->IncludeMedia = Filter::get('IncludeMedia'); $this->conv_path = Filter::get('conv_path'); $this->privatize_export = Filter::get('privatize_export', 'none|visitor|user|gedadmin', 'visitor'); $this->level1 = Filter::getInteger('level1'); $this->level2 = Filter::getInteger('level2'); $this->level3 = Filter::getInteger('level3'); $others = Filter::get('others'); $this->type = Filter::get('type'); if (($this->privatize_export === 'none' || $this->privatize_export === 'none') && !Auth::isManager($WT_TREE)) { $this->privatize_export = 'visitor'; } if ($this->privatize_export === 'user' && !Auth::isMember($WT_TREE)) { $this->privatize_export = 'visitor'; } if ($this->action === 'add') { if (empty($this->type) && !empty($this->id)) { $obj = GedcomRecord::getInstance($this->id, $WT_TREE); if ($obj) { $this->type = $obj::RECORD_TYPE; } else { $this->type = ''; $this->id = ''; $this->action = ''; } } elseif (empty($this->id)) { $this->action = ''; } if (!empty($this->id) && $this->type !== 'FAM' && $this->type !== 'INDI' && $this->type !== 'SOUR') { $this->action = 'add1'; } } if ($this->action === 'add1') { $obj = GedcomRecord::getInstance($this->id, $WT_TREE); $this->addClipping($obj); if ($this->type === 'SOUR') { if ($others === 'linked') { foreach ($obj->linkedIndividuals('SOUR') as $indi) { $this->addClipping($indi); } foreach ($obj->linkedFamilies('SOUR') as $fam) { $this->addClipping($fam); } } } if ($this->type === 'FAM') { if ($others === 'parents') { $this->addClipping($obj->getHusband()); $this->addClipping($obj->getWife()); } elseif ($others === "members") { $this->addFamilyMembers(Family::getInstance($this->id, $WT_TREE)); } elseif ($others === "descendants") { $this->addFamilyDescendancy(Family::getInstance($this->id, $WT_TREE)); } } elseif ($this->type === 'INDI') { if ($others === 'parents') { foreach (Individual::getInstance($this->id, $WT_TREE)->getChildFamilies() as $family) { $this->addFamilyMembers($family); } } elseif ($others === 'ancestors') { $this->addAncestorsToCart(Individual::getInstance($this->id, $WT_TREE), $this->level1); } elseif ($others === 'ancestorsfamilies') { $this->addAncestorsToCartFamilies(Individual::getInstance($this->id, $WT_TREE), $this->level2); } elseif ($others === 'members') { foreach (Individual::getInstance($this->id, $WT_TREE)->getSpouseFamilies() as $family) { $this->addFamilyMembers($family); } } elseif ($others === 'descendants') { foreach (Individual::getInstance($this->id, $WT_TREE)->getSpouseFamilies() as $family) { $this->addClipping($family); $this->addFamilyDescendancy($family, $this->level3); } } uksort($this->cart[$WT_TREE->getTreeId()], array($this, 'compareClippings')); } } elseif ($this->action === 'remove') { unset($this->cart[$WT_TREE->getTreeId()][$this->id]); } elseif ($this->action === 'empty') { $this->cart[$WT_TREE->getTreeId()] = array(); } elseif ($this->action === 'download') { $media = array(); $mediacount = 0; $filetext = FunctionsExport::gedcomHeader($WT_TREE); // Include SUBM/SUBN records, if they exist $subn = Database::prepare("SELECT o_gedcom FROM `##other` WHERE o_type=? AND o_file=?")->execute(array('SUBN', $WT_TREE->getTreeId()))->fetchOne(); if ($subn) { $filetext .= $subn . "\n"; } $subm = Database::prepare("SELECT o_gedcom FROM `##other` WHERE o_type=? AND o_file=?")->execute(array('SUBM', $WT_TREE->getTreeId()))->fetchOne(); if ($subm) { $filetext .= $subm . "\n"; } if ($convert === "yes") { $filetext = str_replace("UTF-8", "ANSI", $filetext); $filetext = utf8_decode($filetext); } switch ($this->privatize_export) { case 'gedadmin': $access_level = Auth::PRIV_NONE; break; case 'user': $access_level = Auth::PRIV_USER; break; case 'visitor': $access_level = Auth::PRIV_PRIVATE; break; case 'none': $access_level = Auth::PRIV_HIDE; break; } foreach (array_keys($this->cart[$WT_TREE->getTreeId()]) as $xref) { $object = GedcomRecord::getInstance($xref, $WT_TREE); // The object may have been deleted since we added it to the cart.... if ($object) { $record = $object->privatizeGedcom($access_level); // Remove links to objects that aren't in the cart preg_match_all('/\\n1 ' . WT_REGEX_TAG . ' @(' . WT_REGEX_XREF . ')@(\\n[2-9].*)*/', $record, $matches, PREG_SET_ORDER); foreach ($matches as $match) { if (!array_key_exists($match[1], $this->cart[$WT_TREE->getTreeId()])) { $record = str_replace($match[0], '', $record); } } preg_match_all('/\\n2 ' . WT_REGEX_TAG . ' @(' . WT_REGEX_XREF . ')@(\\n[3-9].*)*/', $record, $matches, PREG_SET_ORDER); foreach ($matches as $match) { if (!array_key_exists($match[1], $this->cart[$WT_TREE->getTreeId()])) { $record = str_replace($match[0], '', $record); } } preg_match_all('/\\n3 ' . WT_REGEX_TAG . ' @(' . WT_REGEX_XREF . ')@(\\n[4-9].*)*/', $record, $matches, PREG_SET_ORDER); foreach ($matches as $match) { if (!array_key_exists($match[1], $this->cart[$WT_TREE->getTreeId()])) { $record = str_replace($match[0], '', $record); } } $record = FunctionsExport::convertMediaPath($record, $this->conv_path); $savedRecord = $record; // Save this for the "does this file exist" check if ($convert === 'yes') { $record = utf8_decode($record); } switch ($object::RECORD_TYPE) { case 'INDI': $filetext .= $record . "\n"; $filetext .= "1 SOUR @WEBTREES@\n"; $filetext .= "2 PAGE " . WT_BASE_URL . $object->getRawUrl() . "\n"; break; case 'FAM': $filetext .= $record . "\n"; $filetext .= "1 SOUR @WEBTREES@\n"; $filetext .= "2 PAGE " . WT_BASE_URL . $object->getRawUrl() . "\n"; break; case 'SOUR': $filetext .= $record . "\n"; $filetext .= "1 NOTE " . WT_BASE_URL . $object->getRawUrl() . "\n"; break; default: // This autoloads the PclZip library, so we can use its constants. new PclZip(''); $ft = preg_match_all("/\n\\d FILE (.+)/", $savedRecord, $match, PREG_SET_ORDER); $MEDIA_DIRECTORY = $WT_TREE->getPreference('MEDIA_DIRECTORY'); for ($k = 0; $k < $ft; $k++) { // Skip external files and non-existant files if (file_exists(WT_DATA_DIR . $MEDIA_DIRECTORY . $match[$k][1])) { $media[$mediacount] = array(\PCLZIP_ATT_FILE_NAME => WT_DATA_DIR . $MEDIA_DIRECTORY . $match[$k][1], \PCLZIP_ATT_FILE_NEW_FULL_NAME => $match[$k][1]); $mediacount++; } } $filetext .= trim($record) . "\n"; break; } } } if ($this->IncludeMedia === "yes") { $this->media_list = $media; } else { $this->media_list = array(); } $filetext .= "0 @WEBTREES@ SOUR\n1 TITL " . WT_BASE_URL . "\n"; if ($user_id = $WT_TREE->getPreference('CONTACT_EMAIL')) { $user = User::find($user_id); $filetext .= "1 AUTH " . $user->getRealName() . "\n"; } $filetext .= "0 TRLR\n"; //-- make sure the preferred line endings are used $filetext = preg_replace("/[\r\n]+/", WT_EOL, $filetext); $this->download_data = $filetext; $this->downloadClipping(); } Session::put('cart', $this->cart); }