rtMedia for WordPress, BuddyPress and bbPress - Version 3.8.18

Version Description

  • Filter for media action text
  • Updated getid3 lib to latest version
Download this release

Release Info

Developer rtcamp
Plugin Icon 128x128 rtMedia for WordPress, BuddyPress and bbPress
Version 3.8.18
Comparing to
See all releases

Code changes from version 3.8.17 to 3.8.18

Files changed (77) hide show
  1. app/main/controllers/media/RTMediaLike.php +2 -2
  2. app/main/controllers/media/RTMediaUserInteraction.php +96 -74
  3. index.php +1 -1
  4. lib/getid3/extension.cache.dbm.php +8 -10
  5. lib/getid3/extension.cache.mysql.php +43 -26
  6. lib/getid3/extension.cache.sqlite3.php +266 -0
  7. lib/getid3/getid3.lib.php +236 -156
  8. lib/getid3/getid3.php +1790 -1597
  9. lib/getid3/module.archive.gzip.php +12 -11
  10. lib/getid3/module.archive.rar.php +3 -5
  11. lib/getid3/module.archive.szip.php +11 -10
  12. lib/getid3/module.archive.tar.php +11 -12
  13. lib/getid3/module.archive.zip.php +148 -59
  14. lib/getid3/module.audio-video.asf.php +95 -103
  15. lib/getid3/module.audio-video.bink.php +7 -8
  16. lib/getid3/module.audio-video.flv.php +161 -147
  17. lib/getid3/module.audio-video.matroska.php +322 -244
  18. lib/getid3/module.audio-video.mpeg.php +510 -203
  19. lib/getid3/module.audio-video.nsv.php +12 -14
  20. lib/getid3/module.audio-video.quicktime.php +510 -366
  21. lib/getid3/module.audio-video.real.php +14 -16
  22. lib/getid3/module.audio-video.riff.php +742 -565
  23. lib/getid3/module.audio-video.swf.php +5 -7
  24. lib/getid3/module.audio-video.ts.php +79 -0
  25. lib/getid3/module.audio.aa.php +13 -13
  26. lib/getid3/module.audio.aac.php +14 -16
  27. lib/getid3/module.audio.ac3.php +120 -119
  28. lib/getid3/module.audio.amr.php +97 -0
  29. lib/getid3/module.audio.au.php +8 -10
  30. lib/getid3/module.audio.avr.php +4 -6
  31. lib/getid3/module.audio.bonk.php +22 -24
  32. lib/getid3/module.audio.dss.php +46 -28
  33. lib/getid3/module.audio.dts.php +117 -72
  34. lib/getid3/module.audio.flac.php +257 -284
  35. lib/getid3/module.audio.la.php +7 -10
  36. lib/getid3/module.audio.lpac.php +4 -6
  37. lib/getid3/module.audio.midi.php +15 -11
  38. lib/getid3/module.audio.mod.php +16 -18
  39. lib/getid3/module.audio.monkey.php +7 -8
  40. lib/getid3/module.audio.mp3.php +120 -109
  41. lib/getid3/module.audio.mpc.php +22 -24
  42. lib/getid3/module.audio.ogg.php +259 -124
  43. lib/getid3/module.audio.optimfrog.php +31 -33
  44. lib/getid3/module.audio.rkau.php +5 -6
  45. lib/getid3/module.audio.shorten.php +10 -11
  46. lib/getid3/module.audio.tta.php +5 -7
  47. lib/getid3/module.audio.voc.php +26 -28
  48. lib/getid3/module.audio.vqf.php +12 -14
  49. lib/getid3/module.audio.wavpack.php +16 -18
  50. lib/getid3/module.graphic.bmp.php +14 -16
  51. lib/getid3/module.graphic.efax.php +4 -6
  52. lib/getid3/module.graphic.gif.php +15 -17
  53. lib/getid3/module.graphic.jpg.php +27 -27
  54. lib/getid3/module.graphic.pcd.php +14 -15
  55. lib/getid3/module.graphic.png.php +14 -16
  56. lib/getid3/module.graphic.svg.php +4 -6
  57. lib/getid3/module.graphic.tiff.php +19 -21
  58. lib/getid3/module.misc.cue.php +14 -14
  59. lib/getid3/module.misc.exe.php +4 -6
  60. lib/getid3/module.misc.iso.php +18 -19
  61. lib/getid3/module.misc.msoffice.php +5 -7
  62. lib/getid3/module.misc.par2.php +2 -4
  63. lib/getid3/module.misc.pdf.php +2 -4
  64. lib/getid3/module.tag.apetag.php +96 -52
  65. lib/getid3/module.tag.id3v1.php +15 -17
  66. lib/getid3/module.tag.id3v2.php +417 -106
  67. lib/getid3/module.tag.lyrics3.php +20 -19
  68. lib/getid3/module.tag.xmp.php +18 -16
  69. lib/getid3/write.apetag.php +20 -21
  70. lib/getid3/write.id3v1.php +11 -12
  71. lib/getid3/write.id3v2.php +52 -46
  72. lib/getid3/write.lyrics3.php +11 -12
  73. lib/getid3/write.metaflac.php +10 -11
  74. lib/getid3/write.php +25 -32
  75. lib/getid3/write.real.php +19 -20
  76. lib/getid3/write.vorbiscomment.php +10 -11
  77. readme.txt +7 -3
