summaryrefslogtreecommitdiffstats
path: root/perl-install/timezone.pm
blob: df8da49b29d55ec3d7b2a326e65c7218d6957931 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
package timezone; # $Id$

use diagnostics;
use strict;

use common;
use log;


sub getTimeZones {
    my ($prefix) = @_;
    $::testing and $prefix = '';
    open(my $F, "cd $prefix/usr/share/zoneinfo && find [A-Z]* -type f |");
    my @l = chomp_(<$F>);
    close $F or die "cannot list the available zoneinfos";
    sort @l;
}

sub read {
    my %t = getVarsFromSh("$::prefix/etc/sysconfig/clock") or return {};
    { timezone => $t{ZONE}, UTC => text2bool($t{UTC}) };
}

sub ntp_server {
    my ($prefix, $server) = @_;

    my $f = "$prefix/etc/ntp.conf";
    -e $f or return;

    if (@_ > 1) {
	my $added = 0;
	substInFile {
	    if (/^#?\s*server\s+(\S*)/ && $1 ne '127.127.1.0') {
		$_ = $added ? "#server $1\n" : "server $server\n";
		$added = 1;
	    }
	} $f;
	output_p("$prefix/etc/ntp/step-tickers", "$server\n");
    } else {
	$server = find { $_ ne '127.127.1.0' } map { if_(/^\s*server\s+(\S*)/, $1) } cat_($f);
    }
    $server;
}

sub write {
    my ($prefix, $t) = @_;

    ntp_server($prefix, $t->{ntp});

    eval { cp_af("$prefix/usr/share/zoneinfo/$t->{timezone}", "$prefix/etc/localtime") };
    $@ and log::l("installing /etc/localtime failed");
    setVarsInSh("$prefix/etc/sysconfig/clock", {
	ZONE => $t->{timezone},
	UTC  => bool2text($t->{UTC}),
	ARC  => "false",
    });
}

#- best guesses for a given country
my %c2t = (
'AM' => 'Asia/Yerevan',
'AR' => 'America/Buenos_Aires',
'AT' => 'Europe/Vienna',
'AU' => 'Australia/Sydney',
'BA' => 'Europe/Sarajevo',
'BE' => 'Europe/Brussels',
'BG' => 'Europe/Sofia',
'BR' => 'Brazil/East', #- most people live on the east coast
'BY' => 'Europe/Minsk',
'CA' => 'Canada/Eastern',
'CH' => 'Europe/Zurich',
'CN' => 'Asia/Beijing',
'CZ' => 'Europe/Prague',
'DE' => 'Europe/Berlin',
'DK' => 'Europe/Copenhagen',
'EE' => 'Europe/Tallinn',
'ES' => 'Europe/Madrid',
'FI' => 'Europe/Helsinki',
'FR' => 'Europe/Paris',
'GB' => 'Europe/London',
'GE' => 'Asia/Yerevan',
'GL' => 'Arctic/Longyearbyen',
'GR' => 'Europe/Athens',
'HR' => 'Europe/Zagreb',
'HU' => 'Europe/Budapest',
'ID' => 'Asia/Jakarta',
'IE' => 'Europe/Dublin',
'IL' => 'Asia/Tel_Aviv',
'IN' => 'Asia/Calcutta',
'IR' => 'Asia/Tehran',
'IS' => 'Atlantic/Reykjavik',
'IT' => 'Europe/Rome',
'JP' => 'Asia/Tokyo',
'KR' => 'Asia/Seoul',
'LT' => 'Europe/Vilnius',
'LV' => 'Europe/Riga',
'MK' => 'Europe/Skopje',
'MT' => 'Europe/Malta',
'MX' => 'America/Mexico_City',
'MY' => 'Asia/Kuala_Lumpur',
'NL' => 'Europe/Amsterdam',
'NO' => 'Europe/Oslo',
'NZ' => 'Pacific/Auckland',
'PL' => 'Europe/Warsaw',
'PT' => 'Europe/Lisbon',
'RO' => 'Europe/Bucharest',
'RU' => 'Europe/Moscow',
'SE' => 'Europe/Stockholm',
'SI' => 'Europe/Ljubljana',
'SK' => 'Europe/Bratislava',
'TH' => 'Asia/Bangkok',
'TJ' => 'Asia/Dushanbe',
'TR' => 'Europe/Istanbul',
'TW' => 'Asia/Taipei',
'UA' => 'Europe/Kiev',
'US' => 'America/New_York',
'UZ' => 'Asia/Tashkent',
'VN' => 'Asia/Saigon',
'YU' => 'Europe/Belgrade',
'ZA' => 'Africa/Johannesburg',
);

sub fuzzyChoice { 
    my ($b, $count) = bestMatchSentence($_[0], keys %c2t);
    $count ? $b : '';
}
sub bestTimezone { $c2t{fuzzyChoice($_[0])} || 'GMT' }

