Subversion Repositories PHPX

Rev

Rev 24 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
25 PointedEar 1
<?php
2
 
3
/* @section Helper functions */
4
 
2 PointedEar 5
/**
25 PointedEar 6
 * Retrieves the value of an element of an associative array.
7
 *
8
 * This is designed for $_GET and other HTTP variables but
9
 * also works for common associative arrays.
10
 *
11
 * @param $key: string
12
 *   Key identifier.  The default is the empty string.
13
 * @param $array: string
14
 *   Array identifier.  The default is '_GET'.  If there is
15
 *   no such array, the identifier is prefixed with 'HTTP'
16
 *   and suffixed with '_VARS' (to support the deprecated
17
 *   HTTP_GET_VARS etc. arrays as of PHP &lt; 4.1).  If
18
 *   there is still no array with that identifier, return
19
 *   the empty string.
20
 * @param $default: string
21
 *   Default return value if the element specified with
22
 *   $key is not available in the array.  The default
23
 *   is the empty string.
24
 * @return
25
 *   The value of the element of that array with that key or
26
 *   the empty string if there is no such element or array.
27
 * @author
28
 *  Copyright (C) 2004, 2005  Thomas Lahn &lt;php@PointedEars.de&gt;
29
 */
30
function getVars($key = '', $array = '_GET', $default = '', $noEntities = false)
31
{
32
  global ${$array};
33
  if (!isset(${'HTTP'.$array.'_VARS'})) global ${'HTTP'.$array.'_VARS'};
34
/*
35
  echo "<pre>getVars: \$$array"."['$key']: return '"
36
    .(isset(${$array}) && isset(${$array}[$key])
37
    ? ${$array}[$key]
38
    : (isset(${'HTTP'.$array.'_VARS'}) && isset(${'HTTP'.$array.'_VARS'}[$key])
39
       ? ${'HTTP'.$array.'_VARS'}[$key]
40
       : $default)) . "'</pre><br>\n";
41
*/
42
  $result = (isset(${$array}) && isset(${$array}[$key])
43
    ? ${$array}[$key]
44
    : (isset(${'HTTP'.$array.'_VARS'}) && isset(${'HTTP'.$array.'_VARS'}[$key])
45
       ? ${'HTTP'.$array.'_VARS'}[$key]
46
       : $default));
47
 
48
// TODO: Escape HTML entities
49
/*
50
  if (!$noEntities)
51
  {
52
    $result = htmlentities($result);
53
  }
54
*/
55
  return $result;
56
}
57
 
