PluginProbe
wp-forecast / 9.6
wp-forecast v9.6
10.0 trunk 1.4 1.6 1.7 1.8 1.9 2.0 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 3..5 3..8 3.0 3.1 3.2 3.3 3.4 3.6 All 86 releases
← All changes | funclib.php +568 -526 3..59.6 View file →
@@ -1,588 +1,630 @@
1 1 <?php
2 -/* This file is part of the wp-forecast plugin for wordpress */
2 +/**
3 + * This file is part of the wp-forecast plugin for WordPress
4 + *
5 + * Copyright 2006-2023 Hans Matzen (email : webmaster at tuxlog dot de)
6 + *
7 + * This program is free software; you can redistribute it and/or modify
8 + * it under the terms of the GNU General Public License as published by
9 + * the Free Software Foundation; either version 2 of the License, or
10 + * (at your option) any later version.
11 + *
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 General Public License for more details.
16 + *
17 + * You should have received a copy of the GNU General Public License
18 + * along with this program; if not, write to the Free Software
19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 + *
21 + * @package wp-forecast
22 + */
3 23
4 -/* Copyright 2006-2009 Hans Matzen (email : webmaster at tuxlog dot de)
24 +if ( ! function_exists( 'get_wpf_opts' ) ) {
25 + /**
26 + * Converts the given wind parameters into a suitable windstring.
27 + *
28 + * @param string $metric the units to use.
29 + * @param string $wspeed the wind speed.
30 + * @param string $windunit the unit of the wind to convert.
31 + */
32 + function windstr( $metric, $wspeed, $windunit ) {
33 + // if its mph convert it to m/s.
34 + if ( 1 != $metric ) {
35 + $wspeed = round( $wspeed * 0.44704, 0 );
36 + }
5 37
6 - This program is free software; you can redistribute it and/or modify
7 - it under the terms of the GNU General Public License as published by
8 - the Free Software Foundation; either version 2 of the License, or
9 - (at your option) any later version.
38 + // convert it to selected unit.
39 + switch ( $windunit ) {
40 + case 'ms':
41 + $wunit = 'm/s';
42 + break;
43 + case 'kmh':
44 + $wspeed = round( $wspeed * 3.6, 0 );
45 + $wunit = 'km/h';
46 + break;
47 + case 'mph':
48 + $wspeed = round( $wspeed * 2.23694, 0 );
49 + $wunit = 'mph';
50 + break;
51 + case 'kts':
52 + $wspeed = round( $wspeed * 1.9438, 0 );
53 + $wunit = 'kts';
54 + break;
55 + case 'bft':
56 + $wbft = 0;
57 + $bft = array( 0.3, 1.6, 3.4, 5.5, 8.0, 10.8, 13.9, 17.2, 20.8, 24.5, 28.5, 32.7 );
58 + foreach ( $bft as $b ) {
59 + if ( $wspeed < $b ) {
60 + $wbft--;
61 + break;
62 + }
63 + $wbft++;
64 + }
65 + $wunit = 'bft';
66 + $wspeed = $wbft;
67 + break;
68 + }
69 + return $wspeed . ' ' . $wunit;
70 + }
10 71
11 - This program is distributed in the hope that it will be useful,
12 - but WITHOUT ANY WARRANTY; without even the implied warranty of
13 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 - GNU General Public License for more details.
15 72
16 - You should have received a copy of the GNU General Public License
17 - along with this program; if not, write to the Free Software
18 - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 -*/
73 + /**
74 + * Wrapper to make sure the correct option is used whether multisite or wp is used.
75 + * only wraps main parameters and pass through all others.
76 + *
77 + * @param string $name the name of the option to get.
78 + */
79 + function wpf_get_option( $name ) {
80 + global $blog_id;
20 81
21 -if (!function_exists('fetchURL')) {
82 + if ( ! function_exists( 'is_multisite' ) || ! is_multisite() || 1 == $blog_id ) {
83 + return get_option( $name );
84 + } else {
85 + // this is the multisite part.
86 + if ( 'wpf_sa_defaults' == $name || 'wpf_sa_allowed' == $name ) {
87 + return get_blog_option( 1, $name );
88 + } else {
89 + return get_blog_option( $blog_id, $name );
90 + }
91 + }
92 + }
22 93
23 -//
24 -// this function fetches an url an returns it as one whole string
25 -//
26 -function fetchURL($url)
27 -{
28 - pdebug(1,"Start of fetchURL ()");
94 + /**
95 + * Wrapper for update option to hide differences between wp and wpmu.
96 + *
97 + * @param string $name the name of the option.
98 + * @param string $value the value of the option.
99 + */
100 + function wpf_update_option( $name, $value ) {
101 + global $blog_id;
29 102
30 - // get timeout parameter
31 - $timeout = get_option("wp-forecast-timeout");
32 - if ( $timeout =="")
33 - $timeout = 10;
103 + if ( ! function_exists( 'is_multisite' ) || ! is_multisite() || 1 == $blog_id ) {
104 + update_option( $name, $value );
105 + } else {
106 + update_blog_option( $blog_id, $name, $value );
107 + }
108 + }
34 109
110 + /**
111 + * Wrapper for add option to hide differences between wp and wpmu.
112 + *
113 + * @param string $name the name of the option.
114 + * @param string $value the value of the option.
115 + */
116 + function wpf_add_option( $name, $value ) {
117 + global $blog_id;
35 118
36 - if ( function_exists("wp_remote_request") ) {
37 - pdebug(1,"Using wp_remote_request");
119 + if ( ! function_exists( 'is_multisite' ) || ! is_multisite() || 1 == $blog_id ) {
120 + add_option( $name, $value );
121 + } else {
122 + add_blog_option( $blog_id, $name, $value );
123 + }
124 + }
38 125
39 - // switch to wp-forecast transport
40 - switch_wpf_transport(true);
41 -
42 - $wprr_args = array(
43 - 'timeout' => $timeout,
44 - 'decompress' => false,
45 - 'headers' => array(
46 - 'Connection' => 'Close',
47 - 'Accept' => '*/*'
48 - )
49 - );
126 + /**
127 + * Reads all wp-forecast options and returns an array.
128 + *
129 + * @param $string $wpfcid the id of th widget.
130 + */
131 + function get_wpf_opts( $wpfcid ) {
132 + global $blog_id;
50 133
134 + $av = array();
135 + $opt = wpf_get_option( 'wp-forecast-opts' . $wpfcid );
51 136
52 - // use generic wordpress function to retrieve data
53 - $s = time();
54 - $resp = wp_remote_request($url, $wprr_args);
55 - $e = time();
137 + if ( ! empty( $opt ) ) {
138 + // unpack if necessary.
139 + $av = maybe_unserialize( $opt );
140 + } elseif ( get_option( 'wp-forecast-location' . $wpfcid ) != '' ) {
141 + // get old widget options from database.
142 + $av['service'] = get_option( 'wp-forecast-service' . $wpfcid );
143 + $av['apikey1'] = get_option( 'wp-forecast-apikey1' . $wpfcid );
144 + $av['apikey2'] = get_option( 'wp-forecast-apikey2' . $wpfcid );
145 + $av['location'] = get_option( 'wp-forecast-location' . $wpfcid );
146 + $av['locname'] = get_option( 'wp-forecast-locname' . $wpfcid );
147 + $av['refresh'] = get_option( 'wp-forecast-refresh' . $wpfcid );
148 + $av['metric'] = get_option( 'wp-forecast-metric' . $wpfcid );
149 + $av['wpf_language'] = get_option( 'wp-forecast-language' . $wpfcid );
150 + $av['daytime'] = get_option( 'wp-forecast-daytime' . $wpfcid );
151 + $av['nighttime'] = get_option( 'wp-forecast-nighttime' . $wpfcid );
152 + $av['dispconfig'] = get_option( 'wp-forecast-dispconfig' . $wpfcid );
153 + $av['windunit'] = get_option( 'wp-forecast-windunit' . $wpfcid );
154 + $av['currtime'] = get_option( 'wp-forecast-currtime' . $wpfcid );
155 + $av['timeoffset'] = get_option( 'wp-forecast-timeoffset' . $wpfcid );
156 + if ( '' == trim( $av['timeoffset'] ) ) {
157 + $av['timeoffset'] = 0;
158 + }
159 + $av['title'] = get_option( 'wp-forecast-title' . $wpfcid );
160 + // replace old options by new one row option.
161 + wpf_add_option( 'wp-forecast-opts' . $wpfcid, serialize( $av ) );
162 + // remove old options from database.
163 + delete_option( 'wp-forecast-location' . $wpfcid );
164 + delete_option( 'wp-forecast-locname' . $wpfcid );
165 + delete_option( 'wp-forecast-refresh' . $wpfcid );
166 + delete_option( 'wp-forecast-metric' . $wpfcid );
167 + delete_option( 'wp-forecast-language' . $wpfcid );
168 + delete_option( 'wp-forecast-daytime' . $wpfcid );
169 + delete_option( 'wp-forecast-nighttime' . $wpfcid );
170 + delete_option( 'wp-forecast-dispconfig' . $wpfcid );
171 + delete_option( 'wp-forecast-windunit' . $wpfcid );
172 + delete_option( 'wp-forecast-currtime' . $wpfcid );
173 + delete_option( 'wp-forecast-title' . $wpfcid );
174 + delete_option( 'wp-forecast-service' . $wpfcid );
175 + delete_option( 'wp-forecast-apikey1' . $wpfcid );
176 + delete_option( 'wp-forecast-apikey2' . $wpfcid );
177 + } else {
178 + $av = array();
179 + }
56 180
57 - if ( is_wp_error($resp) )
58 - $blen = "-1";
59 - else
60 - $blen = strlen( $resp['body'] );
181 + // add expire options.
182 + $av['expire'] = get_option( 'wp-forecast-expire' . $wpfcid );
61 183
62 - pdebug(1,"Fetch took ".(int) ($e-$s) . " seconds and got ".$blen." Bytes.");
184 + // add generic options.
185 + $av['fc_date_format'] = get_option( 'date_format' );
186 + $av['fc_time_format'] = get_option( 'time_format' );
187 + $av['xmlerror'] = '';
63 188
64 - // switch to wp-forecast transport
65 - switch_wpf_transport(false);
189 + // set static uris for each provider.
190 + $av['OPENWEATHERMAP_BASE_URI'] = 'https://api.openweathermap.org/data/2.5';
191 + $av['OPENWEATHERMAP_BASE_URI_V3'] = 'https://api.openweathermap.org/data/3.0/onecall?';
66 192
67 - if ( is_wp_error($resp) ) {
68 - $errcode = $resp->get_error_code();
69 - $errmesg = $resp->get_error_message($errcode);
70 -
71 - $erg="<ADC_DATABASE><FAILURE>Connection Error:".$errcode . "<br/>";
72 - $erg .= $errmesg ."</FAILURE></ADC_DATABASE>\n";
73 - } else
74 - $erg = $resp['body'];
75 -
76 -
77 - } else {
78 - pdebug(1,"Using build in fsockopen method");
79 - // fallback to old fsockopen variant
80 - $url_parsed = parse_url($url);
81 - $host = $url_parsed["host"];
82 - if (!isset($url_parsed["port"]))
83 - $port = 80;
84 - else
85 - $port = $url_parsed["port"];
86 -
87 - $path = $url_parsed["path"];
88 - if ($url_parsed["query"] != "") $path .= "?" . $url_parsed["query"];
89 - $out = "GET $path HTTP/1.0\r\nHost: $host\r\n\r\n";
90 - // open connection
91 - $fp = @fsockopen($host, $port, $errno, $errstr, $timeout);
92 -
93 - $erg = "";
94 - if ($fp) {
95 - // set timeout for reading
96 - stream_set_timeout($fp, $timeout);
97 - // send request
98 - fwrite($fp, $out);
99 - $body = false;
100 - // read answer
101 - while (!feof($fp)) {
102 - $s = fgets($fp, 1024);
103 - if ($body) $erg .= $s;
104 - if ($s == "\r\n") $body = true;
105 - }
106 - // close connection
107 - fclose($fp);
108 - } else {
109 - // error handling
110 - $erg="<ADC_DATABASE><FAILURE>Connection Error:".$errno. " >> ". $errstr ."</FAILURE></ADC_DATABASE>\n";
111 - }
112 - }
113 -
114 - // workaround for bug in decompress function, class wp_http in wp 2.9
115 - $derg = @gzinflate($erg);
116 - if ($derg !== false)
117 - $erg = $derg;
118 -
119 - pdebug(1,"End of fetchURL ()");
120 -
121 - return $erg;
122 -}
193 + $av['OPENMETEO_BASE_URI'] = 'https://api.open-meteo.com/v1/forecast?';
194 + $av['OPENMETEO_LOC_URI'] = 'https://geocoding-api.open-meteo.com/v1/search?';
123 195
196 + // if we use multisite then merge admin options.
197 + if ( function_exists( 'is_multisite' ) && is_multisite() && 1 != $blog_id ) {
124 198
125 -//
126 -// converts the given wind parameters into a suitable windstring
127 -//
128 -function windstr($metric,$wspeed,$windunit)
129 -{
130 - pdebug(2,"Start of windstr ()");
199 + // read defaults and allowed fields.
200 + $defaults = maybe_unserialize( wpf_get_option( 'wpf_sa_defaults' ) );
201 + $allowed = maybe_unserialize( wpf_get_option( 'wpf_sa_allowed' ) );
202 + // in case allowed is still empty.
203 + if ( ! $allowed ) {
204 + $allowed = array();
205 + }
131 206
132 - // if its mph convert it to m/s
133 - if ($metric != 1)
134 - $wspeed = round($wspeed * 0.44704,0);
135 -
136 - // convert it to selected unit
137 - switch ($windunit) {
138 - case "ms":
139 - $wunit="m/s";
140 - break;
141 - case "kmh":
142 - $wspeed=round($wspeed*3.6,0);
143 - $wunit="km/h";
144 - break;
145 - case "mph":
146 - $wspeed=round($wspeed*2.23694,0);
147 - $wunit="mph";
148 - break;
149 - case "kts":
150 - $wspeed=round($wspeed*1.9438,0);
151 - $wunit="kts";
152 - break;
153 - case "bft":
154 - $wbft = 0;
155 - $bft = array(0.3, 1.6, 3.4, 5.5, 8.0, 10.8, 13.9, 17.2, 20.8, 24.5, 28.5, 32.7);
156 - foreach($bft as $b)
157 - {
158 - if ($wspeed < $b)
159 - {
160 - $wbft--;
161 - break;
162 - }
163 - $wbft++;
207 + // set wpf_maxwidgets for users.
208 + global $blog_id, $wpf_maxwidgets;
209 + if ( $blog_id > '1' && isset( $defaults['wp-forecast-count'] ) ) {
210 + $wpf_maxwidgets = $defaults['wp-forecast-count'];
211 + }
212 +
213 + // map rest of fields.
214 + foreach ( $allowed as $f => $fswitch ) {
215 + $fname = substr( $f, 3 ); // strip ue_ prefix.
216 +
217 + if ( 1 != $fswitch || ! isset( $av[ $fname ] ) ) {
218 + // replace value in av with forced default.
219 + if ( array_key_exists( $fname, $defaults ) ) {
220 + $av[ $fname ] = $defaults[ $fname ];
221 + }
222 + }
223 + }
224 + }
225 + return $av;
164 226 }
165 - $wunit="bft";
166 - $wspeed = $wbft;
167 - break;
168 - }
169 -
170 - pdebug(2,"End of windstr ()");
171 -
172 - return $wspeed." ".$wunit;
173 -}
174 227
228 + /**
229 + * Just return the css link.
230 + * this function is called via the wp_head hook.
231 + *
232 + * @param string $wpfcid the widget id.
233 + */
234 + function wp_forecast_css( $wpfcid = 'A' ) {
175 235
176 -//
177 -// wrapper to make sure the correct option is used whether multisite or wp is used
178 -// only wraps main parameters and pass through all others
179 -//
180 -function wpf_get_option($name)
181 -{
182 - global $blog_id;
183 -
184 - if ( !function_exists("is_multisite") || ! is_multisite() || $blog_id==1 )
185 - return get_option($name);
186 - else {
187 - // this is the multisite part
188 - if ( $name == "wpf_sa_defaults" or
189 - $name == "wpf_sa_allowed" )
190 - return get_blog_option(1, $name);
191 - else
192 - return get_blog_option($blog_id, $name);
193 - }
194 -}
236 + // load weather icon font.
237 + wp_enqueue_style( 'wp-forecast-weathericons', plugin_dir_url( __FILE__ ) . '/weather-icons/weather-icons.min.css', array(), '9999' );
238 + wp_enqueue_style( 'wp-forecast-weathericons-wind', plugin_dir_url( __FILE__ ) . '/weather-icons/weather-icons-wind.min.css', array(), '9999' );
195 239
196 -//
197 -// wrapper for update option to hide differences between wp and wpmu
198 -//
199 -//
200 -function wpf_update_option($name, $value)
201 -{
202 - global $blog_id;
203 -
204 - if ( !function_exists("is_multisite") || ! is_multisite() || $blog_id==1)
205 - update_option($name, $value);
206 - else
207 - update_blog_option($blog_id, $name, $value);
208 -}
240 + $wpf_loadcss = wpf_get_option( 'wp-forecast-loadcss' );
241 + if ( 1 == $wpf_loadcss ) {
242 + return;
243 + }
209 244
210 -//
211 -// wrapper for add option to hide differences between wp and wpmu
212 -//
213 -//
214 -function wpf_add_option($name, $value)
215 -{
216 - global $blog_id;
217 -
218 - if ( !function_exists("is_multisite") || ! is_multisite() || $blog_id==1 )
219 - add_option($name, $value);
220 - else
221 - add_blog_option($blog_id, $name, $value);
222 -}
245 + $def = 'wp-forecast-default.css';
246 + $user = 'wp-forecast.css';
223 247
224 -//
225 -// reads all wp-forecast options and returns an array
226 -//
227 -function get_wpf_opts($wpfcid)
228 -{
229 - pdebug(1,"Start of get_wpf_opts ($wpfcid)");
248 + if ( file_exists( WP_PLUGIN_DIR . '/wp-forecast/' . $user ) ) {
249 + $def = $user;
250 + }
230 251
231 - global $blog_id;
252 + wp_enqueue_style( 'wp-forecast', plugin_dir_url( __FILE__ ) . $def, array(), '9999' );
253 + }
232 254
233 - $av=array();
234 - $opt = wpf_get_option("wp-forecast-opts".$wpfcid);
235 255
236 - if (! empty($opt))
237 - {
238 - // unpack if necessary
239 - $av=maybe_unserialize($opt);
240 - }
241 - else if (get_option("wp-forecast-location".$wpfcid) !="" )
242 - {
243 - // get old widget options from database
244 - $av['service'] = get_option("wp-forecast-service".$wpfcid);
245 - $av['apikey1'] = get_option("wp-forecast-apikey1".$wpfcid);
246 - $av['apikey2'] = get_option("wp-forecast-apikey2".$wpfcid);
247 - $av['location'] = get_option("wp-forecast-location".$wpfcid);
248 - $av['locname'] = get_option("wp-forecast-locname".$wpfcid);
249 - $av['refresh'] = get_option("wp-forecast-refresh".$wpfcid);
250 - $av['metric'] = get_option("wp-forecast-metric".$wpfcid);
251 - $av['wpf_language'] = get_option("wp-forecast-language".$wpfcid);
252 - $av['daytime'] = get_option("wp-forecast-daytime".$wpfcid);
253 - $av['nighttime'] = get_option("wp-forecast-nighttime".$wpfcid);
254 - $av['dispconfig'] = get_option("wp-forecast-dispconfig".$wpfcid);
255 - $av['windunit'] = get_option("wp-forecast-windunit".$wpfcid);
256 - $av['currtime'] = get_option("wp-forecast-currtime".$wpfcid);
257 - $av['timeoffset'] = get_option("wp-forecast-timeoffset".$wpfcid);
258 - $av['title'] = get_option("wp-forecast-title".$wpfcid);
259 - // replace old options by new one row option
260 - wpf_add_option("wp-forecast-opts".$wpfcid,serialize($av));
261 - // remove old options from database
262 - delete_option("wp-forecast-location".$wpfcid);
263 - delete_option("wp-forecast-locname".$wpfcid);
264 - delete_option("wp-forecast-refresh".$wpfcid);
265 - delete_option("wp-forecast-metric".$wpfcid);
266 - delete_option("wp-forecast-language".$wpfcid);
267 - delete_option("wp-forecast-daytime".$wpfcid);
268 - delete_option("wp-forecast-nighttime".$wpfcid);
269 - delete_option("wp-forecast-dispconfig".$wpfcid);
270 - delete_option("wp-forecast-windunit".$wpfcid);
271 - delete_option("wp-forecast-currtime".$wpfcid);
272 - delete_option("wp-forecast-title".$wpfcid);
273 - delete_option("wp-forecast-service".$wpfcid);
274 - delete_option("wp-forecast-apikey1".$wpfcid);
275 - delete_option("wp-forecast-apikey2".$wpfcid);
276 - }
277 - else
278 - {
279 - $av=array();
280 - }
256 + /**
257 + * Just return the css link when not using WordPress
258 + * this function is called when showing widget directly
259 + *
260 + * @param string $wpfcid the widget id.
261 + */
262 + function wp_forecast_css_nowp( $wpfcid = 'A' ) {
281 263
282 - // add expire options
283 - $av['expire']=get_option("wp-forecast-expire".$wpfcid);
264 + // load weather icon font.
265 + wp_enqueue_style( 'wp-forecast-weathericons', plugin_dir_url( __FILE__ ) . '/weather-icons/weather-icons.min.css', array(), '9999' );
266 + wp_enqueue_style( 'wp-forecast-weathericons-wind', plugin_dir_url( __FILE__ ) . '/weather-icons/weather-icons-wind.min.css', array(), '9999' );
284 267
285 - // add generic options
286 - $av['fc_date_format']=get_option("date_format");
287 - $av['fc_time_format']=get_option("time_format");
288 - $av['xmlerror']="";
289 -
290 - // set static uris for each provider
291 - //$av['BASE_URI']="http://host1/accuweather/weather_data.php?"; // for testing
292 - $av['ACCU_LOC_URI']="http://forecastfox.accuweather.com/adcbin/forecastfox/locate_city.asp?location=";
293 - $av['ACCU_BASE_URI']="http://forecastfox.accuweather.com/adcbin/forecastfox/weather_data.asp?";
294 -
295 - $av['BUG_LOC_URI']="http://#apicode#.api.wxbug.net/getLocationsXML.aspx?ACode=#apicode#&SearchString=";
296 - //$av['BUG_STAT_URI']="http://#apicode#.api.wxbug.net/getStationsXML.aspx?ACode=#apicode#&cityCode=";
297 - $av['BUG_BASE_URI']="http://#apicode#.api.wxbug.net/getLiveWeatherRSS.aspx?ACode=#apicode#&cityCode=";
298 - $av['BUG_FORC_URI']="http://#apicode#.api.wxbug.net/getForecastRSS.aspx?ACode=#apicode#&cityCode=";
299 -
300 - $av['GOOGLE_LOC_URI']="http://forecastfox.accuweather.com/adcbin/forecastfox/locate_city.asp?location=";
301 - $av['GOOGLE_BASE_URI']="http://www.google.com/ig/api?";
302 -
303 - // if we use multisite then merge admin options
304 - if ( function_exists("is_multisite") && is_multisite() && $blog_id !=1)
305 - {
268 + $wpf_loadcss = wpf_get_option( 'wp-forecast-loadcss' );
269 + if ( 1 == $wpf_loadcss ) {
270 + return;
271 + }
306 272
307 - // read defaults and allowed fields
308 - $defaults = maybe_unserialize(wpf_get_option("wpf_sa_defaults"));
309 - $allowed = maybe_unserialize(wpf_get_option("wpf_sa_allowed"));
310 - // in case allowed is still empty
311 - if (!$allowed)
312 - $allowed=array();
273 + $def = 'wp-forecast-default-nowp.css';
274 + $user = 'wp-forecast-nowp.css';
313 275
314 - // set wpf_maxwidgets for users
315 - global $blog_id, $wpf_maxwidgets;
316 - if ($blog_id > "1" and isset($defaults["wp-forecast-count"]))
317 - $wpf_maxwidgets = $defaults["wp-forecast-count"];
318 -
319 - // map rest of fields
320 - foreach($allowed as $f => $fswitch)
321 - {
322 - $fname = substr($f,3); // strip ue_ prefix
276 + if ( file_exists( WP_PLUGIN_DIR . '/wp-forecast/' . $user ) ) {
277 + $def = $user;
278 + }
323 279
324 - if ( $fswitch != "1" or ! isset($av[ $fname ]) )
325 - {
326 - // replace value in av with forced default
327 - if (array_key_exists($fname, $defaults))
328 - $av[ $fname ] = $defaults[$fname];
329 - }
330 - }
331 -
332 - }
280 + wp_enqueue_style( 'wp-forecast-nowp', plugin_dir_url( __FILE__ ) . $def, array(), '9999' );
281 + }
333 282
334 - pdebug(1,"End of get_wpf_opts ()");
335 -
336 - return $av;
337 -}
283 + /**
284 + * Just return the css link when not using WordPress
285 + * this function is called when showing widget directly
286 + */
287 + function wp_forecast_get_nowp_css() {
288 + $wpf_loadcss = wpf_get_option( 'wp-forecast-loadcss' );
289 + if ( 1 == $wpf_loadcss ) {
290 + return '';
291 + }
338 292
293 + $def = 'wp-forecast-default-nowp.css';
294 + $user = 'wp-forecast-nowp.css';
339 295
340 -//
341 -// build the url from the parameters and fetch the weather-data
342 -// return it as one long string
343 -//
344 -function get_weather($uri,$loc,$metric)
345 -{
346 - pdebug(1,"Start of get_weather ()");
296 + if ( file_exists( WP_PLUGIN_DIR . '/wp-forecast/' . $user ) ) {
297 + $def = $user;
298 + }
347 299
348 - $url=$uri . "location=" . urlencode($loc) . "&metric=" .
349 - $metric;
350 -
351 - $xml = fetchURL($url);
300 + $res = '';
301 + $file = WP_PLUGIN_DIR . "/wp-forecast/$def";
302 + $f = fopen( $file, 'r' );
352 303
353 - pdebug(1,"End of get_weather ()");
354 -
355 - return $xml;
356 -}
304 + if ( $f ) {
305 + $res = fread( $f, filesize( $file ) );
306 + fclose( $f );
307 + }
357 308
358 -//
359 -// just return the css link
360 -// this function is called via the wp_head hook
361 -//
362 -function wp_forecast_css($wpfcid="A")
363 -{
364 - pdebug(1,"Start of function wp_forecast_css ()");
365 -
366 - $def = "wp-forecast-default.css";
367 - $user = "wp-forecast.css";
368 -
369 - if (file_exists( WP_PLUGIN_DIR . "/wp-forecast/" . $user))
370 - $def =$user;
371 -
372 - $plugin_url = plugins_url("wp-forecast/");
373 -
374 - echo '<link rel="stylesheet" id="wp-forecast-css" href="'. $plugin_url . $def . '" type="text/css" media="screen" />' ."\n";
375 -
376 -
377 -
378 - pdebug(1,"End of function wp_forecast_css ()");
379 -}
309 + return $res;
310 + }
380 311
312 + /**
313 + * Returns the number's widget id used with wp-forecast
314 + * maximum is 999999 :-)
315 + *
316 + * @param int $number number of widgets to use.
317 + */
318 + function get_widget_id( $number ) {
319 + // if negative take the first id.
320 + if ( $number < 0 ) {
321 + return 'A';
322 + }
381 323
382 -//
383 -// just return the css link when not using wordpress
384 -// this function is called when showing widget directly via wp-forecast-show.php
385 -//
386 -function wp_forecast_css_nowp($wpfcid="A")
387 -{
388 - pdebug(1,"Start of function wp_forecast_css_nowp ()");
389 -
390 - $def = "wp-forecast-default-nowp.css";
391 - $user = "wp-forecast-nowp.css";
392 -
393 - if (file_exists( WP_PLUGIN_DIR . "/wp-forecast/" . $user))
394 - $def =$user;
395 -
396 - $plugin_url = plugins_url("wp-forecast/");
397 -
398 - echo '<link rel="stylesheet" id="wp-forecast-nowp-css" href="'. $plugin_url . $def . '" type="text/css" media="screen" />' ."\n";
399 -
400 - pdebug(1,"End of function wp_forecast_css_nowp ()");
401 -}
324 + // the first widgets use chars above we go with 0 padded numbers.
325 + if ( $number <= 25 ) {
326 + return substr( 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', $number, 1 );
327 + } else {
328 + return str_pad( $number, 6, '0', STR_PAD_LEFT );
329 + }
330 + }
402 331
332 + /**
333 + * Function tries to determine the icon path for icon number ino.
334 + *
335 + * @param string $ino icon number.
336 + */
337 + function find_icon( $ino ) {
338 + $path = WPF_PATH . '/icons/' . $ino;
339 + $ext = '.gif';
403 340
404 -//
405 -// little debug output routine
406 -//
407 -if (! function_exists("pdebug") )
408 -{
409 - function pdebug($level,$dstr)
410 - {
411 - global $wpf_debug;
412 - if ($wpf_debug >= $level)
413 - echo $dstr."<br />\n";
414 - }
415 -}
341 + if ( file_exists( $path . '.gif' ) ) {
342 + $ext = '.gif';
343 + } elseif ( file_exists( $path . '.png' ) ) {
344 + $ext = '.png';
345 + } elseif ( file_exists( $path . '.jpg' ) ) {
346 + $ext = '.jpg';
347 + } elseif ( file_exists( $path . '.GIF' ) ) {
348 + $ext = '.GIF';
349 + } elseif ( file_exists( $path . '.PNG' ) ) {
350 + $ext = '.PNG';
351 + } elseif ( file_exists( $path . '.JPG' ) ) {
352 + $ext = '.JPG';
353 + } elseif ( file_exists( $path . '.jpeg' ) ) {
354 + $ext = '.jpeg';
355 + } elseif ( file_exists( $path . '.JPEG' ) ) {
356 + $ext = '.JPEG';
357 + } elseif ( file_exists( $path . '.svg' ) ) {
358 + $ext = '.svg';
359 + } elseif ( file_exists( $path . '.SVG' ) ) {
360 + $ext = '.SVG';
361 + }
416 362
417 -//
418 -// returns the number's widget id used with wp-forecast
419 -// maximum is 999999 :-)
420 -//
421 -function get_widget_id($number)
422 -{
423 - // if negative take the first id
424 - if ($number < 0 )
425 - return "A";
363 + return $ino . $ext;
364 + }
426 365
427 - // the first widgets use chars above we go with 0 padded numbers
428 - if ( $number <= 25 )
429 - return substr("ABCDEFGHIJKLMNOPQRSTUVWXYZ",$number,1);
430 - else
431 - return str_pad($number, 6, "0", STR_PAD_LEFT);
432 -}
366 + /**
367 + * Translates the wind direction into another language
368 + *
369 + * @param string $wdir direction in degrees.
370 + * @param string $tdom textdomain.
371 + */
372 + function translate_winddir( $wdir, $tdom ) {
373 + // translate winddir char by char.
374 + $winddir = '';
375 + $l = strlen( $wdir );
376 + for ( $i = 0;$i < $l;$i++ ) {
377 + $winddir = $winddir . wpf__( $wdir[ $i ], $tdom );
378 + }
379 + return $winddir;
380 + }
433 381
434 -//
435 -// function tries to determine the icon path for icon number ino
436 -//
437 -function find_icon($ino)
438 -{
439 - $path = ABSPATH . "wp-content/plugins/wp-forecast/icons/".$ino;
440 - $ext=".gif";
441 -
442 - if ( file_exists($path.".gif") )
443 - $ext= ".gif";
444 - else if ( file_exists($path.".png") )
445 - $ext= ".png";
446 - else if ( file_exists($path.".jpg") )
447 - $ext= ".jpg";
448 - else if ( file_exists($path.".GIF") )
449 - $ext= ".GIF";
450 - else if ( file_exists($path.".PNG") )
451 - $ext= ".PNG";
452 - else if ( file_exists($path.".JPG") )
453 - $ext= ".JPG";
454 - else if ( file_exists($path.".jpeg") )
455 - $ext= ".jpeg";
456 - else if ( file_exists($path.".JPEG") )
457 - $ext= ".JPEG";
458 - return $ino . $ext;
459 -}
382 + /**
383 + * Translates the wind direction in degree to a string.
384 + *
385 + * @param string $wdir direction in degrees.
386 + * @param string $tdom passhtrough.
387 + */
388 + function translate_winddir_degree( $wdir, $tdom ) {
389 + $dir = '-';
390 + if ( 0 <= $wdir ) {
391 + $dir = 'N';
392 + }
393 + if ( 11.25 <= $wdir ) {
394 + $dir = 'NNE';
395 + }
396 + if ( 33.75 <= $wdir ) {
397 + $dir = 'NE';
398 + }
399 + if ( 56.25 <= $wdir ) {
400 + $dir = 'ENE';
401 + }
402 + if ( 78.75 <= $wdir ) {
403 + $dir = 'E';
404 + }
405 + if ( 101.25 <= $wdir ) {
406 + $dir = 'ESE';
407 + }
408 + if ( 123.75 <= $wdir ) {
409 + $dir = 'SE';
410 + }
411 + if ( 146.25 <= $wdir ) {
412 + $dir = 'SSE';
413 + }
414 + if ( 168.75 <= $wdir ) {
415 + $dir = 'S';
416 + }
417 + if ( 191.25 <= $wdir ) {
418 + $dir = 'SSW';
419 + }
420 + if ( 213.75 <= $wdir ) {
421 + $dir = 'SW';
422 + }
423 + if ( 236.25 <= $wdir ) {
424 + $dir = 'WSW';
425 + }
426 + if ( 258.75 <= $wdir ) {
427 + $dir = 'W';
428 + }
429 + if ( 281.25 <= $wdir ) {
430 + $dir = 'WNW';
431 + }
432 + if ( 303.75 <= $wdir ) {
433 + $dir = 'NW';
434 + }
435 + if ( 326.25 <= $wdir ) {
436 + $dir = 'NNW';
437 + }
438 + if ( 348.75 <= $wdir ) {
439 + $dir = 'N';
440 + }
460 441
461 -function translate_winddir($wdir,$tdom)
462 -{
463 - // translate winddir char by char
464 - $winddir="";
465 - for ($i=0;$i<strlen($wdir);$i++)
466 - $winddir=$winddir . __($wdir{$i},$tdom);
467 - return $winddir;
468 -}
442 + return translate_winddir( $dir, $tdom );
443 + }
469 444
470 -}
471 445
472 -/*
473 - functions to check the wordpress transport methods
446 + /**
447 + * Function for plugin_locale filter hook.
448 + * only returns the first parameter.
449 + *
450 + * @param string $locale iso code of the locale.
451 + * @param string $domain complete domain of the .mo file.
452 + */
453 + function wpf_lplug( $locale, $domain ) {
454 + // extract locale from domain.
455 + $wpf_locale = substr( $domain, 12, 5 );
456 + return $wpf_locale;
457 + }
474 458
475 - if wpf selected transport option is set to empty,
476 - then we are in probing mode and do not change the wordpress result
477 - else we only keep alive what was selected via admin dialog
459 + /**
460 + * Return an array containgin all allowed HTML tags and attributes
461 + */
462 + function wpf_allowed_tags() {
478 463
479 -*/
464 + $allowed_atts = array(
465 + 'align' => array(),
466 + 'class' => array(),
467 + 'type' => array(),
468 + 'id' => array(),
469 + 'dir' => array(),
470 + 'lang' => array(),
471 + 'style' => array(),
472 + 'xml:lang' => array(),
473 + 'src' => array(),
474 + 'alt' => array(),
475 + 'href' => array(),
476 + 'rel' => array(),
477 + 'rev' => array(),
478 + 'target' => array(),
479 + 'novalidate' => array(),
480 + 'type' => array(),
481 + 'value' => array(),
482 + 'name' => array(),
483 + 'tabindex' => array(),
484 + 'action' => array(),
485 + 'method' => array(),
486 + 'for' => array(),
487 + 'width' => array(),
488 + 'height' => array(),
489 + 'data' => array(),
490 + 'title' => array(),
491 + 'maxlength' => array(),
492 + 'border' => array(),
493 + 'onclick' => array(),
494 + 'checked' => array(),
495 + 'selected' => array(),
496 + 'size' => array(),
497 + 'onchange' => array(),
498 + );
480 499
481 -function wpf_check_fsockopen($use, $args = array())
482 -{
483 - $sel_transport = wpf_get_option("wp-forecast-wp-transport");
484 - if ( $sel_transport == "" || $sel_transport == "default" )
485 - return $use;
486 - else if ( $sel_transport == "fsockopen" )
487 - return true;
488 - else
489 - return false;
490 -}
500 + $allowedposttags['aside'] = $allowed_atts;
501 + $allowedposttags['section'] = $allowed_atts;
502 + $allowedposttags['nav'] = $allowed_atts;
503 + $allowedposttags['form'] = $allowed_atts;
504 + $allowedposttags['label'] = $allowed_atts;
505 + $allowedposttags['input'] = $allowed_atts;
506 + $allowedposttags['textarea'] = $allowed_atts;
507 + $allowedposttags['select'] = $allowed_atts;
508 + $allowedposttags['option'] = $allowed_atts;
509 + $allowedposttags['iframe'] = $allowed_atts;
510 + $allowedposttags['script'] = $allowed_atts;
511 + $allowedposttags['style'] = $allowed_atts;
512 + $allowedposttags['strong'] = $allowed_atts;
513 + $allowedposttags['small'] = $allowed_atts;
514 + $allowedposttags['table'] = $allowed_atts;
515 + $allowedposttags['span'] = $allowed_atts;
516 + $allowedposttags['abbr'] = $allowed_atts;
517 + $allowedposttags['code'] = $allowed_atts;
518 + $allowedposttags['pre'] = $allowed_atts;
519 + $allowedposttags['div'] = $allowed_atts;
520 + $allowedposttags['img'] = $allowed_atts;
521 + $allowedposttags['h1'] = $allowed_atts;
522 + $allowedposttags['h2'] = $allowed_atts;
523 + $allowedposttags['h3'] = $allowed_atts;
524 + $allowedposttags['h4'] = $allowed_atts;
525 + $allowedposttags['h5'] = $allowed_atts;
526 + $allowedposttags['h6'] = $allowed_atts;
527 + $allowedposttags['ol'] = $allowed_atts;
528 + $allowedposttags['ul'] = $allowed_atts;
529 + $allowedposttags['li'] = $allowed_atts;
530 + $allowedposttags['em'] = $allowed_atts;
531 + $allowedposttags['hr'] = $allowed_atts;
532 + $allowedposttags['br'] = $allowed_atts;
533 + $allowedposttags['tr'] = $allowed_atts;
534 + $allowedposttags['td'] = $allowed_atts;
535 + $allowedposttags['p'] = $allowed_atts;
536 + $allowedposttags['a'] = $allowed_atts;
537 + $allowedposttags['b'] = $allowed_atts;
538 + $allowedposttags['i'] = $allowed_atts;
491 539
492 -function wpf_check_fopen($use, $args = array())
493 -{
494 - $sel_transport = wpf_get_option("wp-forecast-wp-transport");
495 - if ( $sel_transport == "" || $sel_transport == "default" )
496 - return $use;
497 - else if ( $sel_transport == "fopen" )
498 - return true;
499 - else
500 - return false;
501 -}
540 + return $allowedposttags;
541 + }
502 542
503 -function wpf_check_streams($use, $args = array())
504 -{
505 - $sel_transport = wpf_get_option("wp-forecast-wp-transport");
506 - if ( $sel_transport == "" || $sel_transport == "default" )
507 - return $use;
508 - else if ( $sel_transport == "streams" )
509 - return true;
510 - else
511 - return false;
512 -}
543 + /**
544 + * Function to translate a string into another language
545 + * using the wpf own translation mechanism
546 + * this is necessary because WordPress does not allow
547 + * more than one language per plugin
548 + *
549 + * @param string $s string to translate.
550 + * @param string $d domain to translate to.
551 + */
552 + function wpf__( $s, $d ) {
553 + global $wpf_lang_dict;
513 554
514 -function wpf_check_exthttp($use, $args = array())
515 -{
516 - $sel_transport = wpf_get_option("wp-forecast-wp-transport");
517 - if ( $sel_transport == "" || $sel_transport == "default" )
518 - return $use;
519 - else if ( $sel_transport == "exthttp" )
520 - return true;
521 - else
522 - return false;
523 -}
555 + if ( ! isset( $wpf_lang_dict ) ) {
556 + $wpf_lang_dict = array();
557 + }
524 558
525 -function wpf_check_curl($use, $args = array())
526 -{
527 - $sel_transport = wpf_get_option("wp-forecast-wp-transport");
528 - if ( $sel_transport == "" || $sel_transport == "default" )
529 - return $use;
530 - else if ( $sel_transport == "curl" )
531 - return true;
532 - else
533 - return false;
534 -}
559 + if ( array_key_exists( $d, $wpf_lang_dict ) && isset( $wpf_lang_dict[ $d ] ) ) {
560 + if ( array_key_exists( $s, $wpf_lang_dict[ $d ] ) ) {
561 + return $wpf_lang_dict[ $d ][ $s ];
562 + }
563 + }
535 564
536 -// function to get the list of supported transports ignoring
537 -// any preset method
538 -if (! function_exists("get_wp_transports") )
539 - {
540 - function get_wp_transports()
541 - {
542 - $tlist = array();
543 -
544 - // remove but store selected transport
545 - $wp_transport = wpf_get_option("wp-forecast-wp-transport");
546 - wpf_update_option("wp-forecast-wp-transport","default");
547 -
548 - // get wordpress default transports
549 - $wplist = array();
550 -
551 - if ( true === WP_Http_ExtHttp::test( array() ) )
552 - $tlist[] = "exthttp";
553 -
554 - if ( true === WP_Http_Fsockopen::test( array() ) )
555 - $tlist[] = "fsockopen";
556 -
557 - if ( true === WP_Http_Streams::test( array() ) )
558 - $tlist[] = "streams";
559 -
560 - // disabled fopen, since this class sends no headers
561 - //if ( true === WP_Http_Fopen::test( array() ) )
562 - // $tlist[] = "fopen";
563 -
564 - if ( true === WP_Http_Curl::test( array() ) )
565 - $tlist[] = "curl";
566 -
567 -
568 - // write back selected transport
569 - wpf_update_option("wp-forecast-wp-transport",$wp_transport);
570 -
571 - return $tlist;
565 + // nothing found return original.
566 + return $s;
572 567 }
573 - }
574 568
575 -//
576 -// function to turn on/off wp-forecast preselected transport
577 -//
578 -function switch_wpf_transport($sw)
579 -{
580 - $wptrans = "default";
569 + /**
570 + * Function to translate a string into another language
571 + * using the wpf own translation mechanism
572 + * this is necessary because WordPress does not allow
573 + * more than one language per plugin
574 + * This one echos the translation.
575 + *
576 + * @param string $s string to translate.
577 + * @param string $d domain to translate to.
578 + */
579 + function wpf_e( $s, $d ) {
580 + echo esc_attr( wpf__( $s, $d ) );
581 + }
581 582
582 - if ($sw == true)
583 - $wptrans = wpf_get_option("wp-forecast-pre-transport");
583 + /**
584 + * Function to translate a string into another language
585 + * using the wpf own translation mechanism
586 + * this is necessary because WordPress does not allow
587 + * more than one language per plugin
588 + * This one escape it too
589 + *
590 + * @param string $s string to translate.
591 + * @param string $d domain to translate to.
592 + */
593 + function wpf_esc_attr__( $s, $d ) {
594 + return esc_attr( wpf__( $s, $d ) );
595 + }
584 596
585 - pdebug(1,"Setting preselected transport to ".$wptrans);
586 - update_option("wp-forecast-wp-transport",$wptrans);
587 -}
588 -?>
597 + /**
598 + * Function to translate a string into another language
599 + * using the wpf own translation mechanism
600 + * this is necessary because WordPress does not allow
601 + * more than one language per plugin
602 + * This one escapes and echos the translation.
603 + *
604 + * @param string $s string to translate.
605 + * @param string $d domain to translate to.
606 + */
607 + function wpf_esc_attr_e( $s, $d ) {
608 + echo esc_attr( wpf__( $s, $d ) );
609 + }
610 +
611 + /**
612 + * Echos the admin notice concerning the accuweather probem.
613 + */
614 + function wpf_accuweather_problem_notice() {
615 + $flag = get_option( 'wpf-show-admin-notice' );
616 + if ( false === $flag ) {
617 + $out = '<div class="notice is-dismissible"><p>';
618 + $out .= __(
619 + 'As of September 10, 2023 it seems Accuweather has discontinued the free api-service.
620 + Please switch to either Openweathermap or Open-Meteo instead.
621 + For use with OpenWeatherMap.org you will need a personal API-Key and have to register at their site.
622 + All your Accuweather Widgets have been set to Open-Meteo to avoid errors on your website. Please check if all settings are correct.',
623 + 'wp-forecast'
624 + );
625 + $out .= '</p></div>';
626 + echo wp_kses( $out, wpf_allowed_tags() );
627 + update_option( 'wpf-show-admin-notice', 1 );
628 + }
629 + }
630 +} // end of function_exists