sub ntp_servers { 
q(Australia (ntp.adelaide.edu.au)
Australia (ntp.saard.net)
Australia (time.esec.com.au)
Canada (ntp.cpsc.ucalgary.ca)
Canada (ntp1.cmc.ec.gc.ca)
Canada (ntp2.cmc.ec.gc.ca)
Canada (time.chu.nrc.ca)
Canada (time.nrc.ca)
Canada (timelord.uregina.ca)
Spain (slug.ctv.es)
France (ntp.univ-lyon1.fr)
Croatia (zg1.ntp.carnet.hr)
Croatia (zg2.ntp.carnet.hr)
Croatia (st.ntp.carnet.hr)
Croatia (ri.ntp.carnet.hr)
Croatia (os.ntp.carnet.hr)
Indonesia (ntp.incaf.net)
Italy (time.ien.it)
Korea, republic of (time.nuri.net)
Norway (fartein.ifi.uio.no)
Russia (ntp.landau.ac.ru)
Singapore (ntp.shim.org)
Slovenia (time.ijs.si)
United kingdom (ntp.cs.strath.ac.uk)
United kingdom (ntp2a.mcc.ac.uk)
United kingdom (ntp2b.mcc.ac.uk)
United kingdom (ntp2c.mcc.ac.uk)
United kingdom (ntp2d.mcc.ac.uk)
United states DE (louie.udel.edu)
United states IL (ntp-0.cso.uiuc.edu)
United states IL (ntp-1.cso.uiuc.edu)
United states IL (ntp-2.cso.uiuc.edu)
United states IN (gilbreth.ecn.purdue.edu)
United states IN (harbor.ecn.purdue.edu)
United states IN (molecule.ecn.purdue.edu)
);
}