58
/**
59
 * Converts the argument to a visible (X)HTML hyperlink
60
 * where its URI target is created from the argument.
61
 * Supported are e-mail addresses, domain names with
62
 * optional paths, and valid URIs.
63
 *
64
 * @param $text
65
 *   Argument to be converted.
66
 * @return
67
 *   The converted argument if it applies to a supported
68
 *   scheme, the unconverted argument otherwise.
69
 *
70
 * @author (C) 2001-04-04T02:03
71
 *   mark.young@vdhinc.com at http://php.net/manual/en/ref.strings.php
72
 *
73
 * Minor correction to my HTMLEncode function.
74
 *
75
 * @author 2002-08-29T09:00
76
 *   Thomas Lahn &lt;PointedEars@selfhtml.de&gt; at localhost
77
 *
78
 * - Added target="_blank"
79
 * - Added support for ftp(s)-URIs: (ht|f)
80
 * - Added support for search strings (?...=...&...=...), either
81
 *   with or without HTML entities: \?=(&\w;|&)
82
 * - Removed enclosing nl2br call because of preformatted display
83
 *
84
 * @author 2003-12-30T14:18
85
 *   Thomas Lahn &lt;PointedEars@selfhtml.de&gt; at localhost
86
 *
87
 * - Removed target="_blank".
88
 * - Added PHPdoc.
89
 *
90
 * @author 2004-01-12T12:45
91
 *   Thomas Lahn &lt;PointedEars@selfhtml.de&gt; at localhost
92
 *
93
 * - Added support for #fragment_identifiers in URIs.
94
 * - Added support for bugs and comments.
95
 *
96
 * @author 2004-01-13T01:29
97
 *   Thomas Lahn &lt;PointedEars@selfhtml.de&gt; at localhost
98
 *
99
 * - Added support for bug aliases.
100
 *
101
 * @author 2004-01-26T20:43
102
 *   Thomas Lahn &lt;PointedEars@selfhtml.de&gt; at localhost
103
 *
104
 * - Do not convert URIs in A elements.
105
 * - Do not allow URIs with "&" before search-string.
106
 * - camelCased function identifier.  Only classes
107
 *   and constructors should start with uppercase.
108
 *
109
 * @author 2004-01-27T14:07
110
 *   Thomas Lahn &lt;PointedEars@selfhtml.de&gt; at localhost
111
 *
112
 * - Allow to convert URIs preceded by "&gt;" but not followed by "&lt;/a&gt;".
113
 * - Allow ";" to be part of the search string
114
 *
115
 * @author 2004-01-29T14:10
116
 *   Thomas Lahn &lt;PointedEars@selfhtml.de&gt; at localhost
117
 *
118
 * - Require valid domain name for "bar" on conversion of "foo@bar" and
119
 *   "www.bar".
120
 * - Be case-insensitive except of bug aliases
121
 * - Escaped "-" in character classes if not meant as range metacharacter.
122
 * - Corrected year.
123
 *
124
 * @author 2004-02-14T17:37
125
 *   Thomas Lahn &lt;PointedEars@selfhtml.de&gt; at localhost
126
 *
127
 * - Accept only valid Internet domain names
128
 * - Accept "%" within path and query part (to escape ASCII characters)
129
 *
130
 * @author 2004-02-27T19:21
131
 *   Thomas Lahn &lt;PointedEars@selfhtml.de&gt; at localhost
132
 *
133
 * - Allow unescaped ":" in URI components, since it apparently does not
134
 *   "conflict with the reserved purpose" (RFC 2396, section 2.2.; here:
135
 *   scheme component)
136
 * - Allow slashes, dots and dashes in URI components
137
 * - Removed invalid [...(...|...)...]
138
 *
139
 * @author 2004-03-01T21:48
140
 *   Thomas Lahn &lt;PointedEars@selfhtml.de&gt; at localhost
141
 *
142
 * - Allow IPv4 addresses
143
 *
144
 * @author 2004-03-08T02:20
145
 *   Thomas Lahn &lt;PointedEars@selfhtml.de&gt; at localhost
146
 *
147
 * - Allow "+" and "," in query part
148
 * - Optimized character classes
149
 *
150
 * @author (C) 2004-04-23T10:03
151
 *   Thomas Lahn &lt;PointedEars@selfhtml.de&gt; at localhost
152
 *
153
 * - Rewrite to use RFC 2822 and 2369 syntax
154
 */