app/main/controllers/media/RTMediaLike.php CHANGED
@@ -96,10 +96,10 @@ class RTMediaLike extends RTMediaUserInteraction {
96
  $actions = intval( $actions[ 0 ]->{$actionwa} );
97
  if ( $this->increase === true ) {
98
  $actions ++;
99
- $return[ "next" ] = $this->undo_label;
100
  } else {
101
  $actions --;
102
- $return[ "next" ] = $this->label;
103
  }
104
  if ( $actions < 0 ) {
105
  $actions = 0;
96
  $actions = intval( $actions[ 0 ]->{$actionwa} );
97
  if ( $this->increase === true ) {
98
  $actions ++;
99
+ $return[ "next" ] = apply_filters( 'rtmedia_' . $this->action . '_label_text', $this->undo_label );
100
  } else {
101
  $actions --;
102
+ $return[ "next" ] = apply_filters( 'rtmedia_' . $this->action . '_label_text', $this->label );
103
  }
104
  if ( $actions < 0 ) {
105
  $actions = 0;
app/main/controllers/media/RTMediaUserInteraction.php CHANGED
@@ -51,49 +51,52 @@ class RTMediaUserInteraction {
51
  * Initialise the user interaction
52
  *
53
  * @global object $rtmedia_query Default query
 
54
  * @param string $action The user action
55
  * @param boolean $private Whether other users are allowed the action
56
  * @param string $label The label for the button
57
  * @param boolean $increase Increase or decrease the action count
58
  */
59
- function __construct($args = array()) {
60
  $defaults = array(
61
- 'action' => '',
62
- 'label' => '',
63
- 'plural' => '',
64
- 'undo_label' => '',
65
- 'privacy' => 60,
66
- 'countable' => false,
67
- 'single' => false,
68
- 'repeatable' => false,
69
- 'undoable' => false,
70
- 'icon_class' => ''
71
  );
72
 
73
- $args = wp_parse_args($args,$defaults);
74
- foreach($args as $key=>$val){
75
  $this->{$key} = $val;
76
  }
77
 
78
 
79
-
80
  $this->init();
81
 
82
 
83
-
84
  // filter the default actions with this new one
85
  add_filter( 'rtmedia_query_actions', array( $this, 'register' ) );
86
  // hook into the template for this action
87
  add_action( 'rtmedia_pre_action_' . $this->action, array( $this, 'preprocess' ) );
88
- add_filter( 'rtmedia_action_buttons_before_delete', array($this,'button_filter') );
89
  }
90
 
91
 
92
- function init(){
93
- $this->model = new RTMediaModel();
94
- global $rtmedia_query;
95
- if(!isset($rtmedia_query->action_query)) return;
96
- if(!isset($rtmedia_query->action_query->id)) return;
 
 
 
 
97
 
98
  $this->set_label();
99
  $this->set_plural();
@@ -106,29 +109,29 @@ class RTMediaUserInteraction {
106
  * Checks if there's a label, if not creates from the action name
107
  */
108
  function set_label() {
109
- if ( empty($this->label) ) {
110
  $this->label = ucfirst( $this->action );
111
  }
112
  }
113
 
114
  function set_plural() {
115
- if ( empty($this->plural) ) {
116
- $this->plural = $this->label .'s';
117
  }
118
  }
119
 
120
  function set_media() {
121
 
122
- $media_id = false;
123
  $this->media = false;
124
 
125
  global $rtmedia_query;
126
  $this->action_query = $rtmedia_query->action_query;
127
 
128
- if (isset( $this->action_query->id ) ){
129
  $media_id = $this->action_query->id;
130
- $media = $this->model->get( array( 'id' => $media_id ) );
131
- if(!empty($media)){
132
  $this->media = $media[0];
133
  $this->owner = $this->media->media_author;
134
  }
@@ -139,100 +142,117 @@ class RTMediaUserInteraction {
139
 
140
  function set_interactor() {
141
  $this->interactor = false;
142
- if( is_user_logged_in()){
143
  $this->interactor = get_current_user_id();
144
  }
145
  $this->interactor_privacy = $this->interactor_privacy();
146
  }
147
 
148
- function interactor_privacy(){
149
 
150
- if(!isset($this->interactor)) return 0;
151
- if($this->interactor === false ) return 0;
152
- if($this->interactor ==$this->owner) return 60;
 
 
 
 
 
 
153
 
154
  $friends = new RTMediaFriends();
155
- $friends = $friends->get_friends_cache($this->interactor);
156
 
157
- if($friends && in_array($this->owner,$friends)) return 40;
 
 
158
 
159
  return 20;
160
  }
161
 
162
- function is_visible(){
163
- if($this->interactor_privacy >= $this->privacy) return true;
 
 
 
164
  return false;
165
  }
166
 
167
- function is_clickable(){
168
  $clickable = false;
169
- if($this->repeatable){
170
  $clickable = true;
171
- if($this->undoable){
172
  $clickable = true;
173
  }
174
- }else{
175
- if($this->undoable){
176
  $clickable = true;
177
  }
178
  }
179
 
180
  return $clickable;
181
  }
182
- function before_render(){
183
 
184
- }
 
 
185
 
186
- function render(){
187
- $before_render = $this->before_render();
188
- if($before_render === false )
189
- return false;
 
190
  $button = $button_start = $button_end = '';
191
- if($this->is_visible()){
192
- $link = trailingslashit(get_rtmedia_permalink($this->media->id)).
193
- $this->action.'/';
194
  $disabled = $icon = '';
195
- if(!$this->is_clickable()){
196
  $disabled = ' disabled';
197
  }
198
-
199
- if( isset( $this->icon_class ) && $this->icon_class != "" ) {
200
- $icon = "<i class='" . $this->icon_class . "'></i>";
201
- }
202
- $button_start = '<form action="'. $link .'">';
203
- $button = '<button type="submit" id="rtmedia-'. $this->action .'-button-'.$this->media->id.'" class="rtmedia-'.$this->action
204
- .' rtmedia-action-buttons button'.$disabled.'">' . $icon . '<span>' . $this->label.'</span></button>';
205
-
206
- //filter the button as required
207
- $button = apply_filters( 'rtmedia_' . $this->action . '_button_filter', $button);
208
-
209
- $button_end = '</form>';
210
-
211
- $button = $button_start . $button . $button_end;
212
-
213
  }
214
 
215
  return $button;
216
  }
217
 
218
- function button_filter($buttons){
219
- if(empty($this->media)){
220
  $this->init();
221
  }
222
  $buttons[] = $this->render();
 
223
  return $buttons;
224
  }
 
225
  /**
226
  *
227
  * @param array $actions The default array of actions
 
228
  * @return array $actions Filtered actions array
229
  */
230
  function register( $actions ) {
231
- if(empty($this->media)){
232
  $this->init();
233
  }
234
 
235
  $actions[ $this->action ] = array( $this->label, false );
 
236
  return $actions;
237
  }
238
 
@@ -246,19 +266,21 @@ class RTMediaUserInteraction {
246
  global $rtmedia_query;
247
  $this->action_query = $rtmedia_query->action_query;
248
 
249
- if ( $this->action_query->action != $this->action )
250
  return false;
 
251
 
252
- if ( ! isset( $this->action_query->id ) )
253
  return false;
 
254
  $result = false;
255
 
256
  do_action( 'rtmedia_pre_process_' . $this->action );
257
- if(empty($this->media)){
258
  $this->init();
259
  }
260
 
261
- if($this->interactor_privacy >=$this->privacy){
262
  $result = $this->process();
263
  }
264
 
51
  * Initialise the user interaction
52
  *
53
  * @global object $rtmedia_query Default query
54
+ *
55
  * @param string $action The user action
56
  * @param boolean $private Whether other users are allowed the action
57
  * @param string $label The label for the button
58
  * @param boolean $increase Increase or decrease the action count
59
  */
60
+ function __construct( $args = array() ) {
61
  $defaults = array(
62
+ 'action' => '',
63
+ 'label' => '',
64
+ 'plural' => '',
65
+ 'undo_label' => '',
66
+ 'privacy' => 60,
67
+ 'countable' => false,
68
+ 'single' => false,
69
+ 'repeatable' => false,
70
+ 'undoable' => false,
71
+ 'icon_class' => ''
72
  );
73
 
74
+ $args = wp_parse_args( $args, $defaults );
75
+ foreach ( $args as $key => $val ) {
76
  $this->{$key} = $val;
77
  }
78
 
79
 
 
80
  $this->init();
81
 
82
 
 
83
  // filter the default actions with this new one
84
  add_filter( 'rtmedia_query_actions', array( $this, 'register' ) );
85
  // hook into the template for this action
86
  add_action( 'rtmedia_pre_action_' . $this->action, array( $this, 'preprocess' ) );
87
+ add_filter( 'rtmedia_action_buttons_before_delete', array( $this, 'button_filter' ) );
88
  }
89
 
90
 
91
+ function init() {
92
+ $this->model = new RTMediaModel();
93
+ global $rtmedia_query;
94
+ if ( ! isset( $rtmedia_query->action_query ) ) {
95
+ return;
96
+ }
97
+ if ( ! isset( $rtmedia_query->action_query->id ) ) {
98
+ return;
99
+ }
100
 
101
  $this->set_label();
102
  $this->set_plural();
109
  * Checks if there's a label, if not creates from the action name
110
  */
111
  function set_label() {
112
+ if ( empty( $this->label ) ) {
113
  $this->label = ucfirst( $this->action );
114
  }
115
  }
116
 
117
  function set_plural() {
118
+ if ( empty( $this->plural ) ) {
119
+ $this->plural = $this->label . 's';
120
  }
121
  }
122
 
123
  function set_media() {
124
 
125
+ $media_id = false;
126
  $this->media = false;
127
 
128
  global $rtmedia_query;
129
  $this->action_query = $rtmedia_query->action_query;
130
 
131
+ if ( isset( $this->action_query->id ) ) {
132
  $media_id = $this->action_query->id;
133
+ $media = $this->model->get( array( 'id' => $media_id ) );
134
+ if ( ! empty( $media ) ) {
135
  $this->media = $media[0];
136
  $this->owner = $this->media->media_author;
137
  }
142
 
143
  function set_interactor() {
144
  $this->interactor = false;
145
+ if ( is_user_logged_in() ) {
146
  $this->interactor = get_current_user_id();
147
  }
148
  $this->interactor_privacy = $this->interactor_privacy();
149
  }
150
 
151
+ function interactor_privacy() {
152
 
153
+ if ( ! isset( $this->interactor ) ) {
154
+ return 0;
155
+ }
156
+ if ( $this->interactor === false ) {
157
+ return 0;
158
+ }
159
+ if ( $this->interactor == $this->owner ) {
160
+ return 60;
161
+ }
162
 
163
  $friends = new RTMediaFriends();
164
+ $friends = $friends->get_friends_cache( $this->interactor );
165
 
166
+ if ( $friends && in_array( $this->owner, $friends ) ) {
167
+ return 40;
168
+ }
169
 
170
  return 20;
171
  }
172
 
173
+ function is_visible() {
174
+ if ( $this->interactor_privacy >= $this->privacy ) {
175
+ return true;
176
+ }
177
+
178
  return false;
179
  }
180
 
181
+ function is_clickable() {
182
  $clickable = false;
183
+ if ( $this->repeatable ) {
184
  $clickable = true;
185
+ if ( $this->undoable ) {
186
  $clickable = true;
187
  }
188
+ } else {
189
+ if ( $this->undoable ) {
190
  $clickable = true;
191
  }
192
  }
193
 
194
  return $clickable;
195
  }
 
196
 
197
+ function before_render() {
198
+
199
+ }
200
 
201
+ function render() {
202
+ $before_render = $this->before_render();
203
+ if ( $before_render === false ) {
204
+ return false;
205
+ }
206
  $button = $button_start = $button_end = '';
207
+ if ( $this->is_visible() ) {
208
+ $link = trailingslashit( get_rtmedia_permalink( $this->media->id ) ) .
209
+ $this->action . '/';
210
  $disabled = $icon = '';
211
+ if ( ! $this->is_clickable() ) {
212
  $disabled = ' disabled';
213
  }
214
+
215
+ if ( isset( $this->icon_class ) && $this->icon_class != "" ) {
216
+ $icon = "<i class='" . $this->icon_class . "'></i>";
217
+ }
218
+ $button_start = '<form action="' . $link . '">';
219
+ $button = '<button type="submit" id="rtmedia-' . $this->action . '-button-' . $this->media->id . '" class="rtmedia-' . $this->action
220
+ . ' rtmedia-action-buttons button' . $disabled . '">' . $icon . '<span>' . apply_filters( 'rtmedia_' . $this->action . '_label_text', $this->label ) . '</span></button>';
221
+
222
+ //filter the button as required
223
+ $button = apply_filters( 'rtmedia_' . $this->action . '_button_filter', $button );
224
+
225
+ $button_end = '</form>';
226
+
227
+ $button = $button_start . $button . $button_end;
228
+
229
  }
230
 
231
  return $button;
232
  }
233
 
234
+ function button_filter( $buttons ) {
235
+ if ( empty( $this->media ) ) {
236
  $this->init();
237
  }
238
  $buttons[] = $this->render();
239
+
240
  return $buttons;
241
  }
242
+
243
  /**
244
  *
245
  * @param array $actions The default array of actions
246
+ *
247
  * @return array $actions Filtered actions array
248
  */
249
  function register( $actions ) {
250
+ if ( empty( $this->media ) ) {
251
  $this->init();
252
  }
253
 
254
  $actions[ $this->action ] = array( $this->label, false );
255
+
256
  return $actions;
257
  }
258
 
266
  global $rtmedia_query;
267
  $this->action_query = $rtmedia_query->action_query;
268
 
269
+ if ( $this->action_query->action != $this->action ) {
270
  return false;
271
+ }
272
 
273
+ if ( ! isset( $this->action_query->id ) ) {
274
  return false;
275
+ }
276
  $result = false;
277
 
278
  do_action( 'rtmedia_pre_process_' . $this->action );
279
+ if ( empty( $this->media ) ) {
280
  $this->init();
281
  }
282
 
283
+ if ( $this->interactor_privacy >= $this->privacy ) {
284
  $result = $this->process();
285
  }
286
 
index.php CHANGED
@@ -4,7 +4,7 @@
4
  Plugin Name: rtMedia for WordPress, BuddyPress and bbPress
5
  Plugin URI: http://rtcamp.com/rtmedia/?utm_source=dashboard&utm_medium=plugin&utm_campaign=buddypress-media
6
  Description: This plugin adds missing media rich features like photos, videos and audio uploading to BuddyPress which are essential if you are building social network, seriously!
7
- Version: 3.8.17
8
  Author: rtCamp
9
  Text Domain: rtmedia
10
  Author URI: http://rtcamp.com/?utm_source=dashboard&utm_medium=plugin&utm_campaign=buddypress-media
4
  Plugin Name: rtMedia for WordPress, BuddyPress and bbPress
5
  Plugin URI: http://rtcamp.com/rtmedia/?utm_source=dashboard&utm_medium=plugin&utm_campaign=buddypress-media
6
  Description: This plugin adds missing media rich features like photos, videos and audio uploading to BuddyPress which are essential if you are building social network, seriously!
7
+ Version: 3.8.18
8
  Author: rtCamp
9
  Text Domain: rtmedia
10
  Author URI: http://rtcamp.com/?utm_source=dashboard&utm_medium=plugin&utm_campaign=buddypress-media
lib/getid3/extension.cache.dbm.php CHANGED
@@ -3,6 +3,7 @@
3
  /// getID3() by James Heinrich <info@getid3.org> //
4
  // available at http://getid3.sourceforge.net //
5
  // or http://www.getid3.org //
 
6
  /////////////////////////////////////////////////////////////////
7
  // //
8
  // extension.cache.dbm.php - part of getID3() //
@@ -10,7 +11,7 @@
10
  // ///
11
  /////////////////////////////////////////////////////////////////
12
  // //
13
- // This extension written by Allan Hansen <ah�artemis*dk> //
14
  // ///
15
  /////////////////////////////////////////////////////////////////
16
 
@@ -73,7 +74,7 @@ class getID3_cached_dbm extends getID3
73
  {
74
 
75
  // public: constructor - see top of this file for cache type and cache_options
76
- function getID3_cached_dbm($cache_type, $dbm_filename, $lock_filename) {
77
 
78
  // Check for dba extension
79
  if (!extension_loaded('dba')) {
@@ -135,13 +136,13 @@ class getID3_cached_dbm extends getID3
135
  $this->clear_cache();
136
  }
137
 
138
- parent::getID3();
139
  }
140
 
141
 
142
 
143
- // public: destuctor
144
- function __destruct() {
145
 
146
  // Close dbm file
147
  dba_close($this->dba);
@@ -156,7 +157,7 @@ class getID3_cached_dbm extends getID3
156
 
157
 
158
  // public: clear cache
159
- function clear_cache() {
160
 
161
  // Close dbm file
162
  dba_close($this->dba);
@@ -178,7 +179,7 @@ class getID3_cached_dbm extends getID3
178
 
179
 
180
  // public: analyze file
181
- function analyze($filename) {
182
 
183
  if (file_exists($filename)) {
184
 
@@ -206,6 +207,3 @@ class getID3_cached_dbm extends getID3
206
  }
207
 
208
  }
209
-
210
-
211
- ?>
3
  /// getID3() by James Heinrich <info@getid3.org> //
4
  // available at http://getid3.sourceforge.net //
5
  // or http://www.getid3.org //
6
+ // also https://github.com/JamesHeinrich/getID3 //
7
  /////////////////////////////////////////////////////////////////
8
  // //
9
  // extension.cache.dbm.php - part of getID3() //
11
  // ///
12
  /////////////////////////////////////////////////////////////////
13
  // //
14
+ // This extension written by Allan Hansen <ahØartemis*dk> //
15
  // ///
16
  /////////////////////////////////////////////////////////////////
17
 
74
  {
75
 
76
  // public: constructor - see top of this file for cache type and cache_options
77
+ public function getID3_cached_dbm($cache_type, $dbm_filename, $lock_filename) {
78
 
79
  // Check for dba extension
80
  if (!extension_loaded('dba')) {
136
  $this->clear_cache();
137
  }
138
 
139
+ parent::__construct();
140
  }
141
 
142
 
143
 
144
+ // public: destructor
145
+ public function __destruct() {
146
 
147
  // Close dbm file
148
  dba_close($this->dba);
157
 
158
 
159
  // public: clear cache
160
+ public function clear_cache() {
161
 
162
  // Close dbm file
163
  dba_close($this->dba);
179
 
180
 
181
  // public: analyze file
182
+ public function analyze($filename) {
183
 
184
  if (file_exists($filename)) {
185
 
207
  }
208
 
209
  }
 
 
 
lib/getid3/extension.cache.mysql.php CHANGED
@@ -3,6 +3,7 @@
3
  /// getID3() by James Heinrich <info@getid3.org> //
4
  // available at http://getid3.sourceforge.net //
5
  // or http://www.getid3.org //
 
6
  /////////////////////////////////////////////////////////////////
7
  // //
8
  // extension.cache.mysql.php - part of getID3() //
@@ -10,8 +11,8 @@
10
  // ///
11
  /////////////////////////////////////////////////////////////////
12
  // //
13
- // This extension written by Allan Hansen <ah�artemis*dk> //
14
- // Table name mod by Carlo Capocasa <calro�carlocapocasa*com> //
15
  // ///
16
  /////////////////////////////////////////////////////////////////
17
 
@@ -74,12 +75,12 @@ class getID3_cached_mysql extends getID3
74
  {
75
 
76
  // private vars
77
- var $cursor;
78
- var $connection;
79
 
80
 
81
  // public: constructor - see top of this file for cache type and cache_options
82
- function getID3_cached_mysql($host, $database, $username, $password, $table='getid3_cache') {
83
 
84
  // Check for mysql support
85
  if (!function_exists('mysql_pconnect')) {
@@ -105,38 +106,49 @@ class getID3_cached_mysql extends getID3
105
 
106
  // Check version number and clear cache if changed
107
  $version = '';
108
- if ($this->cursor = mysql_query("SELECT `value` FROM `".mysql_real_escape_string($this->table)."` WHERE (`filename` = '".mysql_real_escape_string(getID3::VERSION)."') AND (`filesize` = '-1') AND (`filetime` = '-1') AND (`analyzetime` = '-1')", $this->connection)) {
 
 
 
 
 
 
109
  list($version) = mysql_fetch_array($this->cursor);
110
  }
111
  if ($version != getID3::VERSION) {
112
  $this->clear_cache();
113
  }
114
 
115
- parent::getID3();
116
  }
117
 
118
 
119
 
120
  // public: clear cache
121
- function clear_cache() {
122
 
123
- $this->cursor = mysql_query("DELETE FROM `".mysql_real_escape_string($this->table)."`", $this->connection);
124
- $this->cursor = mysql_query("INSERT INTO `".mysql_real_escape_string($this->table)."` VALUES ('".getID3::VERSION."', -1, -1, -1, '".getID3::VERSION."')", $this->connection);
125
  }
126
 
127
 
128
 
129
  // public: analyze file
130
- function analyze($filename) {
131
 
132
  if (file_exists($filename)) {
133
 
134
  // Short-hands
135
  $filetime = filemtime($filename);
136
- $filesize = filesize($filename);
137
 
138
  // Lookup file
139
- $this->cursor = mysql_query("SELECT `value` FROM `".mysql_real_escape_string($this->table)."` WHERE (`filename` = '".mysql_real_escape_string($filename)."') AND (`filesize` = '".mysql_real_escape_string($filesize)."') AND (`filetime` = '".mysql_real_escape_string($filetime)."')", $this->connection);
 
 
 
 
 
140
  if (mysql_num_rows($this->cursor) > 0) {
141
  // Hit
142
  list($result) = mysql_fetch_array($this->cursor);
@@ -145,11 +157,17 @@ class getID3_cached_mysql extends getID3
145
  }
146
 
147
  // Miss
148
- $analysis = parent::analyze($filename);
149
 
150
  // Save result
151
  if (file_exists($filename)) {
152
- $this->cursor = mysql_query("INSERT INTO `".mysql_real_escape_string($this->table)."` (`filename`, `filesize`, `filetime`, `analyzetime`, `value`) VALUES ('".mysql_real_escape_string($filename)."', '".mysql_real_escape_string($filesize)."', '".mysql_real_escape_string($filetime)."', '".mysql_real_escape_string(time())."', '".mysql_real_escape_string(base64_encode(serialize($analysis)))."')", $this->connection);
 
 
 
 
 
 
153
  }
154
  return $analysis;
155
  }
@@ -157,17 +175,16 @@ class getID3_cached_mysql extends getID3
157
 
158
 
159
  // private: (re)create sql table
160
- function create_table($drop=false) {
161
-
162
- $this->cursor = mysql_query("CREATE TABLE IF NOT EXISTS `".mysql_real_escape_string($this->table)."` (
163
- `filename` VARCHAR(255) NOT NULL DEFAULT '',
164
- `filesize` INT(11) NOT NULL DEFAULT '0',
165
- `filetime` INT(11) NOT NULL DEFAULT '0',
166
- `analyzetime` INT(11) NOT NULL DEFAULT '0',
167
- `value` TEXT NOT NULL,
168
- PRIMARY KEY (`filename`,`filesize`,`filetime`)) TYPE=MyISAM", $this->connection);
 
169
  echo mysql_error($this->connection);
170
  }
171
  }
172
-
173
- ?>
3
  /// getID3() by James Heinrich <info@getid3.org> //
4
  // available at http://getid3.sourceforge.net //
5
  // or http://www.getid3.org //
6
+ // also https://github.com/JamesHeinrich/getID3 //
7
  /////////////////////////////////////////////////////////////////
8
  // //
9
  // extension.cache.mysql.php - part of getID3() //
11
  // ///
12
  /////////////////////////////////////////////////////////////////
13
  // //
14
+ // This extension written by Allan Hansen <ahØartemis*dk> //
15
+ // Table name mod by Carlo Capocasa <calroØcarlocapocasa*com> //
16
  // ///
17
  /////////////////////////////////////////////////////////////////
18
 
75
  {
76
 
77
  // private vars
78
+ private $cursor;
79
+ private $connection;
80
 
81
 
82
  // public: constructor - see top of this file for cache type and cache_options
83
+ public function getID3_cached_mysql($host, $database, $username, $password, $table='getid3_cache') {
84
 
85
  // Check for mysql support
86
  if (!function_exists('mysql_pconnect')) {
106
 
107
  // Check version number and clear cache if changed
108
  $version = '';
109
+ $SQLquery = 'SELECT `value`';
110
+ $SQLquery .= ' FROM `'.mysql_real_escape_string($this->table).'`';
111
+ $SQLquery .= ' WHERE (`filename` = \''.mysql_real_escape_string(getID3::VERSION).'\')';
112
+ $SQLquery .= ' AND (`filesize` = -1)';
113
+ $SQLquery .= ' AND (`filetime` = -1)';
114
+ $SQLquery .= ' AND (`analyzetime` = -1)';
115
+ if ($this->cursor = mysql_query($SQLquery, $this->connection)) {
116
  list($version) = mysql_fetch_array($this->cursor);
117
  }
118
  if ($version != getID3::VERSION) {
119
  $this->clear_cache();
120
  }
121
 
122
+ parent::__construct();
123
  }
124
 
125
 
126
 
127
  // public: clear cache
128
+ public function clear_cache() {
129
 
130
+ $this->cursor = mysql_query('DELETE FROM `'.mysql_real_escape_string($this->table).'`', $this->connection);
131
+ $this->cursor = mysql_query('INSERT INTO `'.mysql_real_escape_string($this->table).'` VALUES (\''.getID3::VERSION.'\', -1, -1, -1, \''.getID3::VERSION.'\')', $this->connection);
132
  }
133
 
134
 
135
 
136
  // public: analyze file
137
+ public function analyze($filename, $filesize=null, $original_filename='') {
138
 
139
  if (file_exists($filename)) {
140
 
141
  // Short-hands
142
  $filetime = filemtime($filename);
143
+ $filesize = filesize($filename);
144
 
145
  // Lookup file
146
+ $SQLquery = 'SELECT `value`';
147
+ $SQLquery .= ' FROM `'.mysql_real_escape_string($this->table).'`';
148
+ $SQLquery .= ' WHERE (`filename` = \''.mysql_real_escape_string($filename).'\')';
149
+ $SQLquery .= ' AND (`filesize` = \''.mysql_real_escape_string($filesize).'\')';
150
+ $SQLquery .= ' AND (`filetime` = \''.mysql_real_escape_string($filetime).'\')';
151
+ $this->cursor = mysql_query($SQLquery, $this->connection);
152
  if (mysql_num_rows($this->cursor) > 0) {
153
  // Hit
154
  list($result) = mysql_fetch_array($this->cursor);
157
  }
158
 
159
  // Miss
160
+ $analysis = parent::analyze($filename, $filesize, $original_filename);
161
 
162
  // Save result
163
  if (file_exists($filename)) {
164
+ $SQLquery = 'INSERT INTO `'.mysql_real_escape_string($this->table).'` (`filename`, `filesize`, `filetime`, `analyzetime`, `value`) VALUES (';
165
+ $SQLquery .= '\''.mysql_real_escape_string($filename).'\'';
166
+ $SQLquery .= ', \''.mysql_real_escape_string($filesize).'\'';
167
+ $SQLquery .= ', \''.mysql_real_escape_string($filetime).'\'';
168
+ $SQLquery .= ', \''.mysql_real_escape_string(time() ).'\'';
169
+ $SQLquery .= ', \''.mysql_real_escape_string(base64_encode(serialize($analysis))).'\')';
170
+ $this->cursor = mysql_query($SQLquery, $this->connection);
171
  }
172
  return $analysis;
173
  }
175
 
176
 
177
  // private: (re)create sql table
178
+ private function create_table($drop=false) {
179
+
180
+ $SQLquery = 'CREATE TABLE IF NOT EXISTS `'.mysql_real_escape_string($this->table).'` (';
181
+ $SQLquery .= '`filename` VARCHAR(500) NOT NULL DEFAULT \'\'';
182
+ $SQLquery .= ', `filesize` INT(11) NOT NULL DEFAULT \'0\'';
183
+ $SQLquery .= ', `filetime` INT(11) NOT NULL DEFAULT \'0\'';
184
+ $SQLquery .= ', `analyzetime` INT(11) NOT NULL DEFAULT \'0\'';
185
+ $SQLquery .= ', `value` LONGTEXT NOT NULL';
186
+ $SQLquery .= ', PRIMARY KEY (`filename`, `filesize`, `filetime`)) ENGINE=MyISAM';
187
+ $this->cursor = mysql_query($SQLquery, $this->connection);
188
  echo mysql_error($this->connection);
189
  }
190
  }
 
 
lib/getid3/extension.cache.sqlite3.php ADDED
@@ -0,0 +1,266 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /////////////////////////////////////////////////////////////////////////////////
3
+ /// getID3() by James Heinrich <info@getid3.org> //
4
+ // available at http://getid3.sourceforge.net //
5
+ // or http://www.getid3.org //
6
+ // also https://github.com/JamesHeinrich/getID3 //
7
+ /////////////////////////////////////////////////////////////////////////////////
8
+ /// //
9
+ // extension.cache.sqlite3.php - part of getID3() //
10
+ // Please see readme.txt for more information //
11
+ // ///
12
+ /////////////////////////////////////////////////////////////////////////////////
13
+ /// //
14
+ // MySQL extension written by Allan Hansen <ahØartemis*dk> //
15
+ // Table name mod by Carlo Capocasa <calroØcarlocapocasa*com> //
16
+ // MySQL extension was reworked for SQLite3 by Karl G. Holz <newaeonØmac*com> //
17
+ // ///
18
+ /////////////////////////////////////////////////////////////////////////////////
19
+ /**
20
+ * This is a caching extension for getID3(). It works the exact same
21
+ * way as the getID3 class, but return cached information much faster
22
+ *
23
+ * Normal getID3 usage (example):
24
+ *
25
+ * require_once 'getid3/getid3.php';
26
+ * $getID3 = new getID3;
27
+ * $getID3->encoding = 'UTF-8';
28
+ * $info1 = $getID3->analyze('file1.flac');
29
+ * $info2 = $getID3->analyze('file2.wv');
30
+ *
31
+ * getID3_cached usage:
32
+ *
33
+ * require_once 'getid3/getid3.php';
34
+ * require_once 'getid3/extension.cache.sqlite3.php';
35
+ * // all parameters are optional, defaults are:
36
+ * $getID3 = new getID3_cached_sqlite3($table='getid3_cache', $hide=FALSE);
37
+ * $getID3->encoding = 'UTF-8';
38
+ * $info1 = $getID3->analyze('file1.flac');
39
+ * $info2 = $getID3->analyze('file2.wv');
40
+ *
41
+ *
42
+ * Supported Cache Types (this extension)
43
+ *
44
+ * SQL Databases:
45
+ *
46
+ * cache_type cache_options
47
+ * -------------------------------------------------------------------
48
+ * mysql host, database, username, password
49
+ *
50
+ * sqlite3 table='getid3_cache', hide=false (PHP5)
51
+ *
52
+ *
53
+ * *** database file will be stored in the same directory as this script,
54
+ * *** webserver must have write access to that directory!
55
+ * *** set $hide to TRUE to prefix db file with .ht to pervent access from web client
56
+ * *** this is a default setting in the Apache configuration:
57
+ *
58
+ * The following lines prevent .htaccess and .htpasswd files from being viewed by Web clients.
59
+ *
60
+ * <Files ~ "^\.ht">
61
+ * Order allow,deny
62
+ * Deny from all
63
+ * Satisfy all
64
+ * </Files>
65
+ *
66
+ ********************************************************************************
67
+ *
68
+ * -------------------------------------------------------------------
69
+ * DBM-Style Databases: (use extension.cache.dbm)
70
+ *
71
+ * cache_type cache_options
72
+ * -------------------------------------------------------------------
73
+ * gdbm dbm_filename, lock_filename
74
+ * ndbm dbm_filename, lock_filename
75
+ * db2 dbm_filename, lock_filename
76
+ * db3 dbm_filename, lock_filename
77
+ * db4 dbm_filename, lock_filename (PHP5 required)
78
+ *
79
+ * PHP must have write access to both dbm_filename and lock_filename.
80
+ *
81
+ * Recommended Cache Types
82
+ *
83
+ * Infrequent updates, many reads any DBM
84
+ * Frequent updates mysql
85
+ ********************************************************************************
86
+ *
87
+ * IMHO this is still a bit slow, I'm using this with MP4/MOV/ M4v files
88
+ * there is a plan to add directory scanning and analyzing to make things work much faster
89
+ *
90
+ *
91
+ */
92
+ class getID3_cached_sqlite3 extends getID3 {
93
+
94
+ /**
95
+ * __construct()
96
+ * @param string $table holds name of sqlite table
97
+ * @return type
98
+ */
99
+ public function __construct($table='getid3_cache', $hide=false) {
100
+ $this->table = $table; // Set table
101
+ $file = dirname(__FILE__).'/'.basename(__FILE__, 'php').'sqlite';
102
+ if ($hide) {
103
+ $file = dirname(__FILE__).'/.ht.'.basename(__FILE__, 'php').'sqlite';
104
+ }
105
+ $this->db = new SQLite3($file);
106
+ $db = $this->db;
107
+ $this->create_table(); // Create cache table if not exists
108
+ $version = '';
109
+ $sql = $this->version_check;
110
+ $stmt = $db->prepare($sql);
111
+ $stmt->bindValue(':filename', getID3::VERSION, SQLITE3_TEXT);
112
+ $result = $stmt->execute();
113
+ list($version) = $result->fetchArray();
114
+ if ($version != getID3::VERSION) { // Check version number and clear cache if changed
115
+ $this->clear_cache();
116
+ }
117
+ return parent::__construct();
118
+ }
119
+
120
+ /**
121
+ * close the database connection
122
+ */
123
+ public function __destruct() {
124
+ $db=$this->db;
125
+ $db->close();
126
+ }
127
+
128
+ /**
129
+ * hold the sqlite db
130
+ * @var SQLite Resource
131
+ */
132
+ private $db;
133
+
134
+ /**
135
+ * table to use for caching
136
+ * @var string $table
137
+ */
138
+ private $table;
139
+
140
+ /**
141
+ * clear the cache
142
+ * @access private
143
+ * @return type
144
+ */
145
+ private function clear_cache() {
146
+ $db = $this->db;
147
+ $sql = $this->delete_cache;
148
+ $db->exec($sql);
149
+ $sql = $this->set_version;
150
+ $stmt = $db->prepare($sql);
151
+ $stmt->bindValue(':filename', getID3::VERSION, SQLITE3_TEXT);
152
+ $stmt->bindValue(':dirname', getID3::VERSION, SQLITE3_TEXT);
153
+ $stmt->bindValue(':val', getID3::VERSION, SQLITE3_TEXT);
154
+ return $stmt->execute();
155
+ }
156
+
157
+ /**
158
+ * analyze file and cache them, if cached pull from the db
159
+ * @param type $filename
160
+ * @return boolean
161
+ */
162
+ public function analyze($filename, $filesize=null, $original_filename='') {
163
+ if (!file_exists($filename)) {
164
+ return false;
165
+ }
166
+ // items to track for caching
167
+ $filetime = filemtime($filename);
168
+ $filesize = filesize($filename);
169
+ // this will be saved for a quick directory lookup of analized files
170
+ // ... why do 50 seperate sql quries when you can do 1 for the same result
171
+ $dirname = dirname($filename);
172
+ // Lookup file
173
+ $db = $this->db;
174
+ $sql = $this->get_id3_data;
175
+ $stmt = $db->prepare($sql);
176
+ $stmt->bindValue(':filename', $filename, SQLITE3_TEXT);
177
+ $stmt->bindValue(':filesize', $filesize, SQLITE3_INTEGER);
178
+ $stmt->bindValue(':filetime', $filetime, SQLITE3_INTEGER);
179
+ $res = $stmt->execute();
180
+ list($result) = $res->fetchArray();
181
+ if (count($result) > 0 ) {
182
+ return unserialize(base64_decode($result));
183
+ }
184
+ // if it hasn't been analyzed before, then do it now
185
+ $analysis = parent::analyze($filename, $filesize=null, $original_filename='');
186
+ // Save result
187
+ $sql = $this->cache_file;
188
+ $stmt = $db->prepare($sql);
189
+ $stmt->bindValue(':filename', $filename, SQLITE3_TEXT);
190
+ $stmt->bindValue(':dirname', $dirname, SQLITE3_TEXT);
191
+ $stmt->bindValue(':filesize', $filesize, SQLITE3_INTEGER);
192
+ $stmt->bindValue(':filetime', $filetime, SQLITE3_INTEGER);
193
+ $stmt->bindValue(':atime', time(), SQLITE3_INTEGER);
194
+ $stmt->bindValue(':val', base64_encode(serialize($analysis)), SQLITE3_TEXT);
195
+ $res = $stmt->execute();
196
+ return $analysis;
197
+ }
198
+
199
+ /**
200
+ * create data base table
201
+ * this is almost the same as MySQL, with the exception of the dirname being added
202
+ * @return type
203
+ */
204
+ private function create_table() {
205
+ $db = $this->db;
206
+ $sql = $this->make_table;
207
+ return $db->exec($sql);
208
+ }
209
+
210
+ /**
211
+ * get cached directory
212
+ *
213
+ * This function is not in the MySQL extention, it's ment to speed up requesting multiple files
214
+ * which is ideal for podcasting, playlists, etc.
215
+ *
216
+ * @access public
217
+ * @param string $dir directory to search the cache database for
218
+ * @return array return an array of matching id3 data
219
+ */
220
+ public function get_cached_dir($dir) {
221
+ $db = $this->db;
222
+ $rows = array();
223
+ $sql = $this->get_cached_dir;
224
+ $stmt = $db->prepare($sql);
225
+ $stmt->bindValue(':dirname', $dir, SQLITE3_TEXT);
226
+ $res = $stmt->execute();
227
+ while ($row=$res->fetchArray()) {
228
+ $rows[] = unserialize(base64_decode($row));
229
+ }
230
+ return $rows;
231
+ }
232
+
233
+ /**
234
+ * use the magical __get() for sql queries
235
+ *
236
+ * access as easy as $this->{case name}, returns NULL if query is not found
237
+ */
238
+ public function __get($name) {
239
+ switch($name) {
240
+ case 'version_check':
241
+ return "SELECT val FROM $this->table WHERE filename = :filename AND filesize = '-1' AND filetime = '-1' AND analyzetime = '-1'";
242
+ break;
243
+ case 'delete_cache':
244
+ return "DELETE FROM $this->table";
245
+ break;
246
+ case 'set_version':
247
+ return "INSERT INTO $this->table (filename, dirname, filesize, filetime, analyzetime, val) VALUES (:filename, :dirname, -1, -1, -1, :val)";
248
+ break;
249
+ case 'get_id3_data':
250
+ return "SELECT val FROM $this->table WHERE filename = :filename AND filesize = :filesize AND filetime = :filetime";
251
+ break;
252
+ case 'cache_file':
253
+ return "INSERT INTO $this->table (filename, dirname, filesize, filetime, analyzetime, val) VALUES (:filename, :dirname, :filesize, :filetime, :atime, :val)";
254
+ break;
255
+ case 'make_table':
256
+ //return "CREATE TABLE IF NOT EXISTS $this->table (filename VARCHAR(255) NOT NULL DEFAULT '', dirname VARCHAR(255) NOT NULL DEFAULT '', filesize INT(11) NOT NULL DEFAULT '0', filetime INT(11) NOT NULL DEFAULT '0', analyzetime INT(11) NOT NULL DEFAULT '0', val text not null, PRIMARY KEY (filename, filesize, filetime))";
257
+ return "CREATE TABLE IF NOT EXISTS $this->table (filename VARCHAR(255) DEFAULT '', dirname VARCHAR(255) DEFAULT '', filesize INT(11) DEFAULT '0', filetime INT(11) DEFAULT '0', analyzetime INT(11) DEFAULT '0', val text, PRIMARY KEY (filename, filesize, filetime))";
258
+ break;
259
+ case 'get_cached_dir':
260
+ return "SELECT val FROM $this->table WHERE dirname = :dirname";
261
+ break;
262
+ }
263
+ return null;
264
+ }
265
+
266
+ }
lib/getid3/getid3.lib.php CHANGED
@@ -3,6 +3,7 @@
3
  /// getID3() by James Heinrich <info@getid3.org> //
4
  // available at http://getid3.sourceforge.net //
5
  // or http://www.getid3.org //
 
6
  /////////////////////////////////////////////////////////////////
7
  // //
8
  // getid3.lib.php - part of getID3() //
@@ -14,13 +15,13 @@
14
  class getid3_lib
15
  {
16
 
17
- static function PrintHexBytes($string, $hex=true, $spaces=true, $htmlencoding='UTF-8') {
18
  $returnstring = '';
19
  for ($i = 0; $i < strlen($string); $i++) {
20
  if ($hex) {
21
  $returnstring .= str_pad(dechex(ord($string{$i})), 2, '0', STR_PAD_LEFT);
22
  } else {
23
- $returnstring .= ' '.(preg_match("#[\x20-\x7E]#", $string{$i}) ? $string{$i} : '');
24
  }
25
  if ($spaces) {
26
  $returnstring .= ' ';
@@ -35,7 +36,7 @@ class getid3_lib
35
  return $returnstring;
36
  }
37
 
38
- static function trunc($floatnumber) {
39
  // truncates a floating-point number at the decimal point
40
  // returns int (if possible, otherwise float)
41
  if ($floatnumber >= 1) {
@@ -45,14 +46,14 @@ class getid3_lib
45
  } else {
46
  $truncatednumber = 0;
47
  }
48
- if (getid3_lib::intValueSupported($truncatednumber)) {
49
  $truncatednumber = (int) $truncatednumber;
50
  }
51
  return $truncatednumber;
52
  }
53
 
54
 
55
- static function safe_inc(&$variable, $increment=1) {
56
  if (isset($variable)) {
57
  $variable += $increment;
58
  } else {
@@ -61,14 +62,14 @@ class getid3_lib
61
  return true;
62
  }
63
 
64
- static function CastAsInt($floatnum) {
65
  // convert to float if not already
66
  $floatnum = (float) $floatnum;
67
 
68
  // convert a float to type int, only if possible
69
- if (getid3_lib::trunc($floatnum) == $floatnum) {
70
  // it's not floating point
71
- if (getid3_lib::intValueSupported($floatnum)) {
72
  // it's within int range
73
  $floatnum = (int) $floatnum;
74
  }
@@ -92,20 +93,20 @@ class getid3_lib
92
  return false;
93
  }
94
 
95
- static function DecimalizeFraction($fraction) {
96
  list($numerator, $denominator) = explode('/', $fraction);
97
  return $numerator / ($denominator ? $denominator : 1);
98
  }
99
 
100
 
101
- static function DecimalBinary2Float($binarynumerator) {
102
- $numerator = getid3_lib::Bin2Dec($binarynumerator);
103
- $denominator = getid3_lib::Bin2Dec('1'.str_repeat('0', strlen($binarynumerator)));
104
  return ($numerator / $denominator);
105
  }
106
 
107
 
108
- static function NormalizeBinaryPoint($binarypointnumber, $maxbits=52) {
109
  // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
110
  if (strpos($binarypointnumber, '.') === false) {
111
  $binarypointnumber = '0.'.$binarypointnumber;
@@ -129,23 +130,23 @@ class getid3_lib
129
  }
130
 
131
 
132
- static function Float2BinaryDecimal($floatvalue) {
133
  // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
134
  $maxbits = 128; // to how many bits of precision should the calculations be taken?
135
- $intpart = getid3_lib::trunc($floatvalue);
136
  $floatpart = abs($floatvalue - $intpart);
137
  $pointbitstring = '';
138
  while (($floatpart != 0) && (strlen($pointbitstring) < $maxbits)) {
139
  $floatpart *= 2;
140
- $pointbitstring .= (string) getid3_lib::trunc($floatpart);
141
- $floatpart -= getid3_lib::trunc($floatpart);
142
  }
143
  $binarypointnumber = decbin($intpart).'.'.$pointbitstring;
144
  return $binarypointnumber;
145
  }
146
 
147
 
148
- static function Float2String($floatvalue, $bits) {
149
  // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee-expl.html
150
  switch ($bits) {
151
  case 32:
@@ -167,26 +168,26 @@ class getid3_lib
167
  } else {
168
  $signbit = '1';
169
  }
170
- $normalizedbinary = getid3_lib::NormalizeBinaryPoint(getid3_lib::Float2BinaryDecimal($floatvalue), $fractionbits);
171
  $biasedexponent = pow(2, $exponentbits - 1) - 1 + $normalizedbinary['exponent']; // (127 or 1023) +/- exponent
172
  $exponentbitstring = str_pad(decbin($biasedexponent), $exponentbits, '0', STR_PAD_LEFT);
173
  $fractionbitstring = str_pad(substr($normalizedbinary['normalized'], 2), $fractionbits, '0', STR_PAD_RIGHT);
174
 
175
- return getid3_lib::BigEndian2String(getid3_lib::Bin2Dec($signbit.$exponentbitstring.$fractionbitstring), $bits % 8, false);
176
  }
177
 
178
 
179
- static function LittleEndian2Float($byteword) {
180
- return getid3_lib::BigEndian2Float(strrev($byteword));
181
  }
182
 
183
 
184
- static function BigEndian2Float($byteword) {
185
  // ANSI/IEEE Standard 754-1985, Standard for Binary Floating Point Arithmetic
186
  // http://www.psc.edu/general/software/packages/ieee/ieee.html
187
  // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee.html
188
 
189
- $bitword = getid3_lib::BigEndian2Bin($byteword);
190
  if (!$bitword) {
191
  return 0;
192
  }
@@ -209,8 +210,8 @@ class getid3_lib
209
  $exponentstring = substr($bitword, 1, 15);
210
  $isnormalized = intval($bitword{16});
211
  $fractionstring = substr($bitword, 17, 63);
212
- $exponent = pow(2, getid3_lib::Bin2Dec($exponentstring) - 16383);
213
- $fraction = $isnormalized + getid3_lib::DecimalBinary2Float($fractionstring);
214
  $floatvalue = $exponent * $fraction;
215
  if ($signbit == '1') {
216
  $floatvalue *= -1;
@@ -224,8 +225,8 @@ class getid3_lib
224
  }
225
  $exponentstring = substr($bitword, 1, $exponentbits);
226
  $fractionstring = substr($bitword, $exponentbits + 1, $fractionbits);
227
- $exponent = getid3_lib::Bin2Dec($exponentstring);
228
- $fraction = getid3_lib::Bin2Dec($fractionstring);
229
 
230
  if (($exponent == (pow(2, $exponentbits) - 1)) && ($fraction != 0)) {
231
  // Not a Number
@@ -245,12 +246,12 @@ class getid3_lib
245
  $floatvalue = ($signbit ? 0 : -0);
246
  } elseif (($exponent == 0) && ($fraction != 0)) {
247
  // These are 'unnormalized' values
248
- $floatvalue = pow(2, (-1 * (pow(2, $exponentbits - 1) - 2))) * getid3_lib::DecimalBinary2Float($fractionstring);
249
  if ($signbit == '1') {
250
  $floatvalue *= -1;
251
  }
252
  } elseif ($exponent != 0) {
253
- $floatvalue = pow(2, ($exponent - (pow(2, $exponentbits - 1) - 1))) * (1 + getid3_lib::DecimalBinary2Float($fractionstring));
254
  if ($signbit == '1') {
255
  $floatvalue *= -1;
256
  }
@@ -259,7 +260,7 @@ class getid3_lib
259
  }
260
 
261
 
262
- static function BigEndian2Int($byteword, $synchsafe=false, $signed=false) {
263
  $intvalue = 0;
264
  $bytewordlen = strlen($byteword);
265
  if ($bytewordlen == 0) {
@@ -281,20 +282,19 @@ class getid3_lib
281
  $intvalue = 0 - ($intvalue & ($signMaskBit - 1));
282
  }
283
  } else {
284
- throw new Exception('ERROR: Cannot have signed integers larger than '.(8 * PHP_INT_SIZE).'-bits ('.strlen($byteword).') in getid3_lib::BigEndian2Int()');
285
- break;
286
  }
287
  }
288
- return getid3_lib::CastAsInt($intvalue);
289
  }
290
 
291
 
292
- static function LittleEndian2Int($byteword, $signed=false) {
293
- return getid3_lib::BigEndian2Int(strrev($byteword), false, $signed);
294
  }
295
 
296
 
297
- static function BigEndian2Bin($byteword) {
298
  $binvalue = '';
299
  $bytewordlen = strlen($byteword);
300
  for ($i = 0; $i < $bytewordlen; $i++) {
@@ -304,15 +304,15 @@ class getid3_lib
304
  }
305
 
306
 
307
- static function BigEndian2String($number, $minbytes=1, $synchsafe=false, $signed=false) {
308
  if ($number < 0) {
309
- throw new Exception('ERROR: getid3_lib::BigEndian2String() does not support negative numbers');
310
  }
311
  $maskbyte = (($synchsafe || $signed) ? 0x7F : 0xFF);
312
  $intstring = '';
313
  if ($signed) {
314
  if ($minbytes > PHP_INT_SIZE) {
315
- throw new Exception('ERROR: Cannot have signed integers larger than '.(8 * PHP_INT_SIZE).'-bits in getid3_lib::BigEndian2String()');
316
  }
317
  $number = $number & (0x80 << (8 * ($minbytes - 1)));
318
  }
@@ -325,7 +325,7 @@ class getid3_lib
325
  }
326
 
327
 
328
- static function Dec2Bin($number) {
329
  while ($number >= 256) {
330
  $bytes[] = (($number / 256) - (floor($number / 256))) * 256;
331
  $number = floor($number / 256);
@@ -339,7 +339,7 @@ class getid3_lib
339
  }
340
 
341
 
342
- static function Bin2Dec($binstring, $signed=false) {
343
  $signmult = 1;
344
  if ($signed) {
345
  if ($binstring{0} == '1') {
@@ -351,22 +351,22 @@ class getid3_lib
351
  for ($i = 0; $i < strlen($binstring); $i++) {
352
  $decvalue += ((int) substr($binstring, strlen($binstring) - $i - 1, 1)) * pow(2, $i);
353
  }
354
- return getid3_lib::CastAsInt($decvalue * $signmult);
355
  }
356
 
357
 
358
- static function Bin2String($binstring) {
359
  // return 'hi' for input of '0110100001101001'
360
  $string = '';
361
  $binstringreversed = strrev($binstring);
362
  for ($i = 0; $i < strlen($binstringreversed); $i += 8) {
363
- $string = chr(getid3_lib::Bin2Dec(strrev(substr($binstringreversed, $i, 8)))).$string;
364
  }
365
  return $string;
366
  }
367
 
368
 
369
- static function LittleEndian2String($number, $minbytes=1, $synchsafe=false) {
370
  $intstring = '';
371
  while ($number > 0) {
372
  if ($synchsafe) {
@@ -381,8 +381,8 @@ class getid3_lib
381
  }
382
 
383
 
384
- static function array_merge_clobber($array1, $array2) {
385
- // written by kc�hireability*com
386
  // taken from http://www.php.net/manual/en/function.array-merge-recursive.php
387
  if (!is_array($array1) || !is_array($array2)) {
388
  return false;
@@ -390,7 +390,7 @@ class getid3_lib
390
  $newarray = $array1;
391
  foreach ($array2 as $key => $val) {
392
  if (is_array($val) && isset($newarray[$key]) && is_array($newarray[$key])) {
393
- $newarray[$key] = getid3_lib::array_merge_clobber($newarray[$key], $val);
394
  } else {
395
  $newarray[$key] = $val;
396
  }
@@ -399,14 +399,14 @@ class getid3_lib
399
  }
400
 
401
 
402
- static function array_merge_noclobber($array1, $array2) {
403
  if (!is_array($array1) || !is_array($array2)) {
404
  return false;
405
  }
406
  $newarray = $array1;
407
  foreach ($array2 as $key => $val) {
408
  if (is_array($val) && isset($newarray[$key]) && is_array($newarray[$key])) {
409
- $newarray[$key] = getid3_lib::array_merge_noclobber($newarray[$key], $val);
410
  } elseif (!isset($newarray[$key])) {
411
  $newarray[$key] = $val;
412
  }
@@ -414,8 +414,22 @@ class getid3_lib
414
  return $newarray;
415
  }
416
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
417
 
418
- static function ksort_recursive(&$theArray) {
419
  ksort($theArray);
420
  foreach ($theArray as $key => $value) {
421
  if (is_array($value)) {
@@ -425,7 +439,7 @@ class getid3_lib
425
  return true;
426
  }
427
 
428
- static function fileextension($filename, $numextensions=1) {
429
  if (strstr($filename, '.')) {
430
  $reversedfilename = strrev($filename);
431
  $offset = 0;
@@ -441,58 +455,56 @@ class getid3_lib
441
  }
442
 
443
 
444
- static function PlaytimeString($seconds) {
445
  $sign = (($seconds < 0) ? '-' : '');
446
- $seconds = abs($seconds);
447
- $H = floor( $seconds / 3600);
448
- $M = floor(($seconds - (3600 * $H) ) / 60);
449
- $S = round( $seconds - (3600 * $H) - (60 * $M) );
450
  return $sign.($H ? $H.':' : '').($H ? str_pad($M, 2, '0', STR_PAD_LEFT) : intval($M)).':'.str_pad($S, 2, 0, STR_PAD_LEFT);
451
  }
452
 
453
 
454
- static function DateMac2Unix($macdate) {
455
  // Macintosh timestamp: seconds since 00:00h January 1, 1904
456
  // UNIX timestamp: seconds since 00:00h January 1, 1970
457
- return getid3_lib::CastAsInt($macdate - 2082844800);
458
  }
459
 
460
 
461
- static function FixedPoint8_8($rawdata) {
462
- return getid3_lib::BigEndian2Int(substr($rawdata, 0, 1)) + (float) (getid3_lib::BigEndian2Int(substr($rawdata, 1, 1)) / pow(2, 8));
463
  }
464
 
465
 
466
- static function FixedPoint16_16($rawdata) {
467
- return getid3_lib::BigEndian2Int(substr($rawdata, 0, 2)) + (float) (getid3_lib::BigEndian2Int(substr($rawdata, 2, 2)) / pow(2, 16));
468
  }
469
 
470
 
471
- static function FixedPoint2_30($rawdata) {
472
- $binarystring = getid3_lib::BigEndian2Bin($rawdata);
473
- return getid3_lib::Bin2Dec(substr($binarystring, 0, 2)) + (float) (getid3_lib::Bin2Dec(substr($binarystring, 2, 30)) / pow(2, 30));
474
  }
475
 
476
 
477
- static function CreateDeepArray($ArrayPath, $Separator, $Value) {
478
  // assigns $Value to a nested array path:
479
- // $foo = getid3_lib::CreateDeepArray('/path/to/my', '/', 'file.txt')
480
  // is the same as:
481
  // $foo = array('path'=>array('to'=>'array('my'=>array('file.txt'))));
482
  // or
483
  // $foo['path']['to']['my'] = 'file.txt';
484
- while ($ArrayPath && ($ArrayPath{0} == $Separator)) {
485
- $ArrayPath = substr($ArrayPath, 1);
486
- }
487
  if (($pos = strpos($ArrayPath, $Separator)) !== false) {
488
- $ReturnedArray[substr($ArrayPath, 0, $pos)] = getid3_lib::CreateDeepArray(substr($ArrayPath, $pos + 1), $Separator, $Value);
489
  } else {
490
  $ReturnedArray[$ArrayPath] = $Value;
491
  }
492
  return $ReturnedArray;
493
  }
494
 
495
- static function array_max($arraydata, $returnkey=false) {
496
  $maxvalue = false;
497
  $maxkey = false;
498
  foreach ($arraydata as $key => $value) {
@@ -506,7 +518,7 @@ class getid3_lib
506
  return ($returnkey ? $maxkey : $maxvalue);
507
  }
508
 
509
- static function array_min($arraydata, $returnkey=false) {
510
  $minvalue = false;
511
  $minkey = false;
512
  foreach ($arraydata as $key => $value) {
@@ -520,17 +532,20 @@ class getid3_lib
520
  return ($returnkey ? $minkey : $minvalue);
521
  }
522
 
523
- static function XML2array($XMLstring) {
524
- if (function_exists('simplexml_load_string')) {
525
- if (function_exists('get_object_vars')) {
526
- $XMLobject = simplexml_load_string($XMLstring);
527
- return self::SimpleXMLelement2array($XMLobject);
528
- }
 
 
 
529
  }
530
  return false;
531
  }
532
 
533
- static function SimpleXMLelement2array($XMLobject) {
534
  if (!is_object($XMLobject) && !is_array($XMLobject)) {
535
  return $XMLobject;
536
  }
@@ -542,11 +557,11 @@ class getid3_lib
542
  }
543
 
544
 
545
- // Allan Hansen <ah�artemis*dk>
546
- // getid3_lib::md5_data() - returns md5sum for a file from startuing position to absolute end position
547
- static function hash_data($file, $offset, $end, $algorithm) {
548
  static $tempdir = '';
549
- if (!getid3_lib::intValueSupported($end)) {
550
  return false;
551
  }
552
  switch ($algorithm) {
@@ -565,7 +580,7 @@ class getid3_lib
565
  break;
566
 
567
  default:
568
- throw new Exception('Invalid algorithm ('.$algorithm.') in getid3_lib::hash_data()');
569
  break;
570
  }
571
  $size = $end - $offset;
@@ -582,10 +597,10 @@ class getid3_lib
582
  foreach ($RequiredFiles as $required_file) {
583
  if (!is_readable(GETID3_HELPERAPPSDIR.$required_file)) {
584
  // helper apps not available - fall back to old method
585
- break;
586
  }
587
  }
588
- $commandline = GETID3_HELPERAPPSDIR.'head.exe -c '.$end.' "'.escapeshellarg(str_replace('/', DIRECTORY_SEPARATOR, $file)).'" | ';
589
  $commandline .= GETID3_HELPERAPPSDIR.'tail.exe -c '.$size.' | ';
590
  $commandline .= GETID3_HELPERAPPSDIR.$windows_call;
591
 
@@ -621,22 +636,22 @@ class getid3_lib
621
 
622
  // copy parts of file
623
  try {
624
- getid3_lib::CopyFileParts($file, $data_filename, $offset, $end - $offset);
625
  $result = $hash_function($data_filename);
626
  } catch (Exception $e) {
627
- throw new Exception('getid3_lib::CopyFileParts() failed in getid_lib::hash_data(): '.$e->getMessage());
628
  }
629
  unlink($data_filename);
630
  return $result;
631
  }
632
 
633
- static function CopyFileParts($filename_source, $filename_dest, $offset, $length) {
634
- if (!getid3_lib::intValueSupported($offset + $length)) {
635
  throw new Exception('cannot copy file portion, it extends beyond the '.round(PHP_INT_MAX / 1073741824).'GB limit');
636
  }
637
  if (is_readable($filename_source) && is_file($filename_source) && ($fp_src = fopen($filename_source, 'rb'))) {
638
  if (($fp_dest = fopen($filename_dest, 'wb'))) {
639
- if (fseek($fp_src, $offset, SEEK_SET) == 0) {
640
  $byteslefttowrite = $length;
641
  while (($byteslefttowrite > 0) && ($buffer = fread($fp_src, min($byteslefttowrite, getID3::FREAD_BUFFER_SIZE)))) {
642
  $byteswritten = fwrite($fp_dest, $buffer, $byteslefttowrite);
@@ -657,7 +672,7 @@ class getid3_lib
657
  return false;
658
  }
659
 
660
- static function iconv_fallback_int_utf8($charval) {
661
  if ($charval < 128) {
662
  // 0bbbbbbb
663
  $newcharstring = chr($charval);
@@ -681,7 +696,7 @@ class getid3_lib
681
  }
682
 
683
  // ISO-8859-1 => UTF-8
684
- static function iconv_fallback_iso88591_utf8($string, $bom=false) {
685
  if (function_exists('utf8_encode')) {
686
  return utf8_encode($string);
687
  }
@@ -692,13 +707,13 @@ class getid3_lib
692
  }
693
  for ($i = 0; $i < strlen($string); $i++) {
694
  $charval = ord($string{$i});
695
- $newcharstring .= getid3_lib::iconv_fallback_int_utf8($charval);
696
  }
697
  return $newcharstring;
698
  }
699
 
700
  // ISO-8859-1 => UTF-16BE
701
- static function iconv_fallback_iso88591_utf16be($string, $bom=false) {
702
  $newcharstring = '';
703
  if ($bom) {
704
  $newcharstring .= "\xFE\xFF";
@@ -710,7 +725,7 @@ class getid3_lib
710
  }
711
 
712
  // ISO-8859-1 => UTF-16LE
713
- static function iconv_fallback_iso88591_utf16le($string, $bom=false) {
714
  $newcharstring = '';
715
  if ($bom) {
716
  $newcharstring .= "\xFF\xFE";
@@ -722,12 +737,12 @@ class getid3_lib
722
  }
723
 
724
  // ISO-8859-1 => UTF-16LE (BOM)
725
- static function iconv_fallback_iso88591_utf16($string) {
726
- return getid3_lib::iconv_fallback_iso88591_utf16le($string, true);
727
  }
728
 
729
  // UTF-8 => ISO-8859-1
730
- static function iconv_fallback_utf8_iso88591($string) {
731
  if (function_exists('utf8_decode')) {
732
  return utf8_decode($string);
733
  }
@@ -771,7 +786,7 @@ class getid3_lib
771
  }
772
 
773
  // UTF-8 => UTF-16BE
774
- static function iconv_fallback_utf8_utf16be($string, $bom=false) {
775
  $newcharstring = '';
776
  if ($bom) {
777
  $newcharstring .= "\xFE\xFF";
@@ -807,14 +822,14 @@ class getid3_lib
807
  $offset += 1;
808
  }
809
  if ($charval !== false) {
810
- $newcharstring .= (($charval < 65536) ? getid3_lib::BigEndian2String($charval, 2) : "\x00".'?');
811
  }
812
  }
813
  return $newcharstring;
814
  }
815
 
816
  // UTF-8 => UTF-16LE
817
- static function iconv_fallback_utf8_utf16le($string, $bom=false) {
818
  $newcharstring = '';
819
  if ($bom) {
820
  $newcharstring .= "\xFF\xFE";
@@ -850,96 +865,96 @@ class getid3_lib
850
  $offset += 1;
851
  }
852
  if ($charval !== false) {
853
- $newcharstring .= (($charval < 65536) ? getid3_lib::LittleEndian2String($charval, 2) : '?'."\x00");
854
  }
855
  }
856
  return $newcharstring;
857
  }
858
 
859
  // UTF-8 => UTF-16LE (BOM)
860
- static function iconv_fallback_utf8_utf16($string) {
861
- return getid3_lib::iconv_fallback_utf8_utf16le($string, true);
862
  }
863
 
864
  // UTF-16BE => UTF-8
865
- static function iconv_fallback_utf16be_utf8($string) {
866
  if (substr($string, 0, 2) == "\xFE\xFF") {
867
  // strip BOM
868
  $string = substr($string, 2);
869
  }
870
  $newcharstring = '';
871
  for ($i = 0; $i < strlen($string); $i += 2) {
872
- $charval = getid3_lib::BigEndian2Int(substr($string, $i, 2));
873
- $newcharstring .= getid3_lib::iconv_fallback_int_utf8($charval);
874
  }
875
  return $newcharstring;
876
  }
877
 
878
  // UTF-16LE => UTF-8
879
- static function iconv_fallback_utf16le_utf8($string) {
880
  if (substr($string, 0, 2) == "\xFF\xFE") {
881
  // strip BOM
882
  $string = substr($string, 2);
883
  }
884
  $newcharstring = '';
885
  for ($i = 0; $i < strlen($string); $i += 2) {
886
- $charval = getid3_lib::LittleEndian2Int(substr($string, $i, 2));
887
- $newcharstring .= getid3_lib::iconv_fallback_int_utf8($charval);
888
  }
889
  return $newcharstring;
890
  }
891
 
892
  // UTF-16BE => ISO-8859-1
893
- static function iconv_fallback_utf16be_iso88591($string) {
894
  if (substr($string, 0, 2) == "\xFE\xFF") {
895
  // strip BOM
896
  $string = substr($string, 2);
897
  }
898
  $newcharstring = '';
899
  for ($i = 0; $i < strlen($string); $i += 2) {
900
- $charval = getid3_lib::BigEndian2Int(substr($string, $i, 2));
901
  $newcharstring .= (($charval < 256) ? chr($charval) : '?');
902
  }
903
  return $newcharstring;
904
  }
905
 
906
  // UTF-16LE => ISO-8859-1
907
- static function iconv_fallback_utf16le_iso88591($string) {
908
  if (substr($string, 0, 2) == "\xFF\xFE") {
909
  // strip BOM
910
  $string = substr($string, 2);
911
  }
912
  $newcharstring = '';
913
  for ($i = 0; $i < strlen($string); $i += 2) {
914
- $charval = getid3_lib::LittleEndian2Int(substr($string, $i, 2));
915
  $newcharstring .= (($charval < 256) ? chr($charval) : '?');
916
  }
917
  return $newcharstring;
918
  }
919
 
920
  // UTF-16 (BOM) => ISO-8859-1
921
- static function iconv_fallback_utf16_iso88591($string) {
922
  $bom = substr($string, 0, 2);
923
  if ($bom == "\xFE\xFF") {
924
- return getid3_lib::iconv_fallback_utf16be_iso88591(substr($string, 2));
925
  } elseif ($bom == "\xFF\xFE") {
926
- return getid3_lib::iconv_fallback_utf16le_iso88591(substr($string, 2));
927
  }
928
  return $string;
929
  }
930
 
931
  // UTF-16 (BOM) => UTF-8
932
- static function iconv_fallback_utf16_utf8($string) {
933
  $bom = substr($string, 0, 2);
934
  if ($bom == "\xFE\xFF") {
935
- return getid3_lib::iconv_fallback_utf16be_utf8(substr($string, 2));
936
  } elseif ($bom == "\xFF\xFE") {
937
- return getid3_lib::iconv_fallback_utf16le_utf8(substr($string, 2));
938
  }
939
  return $string;
940
  }
941
 
942
- static function iconv_fallback($in_charset, $out_charset, $string) {
943
 
944
  if ($in_charset == $out_charset) {
945
  return $string;
@@ -982,13 +997,26 @@ class getid3_lib
982
  }
983
  if (isset($ConversionFunctionList[strtoupper($in_charset)][strtoupper($out_charset)])) {
984
  $ConversionFunction = $ConversionFunctionList[strtoupper($in_charset)][strtoupper($out_charset)];
985
- return getid3_lib::$ConversionFunction($string);
986
  }
987
  throw new Exception('PHP does not have iconv() support - cannot convert from '.$in_charset.' to '.$out_charset);
988
  }
989
 
 
 
 
 
 
 
 
 
 
 
 
 
 
990
 
991
- static function MultiByteCharString2HTML($string, $charset='ISO-8859-1') {
992
  $string = (string) $string; // in case trying to pass a numeric (float, int) string, would otherwise return an empty string
993
  $HTMLstring = '';
994
 
@@ -1053,7 +1081,7 @@ class getid3_lib
1053
 
1054
  case 'UTF-16LE':
1055
  for ($i = 0; $i < strlen($string); $i += 2) {
1056
- $charval = getid3_lib::LittleEndian2Int(substr($string, $i, 2));
1057
  if (($charval >= 32) && ($charval <= 127)) {
1058
  $HTMLstring .= chr($charval);
1059
  } else {
@@ -1064,7 +1092,7 @@ class getid3_lib
1064
 
1065
  case 'UTF-16BE':
1066
  for ($i = 0; $i < strlen($string); $i += 2) {
1067
- $charval = getid3_lib::BigEndian2Int(substr($string, $i, 2));
1068
  if (($charval >= 32) && ($charval <= 127)) {
1069
  $HTMLstring .= chr($charval);
1070
  } else {
@@ -1082,7 +1110,7 @@ class getid3_lib
1082
 
1083
 
1084
 
1085
- static function RGADnameLookup($namecode) {
1086
  static $RGADname = array();
1087
  if (empty($RGADname)) {
1088
  $RGADname[0] = 'not set';
@@ -1094,7 +1122,7 @@ class getid3_lib
1094
  }
1095
 
1096
 
1097
- static function RGADoriginatorLookup($originatorcode) {
1098
  static $RGADoriginator = array();
1099
  if (empty($RGADoriginator)) {
1100
  $RGADoriginator[0] = 'unspecified';
@@ -1107,7 +1135,7 @@ class getid3_lib
1107
  }
1108
 
1109
 
1110
- static function RGADadjustmentLookup($rawadjustment, $signbit) {
1111
  $adjustment = $rawadjustment / 10;
1112
  if ($signbit == 1) {
1113
  $adjustment *= -1;
@@ -1116,7 +1144,7 @@ class getid3_lib
1116
  }
1117
 
1118
 
1119
- static function RGADgainString($namecode, $originatorcode, $replaygain) {
1120
  if ($replaygain < 0) {
1121
  $signbit = '1';
1122
  } else {
@@ -1131,12 +1159,12 @@ class getid3_lib
1131
  return $gainstring;
1132
  }
1133
 
1134
- static function RGADamplitude2dB($amplitude) {
1135
  return 20 * log10($amplitude);
1136
  }
1137
 
1138
 
1139
- static function GetDataImageSize($imgData, &$imageinfo) {
1140
  static $tempdir = '';
1141
  if (empty($tempdir)) {
1142
  // yes this is ugly, feel free to suggest a better way
@@ -1150,14 +1178,24 @@ class getid3_lib
1150
  if (is_writable($tempfilename) && is_file($tempfilename) && ($tmp = fopen($tempfilename, 'wb'))) {
1151
  fwrite($tmp, $imgData);
1152
  fclose($tmp);
1153
- $GetDataImageSize = @GetImageSize($tempfilename, $imageinfo);
 
 
 
 
 
1154
  }
1155
  unlink($tempfilename);
1156
  }
1157
  return $GetDataImageSize;
1158
  }
1159
 
1160
- static function ImageTypesLookup($imagetypeid) {
 
 
 
 
 
1161
  static $ImageTypesLookup = array();
1162
  if (empty($ImageTypesLookup)) {
1163
  $ImageTypesLookup[1] = 'gif';
@@ -1178,7 +1216,7 @@ class getid3_lib
1178
  return (isset($ImageTypesLookup[$imagetypeid]) ? $ImageTypesLookup[$imagetypeid] : '');
1179
  }
1180
 
1181
- static function CopyTagsToComments(&$ThisFileInfo) {
1182
 
1183
  // Copy all entries from ['tags'] into common ['comments']
1184
  if (!empty($ThisFileInfo['tags'])) {
@@ -1206,16 +1244,21 @@ class getid3_lib
1206
  $newvaluelength = strlen(trim($value));
1207
  foreach ($ThisFileInfo['comments'][$tagname] as $existingkey => $existingvalue) {
1208
  $oldvaluelength = strlen(trim($existingvalue));
1209
- if (($newvaluelength > $oldvaluelength) && (substr(trim($value), 0, strlen($existingvalue)) == $existingvalue)) {
1210
  $ThisFileInfo['comments'][$tagname][$existingkey] = trim($value);
1211
- break 2;
 
1212
  }
1213
  }
1214
 
1215
  }
1216
  if (is_array($value) || empty($ThisFileInfo['comments'][$tagname]) || !in_array(trim($value), $ThisFileInfo['comments'][$tagname])) {
1217
  $value = (is_string($value) ? trim($value) : $value);
1218
- $ThisFileInfo['comments'][$tagname][] = $value;
 
 
 
 
1219
  }
1220
  }
1221
  }
@@ -1223,26 +1266,29 @@ class getid3_lib
1223
  }
1224
 
1225
  // Copy to ['comments_html']
1226
- foreach ($ThisFileInfo['comments'] as $field => $values) {
1227
- if ($field == 'picture') {
1228
- // pictures can take up a lot of space, and we don't need multiple copies of them
1229
- // let there be a single copy in [comments][picture], and not elsewhere
1230
- continue;
1231
- }
1232
- foreach ($values as $index => $value) {
1233
- if (is_array($value)) {
1234
- $ThisFileInfo['comments_html'][$field][$index] = $value;
1235
- } else {
1236
- $ThisFileInfo['comments_html'][$field][$index] = str_replace('&#0;', '', getid3_lib::MultiByteCharString2HTML($value, $ThisFileInfo['encoding']));
 
 
1237
  }
1238
  }
1239
  }
 
1240
  }
1241
  return true;
1242
  }
1243
 
1244
 
1245
- static function EmbeddedLookup($key, $begin, $end, $file, $name) {
1246
 
1247
  // Cached
1248
  static $cache;
@@ -1288,7 +1334,7 @@ class getid3_lib
1288
  return (isset($cache[$file][$name][$key]) ? $cache[$file][$name][$key] : '');
1289
  }
1290
 
1291
- static function IncludeDependency($filename, $sourcefile, $DieOnFailure=false) {
1292
  global $GETID3_ERRORARRAY;
1293
 
1294
  if (file_exists($filename)) {
@@ -1312,6 +1358,40 @@ class getid3_lib
1312
  return trim($string, "\x00");
1313
  }
1314
 
1315
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1316
 
1317
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
3
  /// getID3() by James Heinrich <info@getid3.org> //
4
  // available at http://getid3.sourceforge.net //
5
  // or http://www.getid3.org //
6
+ // also https://github.com/JamesHeinrich/getID3 //
7
  /////////////////////////////////////////////////////////////////
8
  // //
9
  // getid3.lib.php - part of getID3() //
15
  class getid3_lib
16
  {
17
 
18
+ public static function PrintHexBytes($string, $hex=true, $spaces=true, $htmlencoding='UTF-8') {
19
  $returnstring = '';
20
  for ($i = 0; $i < strlen($string); $i++) {
21
  if ($hex) {
22
  $returnstring .= str_pad(dechex(ord($string{$i})), 2, '0', STR_PAD_LEFT);
23
  } else {
24
+ $returnstring .= ' '.(preg_match("#[\x20-\x7E]#", $string{$i}) ? $string{$i} : '¤');
25
  }
26
  if ($spaces) {
27
  $returnstring .= ' ';
36
  return $returnstring;
37
  }
38
 
39
+ public static function trunc($floatnumber) {
40
  // truncates a floating-point number at the decimal point
41
  // returns int (if possible, otherwise float)
42
  if ($floatnumber >= 1) {
46
  } else {
47
  $truncatednumber = 0;
48
  }
49
+ if (self::intValueSupported($truncatednumber)) {
50
  $truncatednumber = (int) $truncatednumber;
51
  }
52
  return $truncatednumber;
53
  }
54
 
55
 
56
+ public static function safe_inc(&$variable, $increment=1) {
57
  if (isset($variable)) {
58
  $variable += $increment;
59
  } else {
62
  return true;
63
  }
64
 
65
+ public static function CastAsInt($floatnum) {
66
  // convert to float if not already
67
  $floatnum = (float) $floatnum;
68
 
69
  // convert a float to type int, only if possible
70
+ if (self::trunc($floatnum) == $floatnum) {
71
  // it's not floating point
72
+ if (self::intValueSupported($floatnum)) {
73
  // it's within int range
74
  $floatnum = (int) $floatnum;
75
  }
93
  return false;
94
  }
95
 
96
+ public static function DecimalizeFraction($fraction) {
97
  list($numerator, $denominator) = explode('/', $fraction);
98
  return $numerator / ($denominator ? $denominator : 1);
99
  }
100
 
101
 
102
+ public static function DecimalBinary2Float($binarynumerator) {
103
+ $numerator = self::Bin2Dec($binarynumerator);
104
+ $denominator = self::Bin2Dec('1'.str_repeat('0', strlen($binarynumerator)));
105
  return ($numerator / $denominator);
106
  }
107
 
108
 
109
+ public static function NormalizeBinaryPoint($binarypointnumber, $maxbits=52) {
110
  // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
111
  if (strpos($binarypointnumber, '.') === false) {
112
  $binarypointnumber = '0.'.$binarypointnumber;
130
  }
131
 
132
 
133
+ public static function Float2BinaryDecimal($floatvalue) {
134
  // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
135
  $maxbits = 128; // to how many bits of precision should the calculations be taken?
136
+ $intpart = self::trunc($floatvalue);
137
  $floatpart = abs($floatvalue - $intpart);
138
  $pointbitstring = '';
139
  while (($floatpart != 0) && (strlen($pointbitstring) < $maxbits)) {
140
  $floatpart *= 2;
141
+ $pointbitstring .= (string) self::trunc($floatpart);
142
+ $floatpart -= self::trunc($floatpart);
143
  }
144
  $binarypointnumber = decbin($intpart).'.'.$pointbitstring;
145
  return $binarypointnumber;
146
  }
147
 
148
 
149
+ public static function Float2String($floatvalue, $bits) {
150
  // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee-expl.html
151
  switch ($bits) {
152
  case 32:
168
  } else {
169
  $signbit = '1';
170
  }
171
+ $normalizedbinary = self::NormalizeBinaryPoint(self::Float2BinaryDecimal($floatvalue), $fractionbits);
172
  $biasedexponent = pow(2, $exponentbits - 1) - 1 + $normalizedbinary['exponent']; // (127 or 1023) +/- exponent
173
  $exponentbitstring = str_pad(decbin($biasedexponent), $exponentbits, '0', STR_PAD_LEFT);
174
  $fractionbitstring = str_pad(substr($normalizedbinary['normalized'], 2), $fractionbits, '0', STR_PAD_RIGHT);
175
 
176
+ return self::BigEndian2String(self::Bin2Dec($signbit.$exponentbitstring.$fractionbitstring), $bits % 8, false);
177
  }
178
 
179
 
180
+ public static function LittleEndian2Float($byteword) {
181
+ return self::BigEndian2Float(strrev($byteword));
182
  }
183
 
184
 
185
+ public static function BigEndian2Float($byteword) {
186
  // ANSI/IEEE Standard 754-1985, Standard for Binary Floating Point Arithmetic
187
  // http://www.psc.edu/general/software/packages/ieee/ieee.html
188
  // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee.html
189
 
190
+ $bitword = self::BigEndian2Bin($byteword);
191
  if (!$bitword) {
192
  return 0;
193
  }
210
  $exponentstring = substr($bitword, 1, 15);
211
  $isnormalized = intval($bitword{16});
212
  $fractionstring = substr($bitword, 17, 63);
213
+ $exponent = pow(2, self::Bin2Dec($exponentstring) - 16383);
214
+ $fraction = $isnormalized + self::DecimalBinary2Float($fractionstring);
215
  $floatvalue = $exponent * $fraction;
216
  if ($signbit == '1') {
217
  $floatvalue *= -1;
225
  }
226
  $exponentstring = substr($bitword, 1, $exponentbits);
227
  $fractionstring = substr($bitword, $exponentbits + 1, $fractionbits);
228
+ $exponent = self::Bin2Dec($exponentstring);
229
+ $fraction = self::Bin2Dec($fractionstring);
230
 
231
  if (($exponent == (pow(2, $exponentbits) - 1)) && ($fraction != 0)) {
232
  // Not a Number
246
  $floatvalue = ($signbit ? 0 : -0);
247
  } elseif (($exponent == 0) && ($fraction != 0)) {
248
  // These are 'unnormalized' values
249
+ $floatvalue = pow(2, (-1 * (pow(2, $exponentbits - 1) - 2))) * self::DecimalBinary2Float($fractionstring);
250
  if ($signbit == '1') {
251
  $floatvalue *= -1;
252
  }
253
  } elseif ($exponent != 0) {
254
+ $floatvalue = pow(2, ($exponent - (pow(2, $exponentbits - 1) - 1))) * (1 + self::DecimalBinary2Float($fractionstring));
255
  if ($signbit == '1') {
256
  $floatvalue *= -1;
257
  }
260
  }
261
 
262
 
263
+ public static function BigEndian2Int($byteword, $synchsafe=false, $signed=false) {
264
  $intvalue = 0;
265
  $bytewordlen = strlen($byteword);
266
  if ($bytewordlen == 0) {
282
  $intvalue = 0 - ($intvalue & ($signMaskBit - 1));
283
  }
284
  } else {
285
+ throw new Exception('ERROR: Cannot have signed integers larger than '.(8 * PHP_INT_SIZE).'-bits ('.strlen($byteword).') in self::BigEndian2Int()');
 
286
  }
287
  }
288
+ return self::CastAsInt($intvalue);
289
  }
290
 
291
 
292
+ public static function LittleEndian2Int($byteword, $signed=false) {
293
+ return self::BigEndian2Int(strrev($byteword), false, $signed);
294
  }
295
 
296
 
297
+ public static function BigEndian2Bin($byteword) {
298
  $binvalue = '';
299
  $bytewordlen = strlen($byteword);
300
  for ($i = 0; $i < $bytewordlen; $i++) {
304
  }
305
 
306
 
307
+ public static function BigEndian2String($number, $minbytes=1, $synchsafe=false, $signed=false) {
308
  if ($number < 0) {
309
+ throw new Exception('ERROR: self::BigEndian2String() does not support negative numbers');
310
  }
311
  $maskbyte = (($synchsafe || $signed) ? 0x7F : 0xFF);
312
  $intstring = '';
313
  if ($signed) {
314
  if ($minbytes > PHP_INT_SIZE) {
315
+ throw new Exception('ERROR: Cannot have signed integers larger than '.(8 * PHP_INT_SIZE).'-bits in self::BigEndian2String()');
316
  }
317
  $number = $number & (0x80 << (8 * ($minbytes - 1)));
318
  }
325
  }
326
 
327
 
328
+ public static function Dec2Bin($number) {
329
  while ($number >= 256) {
330
  $bytes[] = (($number / 256) - (floor($number / 256))) * 256;
331
  $number = floor($number / 256);
339
  }
340
 
341
 
342
+ public static function Bin2Dec($binstring, $signed=false) {
343
  $signmult = 1;
344
  if ($signed) {
345
  if ($binstring{0} == '1') {
351
  for ($i = 0; $i < strlen($binstring); $i++) {
352
  $decvalue += ((int) substr($binstring, strlen($binstring) - $i - 1, 1)) * pow(2, $i);
353
  }
354
+ return self::CastAsInt($decvalue * $signmult);
355
  }
356
 
357
 
358
+ public static function Bin2String($binstring) {
359
  // return 'hi' for input of '0110100001101001'
360
  $string = '';
361
  $binstringreversed = strrev($binstring);
362
  for ($i = 0; $i < strlen($binstringreversed); $i += 8) {
363
+ $string = chr(self::Bin2Dec(strrev(substr($binstringreversed, $i, 8)))).$string;
364
  }
365
  return $string;
366
  }
367
 
368
 
369
+ public static function LittleEndian2String($number, $minbytes=1, $synchsafe=false) {
370
  $intstring = '';
371
  while ($number > 0) {
372
  if ($synchsafe) {
381
  }
382
 
383
 
384
+ public static function array_merge_clobber($array1, $array2) {
385
+ // written by kcØhireability*com
386
  // taken from http://www.php.net/manual/en/function.array-merge-recursive.php
387
  if (!is_array($array1) || !is_array($array2)) {
388
  return false;
390
  $newarray = $array1;
391
  foreach ($array2 as $key => $val) {
392
  if (is_array($val) && isset($newarray[$key]) && is_array($newarray[$key])) {
393
+ $newarray[$key] = self::array_merge_clobber($newarray[$key], $val);
394
  } else {
395
  $newarray[$key] = $val;
396
  }
399
  }
400
 
401
 
402
+ public static function array_merge_noclobber($array1, $array2) {
403
  if (!is_array($array1) || !is_array($array2)) {
404
  return false;
405
  }
406
  $newarray = $array1;
407
  foreach ($array2 as $key => $val) {
408
  if (is_array($val) && isset($newarray[$key]) && is_array($newarray[$key])) {
409
+ $newarray[$key] = self::array_merge_noclobber($newarray[$key], $val);
410
  } elseif (!isset($newarray[$key])) {
411
  $newarray[$key] = $val;
412
  }
414
  return $newarray;
415
  }
416
 
417
+ public static function flipped_array_merge_noclobber($array1, $array2) {
418
+ if (!is_array($array1) || !is_array($array2)) {
419
+ return false;
420
+ }
421
+ # naturally, this only works non-recursively
422
+ $newarray = array_flip($array1);
423
+ foreach (array_flip($array2) as $key => $val) {
424
+ if (!isset($newarray[$key])) {
425
+ $newarray[$key] = count($newarray);
426
+ }
427
+ }
428
+ return array_flip($newarray);
429
+ }
430
+
431
 
432
+ public static function ksort_recursive(&$theArray) {
433
  ksort($theArray);
434
  foreach ($theArray as $key => $value) {
435
  if (is_array($value)) {
439
  return true;
440
  }
441
 
442
+ public static function fileextension($filename, $numextensions=1) {
443
  if (strstr($filename, '.')) {
444
  $reversedfilename = strrev($filename);
445
  $offset = 0;
455
  }
456
 
457
 
458
+ public static function PlaytimeString($seconds) {
459
  $sign = (($seconds < 0) ? '-' : '');
460
+ $seconds = round(abs($seconds));
461
+ $H = (int) floor( $seconds / 3600);
462
+ $M = (int) floor(($seconds - (3600 * $H) ) / 60);
463
+ $S = (int) round( $seconds - (3600 * $H) - (60 * $M) );
464
  return $sign.($H ? $H.':' : '').($H ? str_pad($M, 2, '0', STR_PAD_LEFT) : intval($M)).':'.str_pad($S, 2, 0, STR_PAD_LEFT);
465
  }
466
 
467
 
468
+ public static function DateMac2Unix($macdate) {
469
  // Macintosh timestamp: seconds since 00:00h January 1, 1904
470
  // UNIX timestamp: seconds since 00:00h January 1, 1970
471
+ return self::CastAsInt($macdate - 2082844800);
472
  }
473
 
474
 
475
+ public static function FixedPoint8_8($rawdata) {
476
+ return self::BigEndian2Int(substr($rawdata, 0, 1)) + (float) (self::BigEndian2Int(substr($rawdata, 1, 1)) / pow(2, 8));
477
  }
478
 
479
 
480
+ public static function FixedPoint16_16($rawdata) {
481
+ return self::BigEndian2Int(substr($rawdata, 0, 2)) + (float) (self::BigEndian2Int(substr($rawdata, 2, 2)) / pow(2, 16));
482
  }
483
 
484
 
485
+ public static function FixedPoint2_30($rawdata) {
486
+ $binarystring = self::BigEndian2Bin($rawdata);
487
+ return self::Bin2Dec(substr($binarystring, 0, 2)) + (float) (self::Bin2Dec(substr($binarystring, 2, 30)) / pow(2, 30));
488
  }
489
 
490
 
491
+ public static function CreateDeepArray($ArrayPath, $Separator, $Value) {
492
  // assigns $Value to a nested array path:
493
+ // $foo = self::CreateDeepArray('/path/to/my', '/', 'file.txt')
494
  // is the same as:
495
  // $foo = array('path'=>array('to'=>'array('my'=>array('file.txt'))));
496
  // or
497
  // $foo['path']['to']['my'] = 'file.txt';
498
+ $ArrayPath = ltrim($ArrayPath, $Separator);
 
 
499
  if (($pos = strpos($ArrayPath, $Separator)) !== false) {
500
+ $ReturnedArray[substr($ArrayPath, 0, $pos)] = self::CreateDeepArray(substr($ArrayPath, $pos + 1), $Separator, $Value);
501
  } else {
502
  $ReturnedArray[$ArrayPath] = $Value;
503
  }
504
  return $ReturnedArray;
505
  }
506
 
507
+ public static function array_max($arraydata, $returnkey=false) {
508
  $maxvalue = false;
509
  $maxkey = false;
510
  foreach ($arraydata as $key => $value) {
518
  return ($returnkey ? $maxkey : $maxvalue);
519
  }
520
 
521
+ public static function array_min($arraydata, $returnkey=false) {
522
  $minvalue = false;
523
  $minkey = false;
524
  foreach ($arraydata as $key => $value) {
532
  return ($returnkey ? $minkey : $minvalue);
533
  }
534
 
535
+ public static function XML2array($XMLstring) {
536
+ if (function_exists('simplexml_load_string') && function_exists('libxml_disable_entity_loader')) {
537
+ // http://websec.io/2012/08/27/Preventing-XEE-in-PHP.html
538
+ // https://core.trac.wordpress.org/changeset/29378
539
+ $loader = libxml_disable_entity_loader(true);
540
+ $XMLobject = simplexml_load_string($XMLstring, 'SimpleXMLElement', LIBXML_NOENT);
541
+ $return = self::SimpleXMLelement2array($XMLobject);
542
+ libxml_disable_entity_loader($loader);
543
+ return $return;
544
  }
545
  return false;
546
  }
547
 
548
+ public static function SimpleXMLelement2array($XMLobject) {
549
  if (!is_object($XMLobject) && !is_array($XMLobject)) {
550
  return $XMLobject;
551
  }
557
  }
558
 
559
 
560
+ // Allan Hansen <ahØartemis*dk>
561
+ // self::md5_data() - returns md5sum for a file from startuing position to absolute end position
562
+ public static function hash_data($file, $offset, $end, $algorithm) {
563
  static $tempdir = '';
564
+ if (!self::intValueSupported($end)) {
565
  return false;
566
  }
567
  switch ($algorithm) {
580
  break;
581
 
582
  default:
583
+ throw new Exception('Invalid algorithm ('.$algorithm.') in self::hash_data()');
584
  break;
585
  }
586
  $size = $end - $offset;
597
  foreach ($RequiredFiles as $required_file) {
598
  if (!is_readable(GETID3_HELPERAPPSDIR.$required_file)) {
599
  // helper apps not available - fall back to old method
600
+ break 2;
601
  }
602
  }
603
+ $commandline = GETID3_HELPERAPPSDIR.'head.exe -c '.$end.' '.escapeshellarg(str_replace('/', DIRECTORY_SEPARATOR, $file)).' | ';
604
  $commandline .= GETID3_HELPERAPPSDIR.'tail.exe -c '.$size.' | ';
605
  $commandline .= GETID3_HELPERAPPSDIR.$windows_call;
606
 
636
 
637
  // copy parts of file
638
  try {
639
+ self::CopyFileParts($file, $data_filename, $offset, $end - $offset);
640
  $result = $hash_function($data_filename);
641
  } catch (Exception $e) {
642
+ throw new Exception('self::CopyFileParts() failed in getid_lib::hash_data(): '.$e->getMessage());
643
  }
644
  unlink($data_filename);
645
  return $result;
646
  }
647
 
648
+ public static function CopyFileParts($filename_source, $filename_dest, $offset, $length) {
649
+ if (!self::intValueSupported($offset + $length)) {
650
  throw new Exception('cannot copy file portion, it extends beyond the '.round(PHP_INT_MAX / 1073741824).'GB limit');
651
  }
652
  if (is_readable($filename_source) && is_file($filename_source) && ($fp_src = fopen($filename_source, 'rb'))) {
653
  if (($fp_dest = fopen($filename_dest, 'wb'))) {
654
+ if (fseek($fp_src, $offset) == 0) {
655
  $byteslefttowrite = $length;
656
  while (($byteslefttowrite > 0) && ($buffer = fread($fp_src, min($byteslefttowrite, getID3::FREAD_BUFFER_SIZE)))) {
657
  $byteswritten = fwrite($fp_dest, $buffer, $byteslefttowrite);
672
  return false;
673
  }
674
 
675
+ public static function iconv_fallback_int_utf8($charval) {
676
  if ($charval < 128) {
677
  // 0bbbbbbb
678
  $newcharstring = chr($charval);
696
  }
697
 
698
  // ISO-8859-1 => UTF-8
699
+ public static function iconv_fallback_iso88591_utf8($string, $bom=false) {
700
  if (function_exists('utf8_encode')) {
701
  return utf8_encode($string);
702
  }
707
  }
708
  for ($i = 0; $i < strlen($string); $i++) {
709
  $charval = ord($string{$i});
710
+ $newcharstring .= self::iconv_fallback_int_utf8($charval);
711
  }
712
  return $newcharstring;
713
  }
714
 
715
  // ISO-8859-1 => UTF-16BE
716
+ public static function iconv_fallback_iso88591_utf16be($string, $bom=false) {
717
  $newcharstring = '';
718
  if ($bom) {
719
  $newcharstring .= "\xFE\xFF";
725
  }
726
 
727
  // ISO-8859-1 => UTF-16LE
728
+ public static function iconv_fallback_iso88591_utf16le($string, $bom=false) {
729
  $newcharstring = '';
730
  if ($bom) {
731
  $newcharstring .= "\xFF\xFE";
737
  }
738
 
739
  // ISO-8859-1 => UTF-16LE (BOM)
740
+ public static function iconv_fallback_iso88591_utf16($string) {
741
+ return self::iconv_fallback_iso88591_utf16le($string, true);
742
  }
743
 
744
  // UTF-8 => ISO-8859-1
745
+ public static function iconv_fallback_utf8_iso88591($string) {
746
  if (function_exists('utf8_decode')) {
747
  return utf8_decode($string);
748
  }
786
  }
787
 
788
  // UTF-8 => UTF-16BE
789
+ public static function iconv_fallback_utf8_utf16be($string, $bom=false) {
790
  $newcharstring = '';
791
  if ($bom) {
792
  $newcharstring .= "\xFE\xFF";
822
  $offset += 1;
823
  }
824
  if ($charval !== false) {
825
+ $newcharstring .= (($charval < 65536) ? self::BigEndian2String($charval, 2) : "\x00".'?');
826
  }
827
  }
828
  return $newcharstring;
829
  }
830
 
831
  // UTF-8 => UTF-16LE
832
+ public static function iconv_fallback_utf8_utf16le($string, $bom=false) {
833
  $newcharstring = '';
834
  if ($bom) {
835
  $newcharstring .= "\xFF\xFE";
865
  $offset += 1;
866
  }
867
  if ($charval !== false) {
868
+ $newcharstring .= (($charval < 65536) ? self::LittleEndian2String($charval, 2) : '?'."\x00");
869
  }
870
  }
871
  return $newcharstring;
872
  }
873
 
874
  // UTF-8 => UTF-16LE (BOM)
875
+ public static function iconv_fallback_utf8_utf16($string) {
876
+ return self::iconv_fallback_utf8_utf16le($string, true);
877
  }
878
 
879
  // UTF-16BE => UTF-8
880
+ public static function iconv_fallback_utf16be_utf8($string) {
881
  if (substr($string, 0, 2) == "\xFE\xFF") {
882
  // strip BOM
883
  $string = substr($string, 2);
884
  }
885
  $newcharstring = '';
886
  for ($i = 0; $i < strlen($string); $i += 2) {
887
+ $charval = self::BigEndian2Int(substr($string, $i, 2));
888
+ $newcharstring .= self::iconv_fallback_int_utf8($charval);
889
  }
890
  return $newcharstring;
891
  }
892
 
893
  // UTF-16LE => UTF-8
894
+ public static function iconv_fallback_utf16le_utf8($string) {
895
  if (substr($string, 0, 2) == "\xFF\xFE") {
896
  // strip BOM
897
  $string = substr($string, 2);
898
  }
899
  $newcharstring = '';
900
  for ($i = 0; $i < strlen($string); $i += 2) {
901
+ $charval = self::LittleEndian2Int(substr($string, $i, 2));
902
+ $newcharstring .= self::iconv_fallback_int_utf8($charval);
903
  }
904
  return $newcharstring;
905
  }
906
 
907
  // UTF-16BE => ISO-8859-1
908
+ public static function iconv_fallback_utf16be_iso88591($string) {
909
  if (substr($string, 0, 2) == "\xFE\xFF") {
910
  // strip BOM
911
  $string = substr($string, 2);
912
  }
913
  $newcharstring = '';
914
  for ($i = 0; $i < strlen($string); $i += 2) {
915
+ $charval = self::BigEndian2Int(substr($string, $i, 2));
916