1;
ss="hl slc">// Update post indicators for posts now no longer having attachments $this->resync->resync('post', $this->post_ids); // Update message table if messages are affected $this->resync->resync('message', $this->message_ids); // Now update the topics. This is a bit trickier, because there could be posts still having attachments within the topic $this->resync->resync('topic', $this->topic_ids); return $this->num_deleted; } /** * Set attachment IDs * * @param mixed $ids ID or array of IDs * * @return bool True if attachment IDs were set, false if not */ protected function set_attachment_ids($ids) { // 0 is as bad as an empty array if (empty($ids)) { return false; } if (is_array($ids)) { $ids = array_unique($ids); $this->ids = array_map('intval', $ids); } else { $this->ids = array((int) $ids); } return true; } /** * Set SQL constraints based on mode * * @param string $mode Delete mode; can be: post|message|topic|attach|user */ private function set_sql_constraints($mode) { switch ($mode) { case 'post': case 'message': $this->sql_id = 'post_msg_id'; $this->sql_where = ' AND in_message = ' . ($mode == 'message' ? 1 : 0); break; case 'topic': $this->sql_id = 'topic_id'; break; case 'user': $this->sql_id = 'poster_id'; break; case 'attach': default: $this->sql_id = 'attach_id'; break; } } /** * Collect info about attachment IDs * * @param bool $resync Whether topics/posts should be resynced after delete */ protected function collect_attachment_info($resync) { // Collect post and topic ids for later use if we need to touch remaining entries (if resync is enabled) $sql = 'SELECT post_msg_id, topic_id, in_message, physical_filename, thumbnail, filesize, is_orphan FROM ' . ATTACHMENTS_TABLE . ' WHERE ' . $this->db->sql_in_set($this->sql_id, $this->ids); $sql .= $this->sql_where; $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) { // We only need to store post/message/topic ids if resync is enabled and the file is not orphaned if ($resync && !$row['is_orphan']) { if (!$row['in_message']) { $this->post_ids[] = $row['post_msg_id']; $this->topic_ids[] = $row['topic_id']; } else { $this->message_ids[] = $row['post_msg_id']; } } $this->physical[] = array('filename' => $row['physical_filename'], 'thumbnail' => $row['thumbnail'], 'filesize' => $row['filesize'], 'is_orphan' => $row['is_orphan']); } $this->db->sql_freeresult($result); // IDs should be unique $this->post_ids = array_unique($this->post_ids); $this->message_ids = array_unique($this->message_ids); $this->topic_ids = array_unique($this->topic_ids); } /** * Delete attachments from database table */ protected function delete_attachments_from_db($mode, $ids, $resync) { $sql_id = $this->sql_id; $post_ids = $this->post_ids; $topic_ids = $this->topic_ids; $message_ids = $this->message_ids; $physical = $this->physical; /** * Perform additional actions before attachment(s) deletion * * @event core.delete_attachments_before * @var string mode Variable containing attachments deletion mode, can be: post|message|topic|attach|user * @var mixed ids Array or comma separated list of ids corresponding to the mode * @var bool resync Flag indicating if posts/messages/topics should be synchronized * @var string sql_id The field name to collect/delete data for depending on the mode * @var array post_ids Array with post ids for deleted attachment(s) * @var array topic_ids Array with topic ids for deleted attachment(s) * @var array message_ids Array with private message ids for deleted attachment(s) * @var array physical Array with deleted attachment(s) physical file(s) data * @since 3.1.7-RC1 */ $vars = array( 'mode', 'ids', 'resync', 'sql_id', 'post_ids', 'topic_ids', 'message_ids', 'physical', ); extract($this->dispatcher->trigger_event('core.delete_attachments_before', compact($vars))); $this->sql_id = $sql_id; $this->post_ids = $post_ids; $this->topic_ids = $topic_ids; $this->message_ids = $message_ids; $this->physical = $physical; unset($sql_id, $post_ids, $topic_ids, $message_ids, $physical); // Delete attachments $sql = 'DELETE FROM ' . ATTACHMENTS_TABLE . ' WHERE ' . $this->db->sql_in_set($this->sql_id, $this->ids); $sql .= $this->sql_where; $this->db->sql_query($sql); $this->num_deleted = $this->db->sql_affectedrows(); } /** * Delete attachments from filesystem */ protected function remove_from_filesystem($mode, $ids, $resync) { $space_removed = $files_removed = 0; foreach ($this->physical as $file_ary) { if ($this->unlink_attachment($file_ary['filename'], 'file', true) && !$file_ary['is_orphan']) { // Only non-orphaned files count to the file size $space_removed += $file_ary['filesize']; $files_removed++; } if ($file_ary['thumbnail']) { $this->unlink_attachment($file_ary['filename'], 'thumbnail', true); } } $sql_id = $this->sql_id; $post_ids = $this->post_ids; $topic_ids = $this->topic_ids; $message_ids = $this->message_ids; $physical = $this->physical; $num_deleted = $this->num_deleted; /** * Perform additional actions after attachment(s) deletion from the filesystem * * @event core.delete_attachments_from_filesystem_after * @var string mode Variable containing attachments deletion mode, can be: post|message|topic|attach|user * @var mixed ids Array or comma separated list of ids corresponding to the mode * @var bool resync Flag indicating if posts/messages/topics should be synchronized * @var string sql_id The field name to collect/delete data for depending on the mode * @var array post_ids Array with post ids for deleted attachment(s) * @var array topic_ids Array with topic ids for deleted attachment(s) * @var array message_ids Array with private message ids for deleted attachment(s) * @var array physical Array with deleted attachment(s) physical file(s) data * @var int num_deleted The number of deleted attachment(s) from the database * @var int space_removed The size of deleted files(s) from the filesystem * @var int files_removed The number of deleted file(s) from the filesystem * @since 3.1.7-RC1 */ $vars = array( 'mode', 'ids', 'resync', 'sql_id', 'post_ids', 'topic_ids', 'message_ids', 'physical', 'num_deleted', 'space_removed', 'files_removed', ); extract($this->dispatcher->trigger_event('core.delete_attachments_from_filesystem_after', compact($vars))); $this->sql_id = $sql_id; $this->post_ids = $post_ids; $this->topic_ids = $topic_ids; $this->message_ids = $message_ids; $this->physical = $physical; $this->num_deleted = $num_deleted; unset($sql_id, $post_ids, $topic_ids, $message_ids, $physical, $num_deleted); if ($space_removed || $files_removed) { $this->config->increment('upload_dir_size', $space_removed * (-1), false); $this->config->increment('num_files', $files_removed * (-1), false); } } /** * Delete attachment from filesystem * * @param string $filename Filename of attachment * @param string $mode Delete mode * @param bool $entry_removed Whether entry was removed. Defaults to false * @return bool True if file was removed, false if not */ public function unlink_attachment($filename, $mode = 'file', $entry_removed = false) { // Because of copying topics or modifications a physical filename could be assigned more than once. If so, do not remove the file itself. $sql = 'SELECT COUNT(attach_id) AS num_entries FROM ' . ATTACHMENTS_TABLE . " WHERE physical_filename = '" . $this->db->sql_escape(utf8_basename($filename)) . "'"; $result = $this->db->sql_query($sql); $num_entries = (int) $this->db->sql_fetchfield('num_entries'); $this->db->sql_freeresult($result); // Do not remove file if at least one additional entry with the same name exist. if (($entry_removed && $num_entries > 0) || (!$entry_removed && $num_entries > 1)) { return false; } $filename = ($mode == 'thumbnail') ? 'thumb_' . utf8_basename($filename) : utf8_basename($filename); $filepath = $this->phpbb_root_path . $this->config['upload_path'] . '/' . $filename; try { if ($this->filesystem->exists($filepath)) { $this->filesystem->remove($this->phpbb_root_path . $this->config['upload_path'] . '/' . $filename); return true; } } catch (\phpbb\filesystem\exception\filesystem_exception $exception) { // Fail is covered by return statement below } return false; } }