155
function htmlEncode($text)
156
{
157
  // see RFC 2822 "Internet Message Format"
158
  $local_part    = '[^()<>@,;:\\"\-\[\] \x00-\x1A\x7F]+';
159
 
160
  // see RFC 2396 "Uniform Resource Identifiers (URI): Generic Syntax"
161
  // $digit      = '\d';          // 0-9; def. not required
162
  // $hex        = '\da-f';     // "hex" for case-insensitive match; def. N/R
163
  $alpha         = 'a-z';         // "alpha" for case-insensitive match
164
  $alphanum      = $alpha.'\d';   // "alphanum" for case-insensitive match
165
  $mark          = "\-_.!~*\'()";
166
  $reserved      = ';/?:@&=+$,';
167
  $unreserved    = $alphanum.$mark;
168
  $escaped       = '%[\da-f]';    // contains $hex
169
 
170
  // added (?!gt;) to allow "&lt;URI&gt;"
171
  $uric          = '(['.$reserved.$alphanum.$mark.'](?!gt;)|'.$escaped.')';
172
  $uric_no_slash = '(['.$unreserved.';\?:@&=+$,](?!gt;)|'.$escaped.')';
173
  $pchar         = '(['.$unreserved.':@&=+$,](?!gt;)|'.$escaped.')';
174
  $param         = $pchar;
175
  $segment       = $pchar.'*(;'.$param.')*';
176
  $abs_path      = '/' . $segment . '(/'.$segment.')*';
177
  $userinfo      = '(['.$unreserved.';:&=+$,](?!gt;)|'.$escaped.')*';
178
  $domainlabel   = '(['.$alphanum.']'
179
                   . '|['.$alphanum.'](['.$alphanum.']|-)*['.$alphanum.']'
180
                   . ')';
181
  $toplabel      = '(['.$alpha.']'
182
                   . '|['.$alpha.'](['.$alphanum.']|-)*['.$alphanum. '])';
183
  $hostname      = '('.$domainlabel. '\.)*' . $toplabel . '\.?';
184
  $ipv4_address  = '\d+\.\d+\.\d+\.\d+';
185
  $host          = '(' . $hostname . '|' . $ipv4_address . ')';
186
  $port          = '\d*';
187
  $hostport      = $host . '(:' . $port . ')?';
188
  $server_req    = '(' . $userinfo . ')?' . $hostport; // server is required
189
  $reg_name      = '([' . $unreserved . '$,;:@&=+](?!gt;)|' . $escaped . ')+';
190
  $authority     = '(' . $server_req . '|' . $reg_name . ')';
191
  $net_path      = '//' . $authority . '('.$abs_path.')?';
192
  $query         = $uric.'*';
193
  $scheme        = '(ht|f)tps?';
194
  $hier_part     = '(' . $net_path  .'|' . $abs_path . ')(\?' . $query . ')?';
195
  $opaque_part   = $uric_no_slash . $uric.'*';
196
  $absolute_uri  = $scheme . ':(' . $hier_part . '|' . $opaque_part . ')';
197
  $fragment      = $uric.'*';
198
 
199
  // absolute URIs only
200
  $uri_reference = $absolute_uri . '(#' . $fragment . ')?';
201
  // echo '<br>'.htmlentities($local_part . '@' . $host).'<br>';
202
 
203
  $searcharray = array(
204
    "'(?i)(" . $local_part . '@' . $host . ")'i",
205
    "'(?i)((?:(?!://).{3}|^.{0,2}))(www\." . $hostname
206
      . '|' . $ipv4_address . ")'i",
207
    "'(?i)(?<!href=\")(" . $uri_reference . ")(?!</a>)'i",
208
    "'(((?i)bug)\s+#?([\dA-Z_]+)\s+((?i)comment|Kommentar)\s+#?(\d+))'",
209
    "'(((?i)bug)\s+#?([\dA-Z_]+))'",
210
    "'(((?i)comment|Kommentar)\s+#?(\d+))'"
211
  );
212
 
213
  $replacearray = array(
214
    "<a href=\"mailto:\\1\">\\1</a>",
215
    "\\1http://\\2",
216
    "<a href=\"\\1\">\\1</a>",
217
    "<a href=\"./?bug=\\3#c\\5\">\\1</a>",
218
    "<a href=\"./?bug=\\3#details\">\\1</a>",
219
    "<a href=\"#c\\3\">\\1</a>"
220
  );
221
 
222
  return preg_replace($searcharray, $replacearray, $text);
223
}
224
 
225
/**
226
 * Converts HTML entities to real characters using the detected
227
 * or specified character encoding.
228
 *
229
 * @param string $s
230
 * @param int[optional] $quote_style
231
 * @return string
232
 */
233
function htmlEntityDecode($s, $quote_style=ENT_COMPAT, $encoding=null)
234
{
235
  $s = (string) $s;
236
 
237
  if (is_null($encoding))
238
  {
239
    $encoding = mb_detect_encoding($s);
240
    if ($encoding === 'ASCII')
241
    {
242
      $encoding = 'ISO-8859-1';
243
    }
244
  }
245
 
246
  return html_entity_decode($s, $quote_style, $encoding);
247
}
248
 
249
 
250
/**
251
 * Converts the argument into a visible (X)HTML hyperlink if a condition
252
 * applies.
253
 *
254
 * @author
255
 *   (C) 2003, 2004  Thomas Lahn &lt;selfhtml.de@PointedEars.de&gt;
256
 * @param $s
257
 *   Content to be converted.  Required.
258
 * @param $sCond
259
 *   Condition to be true for the content to be converted.
260
 *   The default is <code>true</code>.
261
 * @param $sURI
262
 *   Target URI of the hyperlink.  The default is the
263
 *   value of $s.
264
 * @param $sName
265
 *   Value of the <code>name</code> attribute of the
266
 *   <code>a</code> element.  Unused if not provided
267
 *   or empty.
268
 * @param $sTitle
269
 *   Value of the <code>title</code> attribute of the
270
 *   <code>a</code> element.  Unused if not provided
271
 *   or empty.
272
 * @param $sClass
273
 *   Value of the <code>class</code> attribute of the
274
 *   <code>a</code> element.  Unused if not provided
275
 *   or empty.
276
 * @return
277
 *   The converted argument if the condition applies,
278
 *   the unconverted argument otherwise.
279
 */
280
function makeLinkIf(
281
  $s,
282
  $sCond = true,
283
  $sURI = NULL,
284
  $sTarget = '',
285
  $sName = '',
286
  $sTitle = '',
287
  $sClass = '')
288
{
289
  return ($sCond || $sName
290
          ? '<a' . ($sCond
291
                    ? " href=\"" . (is_null($sURI) ? $s : $sURI)
292
                      . "\"".($sTarget ? " target=\"$sTarget\"" : '')
293
                    : ''
294
                   )
295
            . ($sName  ? " name=\"$sName\""   : '')
296
            . ($sTitle ? " title=\"$sTitle\"" : '')
297
            . ($sClass ? " class=\"$sClass\"" : '')
298
            . '>'
299
          : ''
300
         )
301
         . $s
302
         . ($sCond || $sName ? '</a>' : '');
303
}
304
 
305
/**
306
 * Returns a visible (X)HTML hyperlink that uses the mailto: URI scheme.
307
 *
308
 * @author (C) 2003  Thomas Lahn &lt;selfhtml.de@PointedEars.de&gt;
309
 *
310
 * @author (C) 2003-12-30  Thomas Lahn &lt;selfhtml.de@PointedEars.de&gt;
311
 * - Corrected `$email ($name)'.
312
 * - Now uses rawurlencode(...).
313
 * - Added PHPdoc.
314
 *
315
 * @author (C) 2004-11-30  Thomas Lahn &lt;selfhtml.de@PointedEars.de&gt;
316
 * - Don't rawurlencode(...) parens for comments.
317
 *
318
 * @param $sAddress
319
 *   E-mail address.  The default is <selfhtml.de@PointedEars.de>.
320
 * @param $sTitle
321
 *   Value of the <code>title</code> attribute of the
322
 *   <code>a</code> element.  Unused if not provided
323
 *   or empty.  The default is 'PointedEars'.
324
 * @param $sToName
325
 *   Name to be used in the To header of the e-mail.
326
 *   Note that @link{rawurlencode()} is used to escape
327
 *   special characters automatically.
328
 *   The default is "Thomas 'PointedEars' Lahn".
329
 *
330
 * @return
331
 *   The converted argument if the condition applies,
332
 *   the unconverted argument otherwise.
333
 */
334
function mailto_link(
335
  $sAddress = 'selfhtml.de@PointedEars.de',
336
  $sTitle = 'PointedEars',
337
  $sToName = "Thomas 'PointedEars' Lahn",
338
  $sSubject = 'SELFbug',
339
  $sImgPath = '../../media/mail.gif'
340
)
341
{
342
//width="14" height="15" // image size detection not yet implemented
343
  return ($sImgPath != ''
344
          ? '<img src="' . $sImgPath . '" border="0" alt="@">&nbsp;'
345
          : '')
346
    . '<a href="mailto:'
347
    . ($sAddress != ''
348
       ? $sAddress
349
       : 'selfhtml.de@PointedEars.de')
350
    . ($sToName != ''
351
       ? ' (' . rawurlencode($sToName) . ')'
352
       : '')
353
    . ($sSubject != ''
354
       ? '?subject=' . rawurlencode($sSubject)
355
       : '')
356
    . '">' . (($sTitle != '') ? $sTitle : $sAddress) . '</a>';
357
}
358
 
359
// map bug states to numbers so that they become comparable
360
function array_values_to_keys($a)
361
{
362
  $aNew = array();
363
  foreach ($a as $key => $value)
364
  {
365
    $aNew[$value] = count($aNew);
366
  }
367
  return $aNew;
368
}
369
 
370
/**
371
 * Maps an array to another array using a callback function.
372
 *
373
 * Unlike array_map(), the callback is called with three parameters: the value
374
 * to be processed, the key of that value, and the array processed.  The return
375
 * value of the callback defines the value for the same key of the returned
376
 * array.
377
 *
378
 * Because of the way the callback is called, this method supports processing
379
 * only one array at a time, unlike array_map().  Unlike array_walk(), this
380
 * function does not modify the original array.
381
 *
382
 * @param string|array $callback
383
 *   The callback to be used for mapping array values.  If an array, the first
384
 *   element of the array is supposed to be the class name, and the second
385
 *   element the method name of a static method to be used.
386
 * @param array $array
387
 *   The array to process
388
 * @return array
389
 * @see array_map()
390
 * @see array_walk()
391
 */
392
function array_map2($callback, $array)
393
{
394
  $a = array();
395
 
396
  if (is_array($callback))
397
  {
398
    list($class, $method) = $callback;
399
  }
400
 
401
  foreach ($array as $key => &$value)
402
  {
403
    if (is_array($callback))
404
    {
405
      $a[$key] = $class::$method($value, $key, $array);
406
    }
407
    else
408
    {
409
      $a[$key] = $callback($value, $key, $array);
410
    }
411
  }
412
 
413
  return $a;
414
}
415
 
416
/**
2 PointedEar 417
 * Converts a string or an array of strings to an associative
418
 * bitmask array with the string(s) as key(s).
25 PointedEar 419
 *
2 PointedEar 420
 * Converts the argument to a bitmask array where each member's
421
 * value is a power of 2, so that arbitrary member values can be
422
 * added to an integer on which bitwise operations with the member
25 PointedEar 423
 * value or a combination of member values are possible.
424
 *
425
 * @author (c) 2003 Thomas Lahn &lt;SELFbug@PointedEars.de&gt;
426
 * @param $aArray
427
 *   String or array of strings to be converted.
428
 */
429
function getBitmaskArray($aArray)
430
{
431
  $a = array();
432
 
433
  if (is_array($aArray))
434
  {
435
    for ($i = 0; $i < count($aArray); $i++)
436
    {
437
      $a[$aArray[$i]] = pow(2, $i);
438
    }
439
  }
440
  else
441
    $a[$aArray] = 1;
442
 
443
  return $a;
444
}
445
 
446
/**
447
 * Returns the contents of a file as if include() was used.
448
 *
449
 * @param string $filename Path of the file to retrieve
450
 * @return string File contents
451
 */
452
function get_include_content($filename)
453
{
454
  if (is_file($filename))
455
  {
456
    ob_start();
457
    include $filename;
458
    $contents = ob_get_contents();
459
    ob_end_clean();
460
    return $contents;
461
  }
462
 
463
  return '';
464
}
465
 
466
/**
467
 * Replaces each group of expressions in a string with the same
468
 * corresponding string.
469
 *
470
 * @param Array[Array[string] | string, string] $map
471
 * @param string                                $subject
472
 * @return string
473
 *   A copy of $subject with the provided mapping applied.
474
 */
475
function preg_replace_group($map = array(), $subject = '')
476
{
477
  if ($subject)
478
  {
479
    for ($i = 0, $len = count($map); $i < $len; $i++)
480
    {
481
      $subject = preg_replace($map[$i][0], $map[$i][1], $subject);
482
    }
483
  }
484
 
485
  return $subject;
486
}
487
 
488
/**
489
 * Randomly encodes a string of characters.
490
 *
491
 * @param string $s
492
 *   String to be encoded
493
 * @param string $format = 'sgml'
494
 *   Encoding format.  Currently only SGML-based encoding of
495
 *   ASCII characters with character references is supported.
496
 * @return string
497
 */
498
function randomEsc($s = '', $format = 'sgml')
499
{
500
  $f = function_exists('mt_rand') ? 'mt_rand' : 'rand';
501
 
502
  return preg_replace_callback('/[\\x00-\\x7F]/',
503
    create_function('$m', "return $f(0, 1)" . '? $m[0] : "&#" . ord($m[0]) . ";";'),
504
    $s);
505
}
506
 
507
/**
508
 * Reduces sequences of two or more consecutive white-space characters
509
 * in an input to a single space.
510
 *
511
 * @param string $s
512
 * @return string
513
 */
514
function reduceWhitespace($s)
515
{
516
  return preg_replace('/\s{2,}/', ' ', $s);
517
}
518
 
519
function debug($x)
520
{
521
  echo '<pre>';
522
 
523
//   if (is_array($x))
524
//   {
525
//     print_r($x);
526
//   }
527
//   else
528
//   {
529
    var_dump($x);
530
//   }
531
 
532
  echo '</pre>';
533
}