BackWPup – WordPress Backup Plugin - Version 1.5.5

Version Description

  • Updatet AWS SDK to ver.1.2.6 for Amazon S3
  • Added AWS Regin "Northeast" (Japan)
  • Added Microsoft Azure (Blob) as backup destination
  • bug fixes
Download this release

Release Info

Developer danielhuesken
Plugin Icon 128x128 BackWPup – WordPress Backup Plugin
Version 1.5.5
Comparing to
See all releases

Code changes from version 1.5.2 to 1.5.5

Files changed (86) hide show
  1. app/backwpup_dojob.php +88 -17
  2. app/functions5.php +124 -9
  3. app/js/options.js +26 -0
  4. app/libs/Microsoft/Exception.php +43 -0
  5. app/libs/Microsoft/Http/Client.php +1444 -0
  6. app/libs/Microsoft/Http/Client/Adapter/Curl.php +498 -0
  7. app/libs/Microsoft/Http/Client/Adapter/Exception.php +38 -0
  8. app/libs/Microsoft/Http/Client/Adapter/Interface.php +78 -0
  9. app/libs/Microsoft/Http/Client/Adapter/Proxy.php +267 -0
  10. app/libs/Microsoft/Http/Client/Adapter/Socket.php +531 -0
  11. app/libs/Microsoft/Http/Client/Adapter/Stream.php +46 -0
  12. app/libs/Microsoft/Http/Client/Exception.php +36 -0
  13. app/libs/Microsoft/Http/Cookie.php +408 -0
  14. app/libs/Microsoft/Http/CookieJar.php +403 -0
  15. app/libs/Microsoft/Http/Exception.php +48 -0
  16. app/libs/Microsoft/Http/Response.php +664 -0
  17. app/libs/Microsoft/Http/Response/Stream.php +235 -0
  18. app/libs/Microsoft/Uri.php +188 -0
  19. app/libs/Microsoft/Uri/Exception.php +37 -0
  20. app/libs/Microsoft/Uri/Http.php +761 -0
  21. app/libs/Microsoft/WindowsAzure/Credentials/CredentialsAbstract.php +257 -0
  22. app/libs/Microsoft/WindowsAzure/Credentials/Exception.php +48 -0
  23. app/libs/Microsoft/WindowsAzure/Credentials/SharedAccessSignature.php +320 -0
  24. app/libs/Microsoft/WindowsAzure/Credentials/SharedKey.php +200 -0
  25. app/libs/Microsoft/WindowsAzure/Credentials/SharedKeyLite.php +179 -0
  26. app/libs/Microsoft/WindowsAzure/Diagnostics/ConfigurationDataSources.php +104 -0
  27. app/libs/Microsoft/WindowsAzure/Diagnostics/ConfigurationDiagnosticInfrastructureLogs.php +80 -0
  28. app/libs/Microsoft/WindowsAzure/Diagnostics/ConfigurationDirectories.php +103 -0
  29. app/libs/Microsoft/WindowsAzure/Diagnostics/ConfigurationInstance.php +234 -0
  30. app/libs/Microsoft/WindowsAzure/Diagnostics/ConfigurationLogs.php +80 -0
  31. app/libs/Microsoft/WindowsAzure/Diagnostics/ConfigurationObjectBaseAbstract.php +84 -0
  32. app/libs/Microsoft/WindowsAzure/Diagnostics/ConfigurationPerformanceCounters.php +102 -0
  33. app/libs/Microsoft/WindowsAzure/Diagnostics/ConfigurationWindowsEventLog.php +104 -0
  34. app/libs/Microsoft/WindowsAzure/Diagnostics/DirectoryConfigurationSubscription.php +75 -0
  35. app/libs/Microsoft/WindowsAzure/Diagnostics/Exception.php +51 -0
  36. app/libs/Microsoft/WindowsAzure/Diagnostics/LogLevel.php +52 -0
  37. app/libs/Microsoft/WindowsAzure/Diagnostics/Manager.php +225 -0
  38. app/libs/Microsoft/WindowsAzure/Diagnostics/PerformanceCounterSubscription.php +72 -0
  39. app/libs/Microsoft/WindowsAzure/Exception.php +48 -0
  40. app/libs/Microsoft/WindowsAzure/RetryPolicy/Exception.php +49 -0
  41. app/libs/Microsoft/WindowsAzure/RetryPolicy/NoRetry.php +71 -0
  42. app/libs/Microsoft/WindowsAzure/RetryPolicy/RetryN.php +105 -0
  43. app/libs/Microsoft/WindowsAzure/RetryPolicy/RetryPolicyAbstract.php +90 -0
  44. app/libs/Microsoft/WindowsAzure/SessionHandler.php +230 -0
  45. app/libs/Microsoft/WindowsAzure/Storage.php +586 -0
  46. app/libs/Microsoft/WindowsAzure/Storage/Batch.php +261 -0
  47. app/libs/Microsoft/WindowsAzure/Storage/BatchStorageAbstract.php +210 -0
  48. app/libs/Microsoft/WindowsAzure/Storage/Blob.php +2029 -0
  49. app/libs/Microsoft/WindowsAzure/Storage/Blob/Stream.php +578 -0
  50. app/libs/Microsoft/WindowsAzure/Storage/BlobContainer.php +112 -0
  51. app/libs/Microsoft/WindowsAzure/Storage/BlobInstance.php +145 -0
  52. app/libs/Microsoft/WindowsAzure/Storage/DynamicTableEntity.php +213 -0
  53. app/libs/Microsoft/WindowsAzure/Storage/LeaseInstance.php +78 -0
  54. app/libs/Microsoft/WindowsAzure/Storage/PageRegionInstance.php +72 -0
  55. app/libs/Microsoft/WindowsAzure/Storage/Queue.php +582 -0
  56. app/libs/Microsoft/WindowsAzure/Storage/QueueInstance.php +74 -0
  57. app/libs/Microsoft/WindowsAzure/Storage/QueueMessage.php +87 -0
  58. app/libs/Microsoft/WindowsAzure/Storage/SignedIdentifier.php +78 -0
  59. app/libs/Microsoft/WindowsAzure/Storage/StorageEntityAbstract.php +86 -0
  60. app/libs/Microsoft/WindowsAzure/Storage/Table.php +919 -0
  61. app/libs/Microsoft/WindowsAzure/Storage/TableEntity.php +344 -0
  62. app/libs/Microsoft/WindowsAzure/Storage/TableEntityQuery.php +363 -0
  63. app/libs/Microsoft/WindowsAzure/Storage/TableInstance.php +78 -0
  64. app/libs/aws/lib/requestcore/requestcore.class.php +81 -4
  65. app/libs/aws/sdk.class.php +71 -3
  66. app/libs/aws/services/as.class.php +6 -1
  67. app/libs/aws/services/cloudformation.class.php +6 -1
  68. app/libs/aws/services/cloudfront.class.php +11 -0
  69. app/libs/aws/services/cloudwatch.class.php +6 -1
  70. app/libs/aws/services/ec2.class.php +6 -1
  71. app/libs/aws/services/elasticbeanstalk.class.php +1 -1
  72. app/libs/aws/services/elb.class.php +6 -1
  73. app/libs/aws/services/emr.class.php +6 -1
  74. app/libs/aws/services/iam.class.php +1 -1
  75. app/libs/aws/services/importexport.class.php +1 -1
  76. app/libs/aws/services/rds.class.php +6 -1
  77. app/libs/aws/services/s3.class.php +33 -14
  78. app/libs/aws/services/sdb.class.php +6 -1
  79. app/libs/aws/services/ses.class.php +1 -1
  80. app/libs/aws/services/sns.class.php +23 -47
  81. app/libs/aws/services/sqs.class.php +29 -67
  82. app/list-tables.php +2 -0
  83. app/options-edit-job.php +27 -2
  84. app/options-save.php +65 -7
  85. backwpup.php +4 -3
  86. readme.txt +10 -2
app/backwpup_dojob.php CHANGED
@@ -92,7 +92,7 @@ class backwpup_dojob {
92
  $this->job_end($jobs[$this->jobid]['logfile']);
93
  } else {
94
  trigger_error(sprintf(__('Job %1$s already running!!!','backwpup'),$jobs[$this->jobid]['name']),E_USER_ERROR);
95
- return false;
96
  }
97
  }
98
  //Set job start settings
@@ -106,24 +106,26 @@ class backwpup_dojob {
106
  $this->job=backwpup_check_job_vars($jobs[$this->jobid],$this->jobid);//Set and check job settings
107
  //set waht to do
108
  $this->todo=explode('+',$this->job['type']);
109
- //set Backup File format
110
- $this->backupfileformat=$this->job['fileformart'];
111
  //set Temp Dir
112
  $this->tempdir=trailingslashit($this->cfg['dirtemp']);
113
  if (empty($this->tempdir) or $this->tempdir=='/')
114
  $this->tempdir=backwpup_get_upload_dir();
115
- //set Backup Dir
116
- $this->backupdir=$this->job['backupdir'];
117
- if (empty($this->backupdir))
118
- $this->backupdir=$this->tempdir;
119
- //check backup dir
120
- if ($this->backupdir!=backwpup_get_upload_dir()) {
121
- if (!$this->_check_folders($this->backupdir))
122
- return false;
123
- }
124
- //set Backup file name only for jos that makes backups
125
- if (in_array('FILE',$this->todo) or in_array('DB',$this->todo) or in_array('WPEXP',$this->todo))
 
 
 
126
  $this->backupfile=$this->job['fileprefix'].date_i18n('Y-m-d_H-i-s').$this->backupfileformat;
 
127
  //check max script execution tme
128
  if (ini_get('safe_mode') or strtolower(ini_get('safe_mode'))=='on' or ini_get('safe_mode')=='1')
129
  trigger_error(sprintf(__('PHP Safe Mode is on!!! Max exec time is %1$d sec.','backwpup'),ini_get('max_execution_time')),E_USER_WARNING);
@@ -165,6 +167,8 @@ class backwpup_dojob {
165
  $this->destination_s3();
166
  if (in_array('RSC',$dests))
167
  $this->destination_rsc();
 
 
168
  $this->destination_dir();
169
  }
170
 
@@ -1002,9 +1006,10 @@ class backwpup_dojob {
1002
  }
1003
  }
1004
 
1005
- if (ftp_put($ftp_conn_id, $this->job['ftpdir'].$this->backupfile, $this->backupdir.$this->backupfile, FTP_BINARY)) //transfere file
1006
  trigger_error(__('Backup File transferred to FTP Server:','backwpup').' '.$this->job['ftpdir'].$this->backupfile,E_USER_NOTICE);
1007
- else
 
1008
  trigger_error(__('Can not transfer backup to FTP server.','backwpup'),E_USER_ERROR);
1009
 
1010
  if ($this->job['ftpmaxbackups']>0) { //Delete old backups
@@ -1238,7 +1243,7 @@ class backwpup_dojob {
1238
  if ($backwpupcontainer->delete_object($this->job['rscdir'].$backupfilelist[$i])) //delte files on Cloud
1239
  $numdeltefiles++;
1240
  else
1241
- trigger_error(__('Can not delete file on RSC://','backwpup').$this->job['rscContainer'].'/'.$this->job['rscdir'].$backupfilelist[$i],E_USER_ERROR);
1242
  }
1243
  if ($numdeltefiles>0)
1244
  trigger_error($numdeltefiles.' '.__('files deleted on Racspase Cloud Container!','backwpup'),E_USER_NOTICE);
@@ -1249,6 +1254,72 @@ class backwpup_dojob {
1249
  }
1250
  }
1251
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1252
 
1253
  private function destination_dir() {
1254
  if (empty($this->job['backupdir'])) //Go back if no destination dir
92
  $this->job_end($jobs[$this->jobid]['logfile']);
93
  } else {
94
  trigger_error(sprintf(__('Job %1$s already running!!!','backwpup'),$jobs[$this->jobid]['name']),E_USER_ERROR);
95
+ $this->job_end();
96
  }
97
  }
98
  //Set job start settings
106
  $this->job=backwpup_check_job_vars($jobs[$this->jobid],$this->jobid);//Set and check job settings
107
  //set waht to do
108
  $this->todo=explode('+',$this->job['type']);
 
 
109
  //set Temp Dir
110
  $this->tempdir=trailingslashit($this->cfg['dirtemp']);
111
  if (empty($this->tempdir) or $this->tempdir=='/')
112
  $this->tempdir=backwpup_get_upload_dir();
113
+ //only for jos that makes backups
114
+ if (in_array('FILE',$this->todo) or in_array('DB',$this->todo) or in_array('WPEXP',$this->todo)) {
115
+ //set Backup File format
116
+ $this->backupfileformat=$this->job['fileformart'];
117
+ //set Backup Dir
118
+ $this->backupdir=$this->job['backupdir'];
119
+ if (empty($this->backupdir))
120
+ $this->backupdir=$this->tempdir;
121
+ //check backup dir
122
+ if ($this->backupdir!=backwpup_get_upload_dir()) {
123
+ if (!$this->_check_folders($this->backupdir))
124
+ return false;
125
+ }
126
+ //set Backup file Name
127
  $this->backupfile=$this->job['fileprefix'].date_i18n('Y-m-d_H-i-s').$this->backupfileformat;
128
+ }
129
  //check max script execution tme
130
  if (ini_get('safe_mode') or strtolower(ini_get('safe_mode'))=='on' or ini_get('safe_mode')=='1')
131
  trigger_error(sprintf(__('PHP Safe Mode is on!!! Max exec time is %1$d sec.','backwpup'),ini_get('max_execution_time')),E_USER_WARNING);
167
  $this->destination_s3();
168
  if (in_array('RSC',$dests))
169
  $this->destination_rsc();
170
+ if (in_array('MSAZURE',$dests))
171
+ $this->destination_msazure();
172
  $this->destination_dir();
173
  }
174
 
1006
  }
1007
  }
1008
 
1009
+ if (ftp_put($ftp_conn_id, $this->job['ftpdir'].$this->backupfile, $this->backupdir.$this->backupfile, FTP_BINARY)) { //transfere file
1010
  trigger_error(__('Backup File transferred to FTP Server:','backwpup').' '.$this->job['ftpdir'].$this->backupfile,E_USER_NOTICE);
1011
+ $this->lastbackupdownloadurl="ftp://".$this->job['ftpuser'].":".base64_decode($this->job['ftppass'])."@".$this->job['ftphost'].$this->job['ftpdir'].$this->backupfile;
1012
+ } else
1013
  trigger_error(__('Can not transfer backup to FTP server.','backwpup'),E_USER_ERROR);
1014
 
1015
  if ($this->job['ftpmaxbackups']>0) { //Delete old backups
1243
  if ($backwpupcontainer->delete_object($this->job['rscdir'].$backupfilelist[$i])) //delte files on Cloud
1244
  $numdeltefiles++;
1245
  else
1246
+ trigger_error(__('Can not delete file on RSC://','backwpup').$this->job['rscContainer'].$this->job['rscdir'].$backupfilelist[$i],E_USER_ERROR);
1247
  }
1248
  if ($numdeltefiles>0)
1249
  trigger_error($numdeltefiles.' '.__('files deleted on Racspase Cloud Container!','backwpup'),E_USER_NOTICE);
1254
  }
1255
  }
1256
 
1257
+ private function destination_msazure() {
1258
+
1259
+ if (empty($this->job['msazureHost']) or empty($this->job['msazureAccName']) or empty($this->job['msazureKey']) or empty($this->job['msazureContainer']))
1260
+ return;
1261
+
1262
+ if (!(extension_loaded('curl') or @dl(PHP_SHLIB_SUFFIX == 'so' ? 'curl.so' : 'php_curl.dll'))) {
1263
+ trigger_error(__('Can not load curl extension is needed for Microsoft Azure!','backwpup'),E_USER_ERROR);
1264
+ return;
1265
+ }
1266
+
1267
+ if (!class_exists('Microsoft_WindowsAzure_Storage_Blob')) {
1268
+ set_include_path(get_include_path().PATH_SEPARATOR.dirname(__FILE__).'/libs');
1269
+ require_once 'Microsoft/WindowsAzure/Storage/Blob.php';
1270
+ }
1271
+
1272
+ try {
1273
+ $storageClient = new Microsoft_WindowsAzure_Storage_Blob($this->job['msazureHost'],$this->job['msazureAccName'],$this->job['msazureKey']);
1274
+
1275
+ if(!$storageClient->containerExists($this->job['msazureContainer'])) {
1276
+ trigger_error(__('Microsoft Azure Container not exists:','backwpup').' '.$this->job['msazureContainer'],E_USER_ERROR);
1277
+ return;
1278
+ } else {
1279
+ trigger_error(__('Connected to Microsoft Azure Container:','backwpup').' '.$this->job['msazureContainer'],E_USER_NOTICE);
1280
+ }
1281
+
1282
+ if (filesize($this->backupdir.$this->backupfile)<Microsoft_WindowsAzure_Storage_Blob::MAX_BLOB_SIZE) { //for files bigger tha 64MB
1283
+ $result = $storageClient->putBlob($this->job['msazureContainer'], $this->job['msazuredir'].$this->backupfile, $this->backupdir.$this->backupfile);
1284
+ } else {
1285
+ $result = $storageClient->putLargeBlob($this->job['msazureContainer'], $this->job['msazuredir'].$this->backupfile, $this->backupdir.$this->backupfile);
1286
+ }
1287
+
1288
+ if ($result->Name==$this->job['msazuredir'].$this->backupfile) {
1289
+ trigger_error(__('Backup File transferred to azure://','backwpup').$this->job['msazuredir'].$this->backupfile,E_USER_NOTICE);
1290
+ $this->lastbackupdownloadurl='admin.php?page=BackWPup&subpage=backups&action=downloadmsazure&file='.$this->job['msazuredir'].$this->backupfile.'&jobid='.$this->jobid;
1291
+ } else {
1292
+ trigger_error(__('Can not transfer backup to Microsoft Azure.','backwpup'),E_USER_ERROR);
1293
+ }
1294
+
1295
+ if ($this->job['msazuremaxbackups']>0) { //Delete old backups
1296
+ $backupfilelist=array();
1297
+ $blobs = $storageClient->listBlobs($this->job['msazureContainer'],$this->job['msazuredir']);
1298
+ if (is_array($blobs)) {
1299
+ foreach ($blobs as $blob) {
1300
+ $file=basename($blob->Name);
1301
+ if ($this->job['msazuredir'].$file == $blob->Name) {//only in the folder and not in complete bucket
1302
+ if ($this->job['fileprefix'] == substr($file,0,strlen($this->job['fileprefix'])) and $this->backupfileformat == substr($file,-strlen($this->backupfileformat)))
1303
+ $backupfilelist[]=$file;
1304
+ }
1305
+ }
1306
+ }
1307
+ if (sizeof($backupfilelist)>0) {
1308
+ rsort($backupfilelist);
1309
+ $numdeltefiles=0;
1310
+ for ($i=$this->job['msazuremaxbackups'];$i<sizeof($backupfilelist);$i++) {
1311
+ $storageClient->deleteBlob($this->job['msazureContainer'],$this->job['msazuredir'].$backupfilelist[$i]); //delte files on Cloud
1312
+ $numdeltefiles++;
1313
+ }
1314
+ if ($numdeltefiles>0)
1315
+ trigger_error($numdeltefiles.' '.__('files deleted on Microsoft Azure Container!','backwpup'),E_USER_NOTICE);
1316
+ }
1317
+ }
1318
+
1319
+ } catch (Exception $e) {
1320
+ trigger_error(__('Microsoft Azure API:','backwpup').' '.__($e->getMessage(),'backwpup'),E_USER_ERROR);
1321
+ }
1322
+ }
1323
 
1324
  private function destination_dir() {
1325
  if (empty($this->job['backupdir'])) //Go back if no destination dir
app/functions5.php CHANGED
@@ -217,7 +217,28 @@ function backwpup_check_job_vars($jobsettings,$jobid='') {
217
 
218
  if (!isset($jobsettings['awsmaxbackups']) or !is_int($jobsettings['awsmaxbackups']))
219
  $jobsettings['awsmaxbackups']=0;
 
 
 
 
 
 
 
 
 
 
 
 
220
 
 
 
 
 
 
 
 
 
 
221
  if (!isset($jobsettings['rscUsername']) or !is_string($jobsettings['rscUsername']))
222
  $jobsettings['rscUsername']='';
223
 
@@ -264,6 +285,9 @@ function backwpup_get_backup_files($onlyjobid='') {
264
  $files=array();
265
  $donefolders=array();
266
  if (extension_loaded('curl') or @dl(PHP_SHLIB_SUFFIX == 'so' ? 'curl.so' : 'php_curl.dll')) {
 
 
 
267
  if (!class_exists('CFRuntime'))
268
  require_once(dirname(__FILE__).'/libs/aws/sdk.class.php');
269
  if (!class_exists('CF_Authentication'))
@@ -320,6 +344,28 @@ function backwpup_get_backup_files($onlyjobid='') {
320
  $donefolders[]=$jobvalue['awsAccessKey'].'|'.$jobvalue['awsBucket'].'|'.$jobvalue['awsdir'];
321
  }
322
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
323
  //Get files/filinfo from RSC
324
  if (class_exists('CF_Authentication') and in_array('RSC',$dests) and !in_array($jobvalue['rscUsername'].'|'.$jobvalue['rscContainer'].'|'.$jobvalue['rscdir'],$donefolders)) {
325
  if (!empty($jobvalue['rscUsername']) and !empty($jobvalue['rscAPIKey']) and !empty($jobvalue['rscContainer'])) {
@@ -382,10 +428,7 @@ function backwpup_get_backup_files($onlyjobid='') {
382
  $files[$filecounter]['filename']=basename($ftpfiles);
383
  $files[$filecounter]['downloadurl']="ftp://".$jobvalue['ftpuser'].":".base64_decode($jobvalue['ftppass'])."@".$jobvalue['ftphost'].$ftpfiles;
384
  $files[$filecounter]['filesize']=ftp_size($ftp_conn_id,$ftpfiles);
385
- if ('backwpup_log_' == substr(basename($ftpfiles),0,strlen('backwpup_log_'))) {
386
- $filnameparts=explode('_',substr(basename($ftpfiles),0,strpos(basename($ftpfiles),'.')));
387
- $files[$filecounter]['time']=strtotime($filnameparts[2].' '.str_replace('-',':',$filnameparts[3]));
388
- }
389
  $filecounter++;
390
  }
391
  }
@@ -428,11 +471,18 @@ function backwpup_get_aws_buckets($args='') {
428
  else
429
  return;
430
  }
431
- $s3 = new AmazonS3($awsAccessKey, $awsSecretKey);
432
- $buckets=$s3->list_buckets();
433
- //print_r($buckets);
 
 
 
 
 
 
 
434
  if ($buckets->status!=200) {
435
- echo '<span id="awsBucket" style="color:red;">'.__('No Buckets found! Or wrong Keys!','backwpup').'</span>';
436
  if ($ajax)
437
  die();
438
  else
@@ -477,9 +527,9 @@ function backwpup_get_rsc_container($args='') {
477
  else
478
  return;
479
  }
480
- $auth = new CF_Authentication($rscUsername, $rscAPIKey);
481
 
482
  try {
 
483
  $auth->authenticate();
484
  $conn = new CF_Connection($auth);
485
  $containers=$conn->get_containers();
@@ -507,5 +557,70 @@ function backwpup_get_rsc_container($args='') {
507
  die();
508
  else
509
  return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
510
  }
511
  ?>
217
 
218
  if (!isset($jobsettings['awsmaxbackups']) or !is_int($jobsettings['awsmaxbackups']))
219
  $jobsettings['awsmaxbackups']=0;
220
+
221
+ if (!isset($jobsettings['msazureHost']) or !is_string($jobsettings['msazureHost']))
222
+ $jobsettings['msazureHost']='blob.core.windows.net';
223
+
224
+ if (!isset($jobsettings['msazureAccName']) or !is_string($jobsettings['msazureAccName']))
225
+ $jobsettings['msazureAccName']='';
226
+
227
+ if (!isset($jobsettings['msazureKey']) or !is_string($jobsettings['msazureKey']))
228
+ $jobsettings['msazureKey']='';
229
+
230
+ if (!isset($jobsettings['msazureContainer']) or !is_string($jobsettings['msazureContainer']))
231
+ $jobsettings['msazureContainer']='';
232
 
233
+ if (!isset($jobsettings['msazuredir']) or !is_string($jobsettings['msazuredir']) or $jobsettings['msazuredir']=='/')
234
+ $jobsettings['msazuredir']='';
235
+ $jobsettings['msazuredir']=trailingslashit(str_replace('//','/',str_replace('\\','/',trim($jobsettings['msazuredir']))));
236
+ if (substr($jobsettings['msazuredir'],0,1)=='/')
237
+ $jobsettings['msazuredir']=substr($jobsettings['msazuredir'],1);
238
+
239
+ if (!isset($jobsettings['msazuremaxbackups']) or !is_int($jobsettings['msazuremaxbackups']))
240
+ $jobsettings['msazuremaxbackups']=0;
241
+
242
  if (!isset($jobsettings['rscUsername']) or !is_string($jobsettings['rscUsername']))
243
  $jobsettings['rscUsername']='';
244
 
285
  $files=array();
286
  $donefolders=array();
287
  if (extension_loaded('curl') or @dl(PHP_SHLIB_SUFFIX == 'so' ? 'curl.so' : 'php_curl.dll')) {
288
+ set_include_path(get_include_path().PATH_SEPARATOR.dirname(__FILE__).'/libs');
289
+ if (!class_exists('Microsoft_WindowsAzure_Storage_Blob'))
290
+ require_once 'Microsoft/WindowsAzure/Storage/Blob.php';
291
  if (!class_exists('CFRuntime'))
292
  require_once(dirname(__FILE__).'/libs/aws/sdk.class.php');
293
  if (!class_exists('CF_Authentication'))
344
  $donefolders[]=$jobvalue['awsAccessKey'].'|'.$jobvalue['awsBucket'].'|'.$jobvalue['awsdir'];
345
  }
346
  }
347
+ //Get files/filinfo from Microsoft Azure
348
+ if (class_exists('Microsoft_WindowsAzure_Storage_Blob') and in_array('MSAZURE',$dests) and !in_array($jobvalue['msazureAccName'].'|'.$jobvalue['msazureKey'].'|'.$jobvalue['msazureContainer'].'|'.$jobvalue['msazuredir'],$donefolders)) {
349
+ if (!empty($jobvalue['msazureHost']) and !empty($jobvalue['msazureAccName']) and !empty($jobvalue['msazureKey']) and !empty($jobvalue['msazureContainer'])) {
350
+ $storageClient = new Microsoft_WindowsAzure_Storage_Blob($jobvalue['msazureHost'],$jobvalue['msazureAccName'],$jobvalue['msazureKey']);
351
+ $blobs = $storageClient->listBlobs($jobvalue['msazureContainer'],$jobvalue['msazuredir']);
352
+ if (is_array($blobs)) {
353
+ foreach ($blobs as $blob) {
354
+ if (strtolower(substr($blob->Name,-4))=='.zip' or strtolower(substr($blob->Name,-4))=='.tar' or strtolower(substr($blob->Name,-7))=='.tar.gz' or strtolower(substr($blob->Name,-8))=='.tar.bz2') {
355
+ $files[$filecounter]['type']='MSAZURE';
356
+ $files[$filecounter]['jobid']=$jobid;
357
+ $files[$filecounter]['file']=$blob->Name;
358
+ $files[$filecounter]['filename']=basename($blob->Name);
359
+ $files[$filecounter]['downloadurl']='admin.php?page=BackWPup&subpage=backups&action=downloadmsazure&file='.$blob->Name.'&jobid='.$jobid;
360
+ $files[$filecounter]['filesize']=$blob->size;
361
+ $files[$filecounter]['time']=strtotime($blob->lastmodified);
362
+ $filecounter++;
363
+ }
364
+ }
365
+ }
366
+ $donefolders[]=$jobvalue['msazureAccName'].'|'.$jobvalue['msazureKey'].'|'.$jobvalue['msazureContainer'].'|'.$jobvalue['msazuredir'];
367
+ }
368
+ }
369
  //Get files/filinfo from RSC
370
  if (class_exists('CF_Authentication') and in_array('RSC',$dests) and !in_array($jobvalue['rscUsername'].'|'.$jobvalue['rscContainer'].'|'.$jobvalue['rscdir'],$donefolders)) {
371
  if (!empty($jobvalue['rscUsername']) and !empty($jobvalue['rscAPIKey']) and !empty($jobvalue['rscContainer'])) {
428
  $files[$filecounter]['filename']=basename($ftpfiles);
429
  $files[$filecounter]['downloadurl']="ftp://".$jobvalue['ftpuser'].":".base64_decode($jobvalue['ftppass'])."@".$jobvalue['ftphost'].$ftpfiles;
430
  $files[$filecounter]['filesize']=ftp_size($ftp_conn_id,$ftpfiles);
431
+ $files[$filecounter]['time']=ftp_mdtm($ftp_conn_id,$ftpfiles);
 
 
 
432
  $filecounter++;
433
  }
434
  }
471
  else
472
  return;
473
  }
474
+ try {
475
+ $s3 = new AmazonS3($awsAccessKey, $awsSecretKey);
476
+ $buckets=$s3->list_buckets();
477
+ } catch (Exception $e) {
478
+ echo '<span id="awsBucket" style="color:red;">'.__($e->getMessage(),'backwpup').'</span>';
479
+ if ($ajax)
480
+ die();
481
+ else
482
+ return;
483
+ }
484
  if ($buckets->status!=200) {
485
+ echo '<span id="awsBucket" style="color:red;">'.__('No Buckets found!','backwpup').'</span>';
486
  if ($ajax)
487
  die();
488
  else
527
  else
528
  return;
529
  }
 
530
 
531
  try {
532
+ $auth = new CF_Authentication($rscUsername, $rscAPIKey);
533
  $auth->authenticate();
534
  $conn = new CF_Connection($auth);
535
  $containers=$conn->get_containers();
557
  die();
558
  else
559
  return;
560
+ }
561
+
562
+ //ajax/normal get buckests select box
563
+ function backwpup_get_msazure_container($args='') {
564
+ if (is_array($args)) {
565
+ extract($args);
566
+ $ajax=false;
567
+ } else {
568
+ $msazureHost=$_POST['msazureHost'];
569
+ $msazureAccName=$_POST['msazureAccName'];
570
+ $msazureKey=$_POST['msazureKey'];
571
+ $msazureselected=$_POST['msazureselected'];
572
+ $ajax=true;
573
+ }
574
+ if (!class_exists('Microsoft_WindowsAzure_Storage_Blob')) {
575
+ set_include_path(get_include_path().PATH_SEPARATOR.dirname(__FILE__).'/libs');
576
+ require_once 'Microsoft/WindowsAzure/Storage/Blob.php';
577
+ }
578
+ if (empty($msazureHost)) {
579
+ echo '<span id="msazureContainer" style="color:red;">'.__('Missing Hostname!','backwpup').'</span>';
580
+ if ($ajax)
581
+ die();
582
+ else
583
+ return;
584
+ }
585
+ if (empty($msazureAccName)) {
586
+ echo '<span id="msazureContainer" style="color:red;">'.__('Missing Account Name!','backwpup').'</span>';
587
+ if ($ajax)
588
+ die();
589
+ else
590
+ return;
591
+ }
592
+ if (empty($msazureKey)) {
593
+ echo '<span id="msazureContainer" style="color:red;">'.__('Missing Access Key!','backwpup').'</span>';
594
+ if ($ajax)
595
+ die();
596
+ else
597
+ return;
598
+ }
599
+ try {
600
+ $storageClient = new Microsoft_WindowsAzure_Storage_Blob($msazureHost,$msazureAccName,$msazureKey);
601
+ $Containers=$storageClient->listContainers();
602
+ } catch (Exception $e) {
603
+ echo '<span id="msazureContainer" style="color:red;">'.$e->getMessage().'</span>';
604
+ if ($ajax)
605
+ die();
606
+ else
607
+ return;
608
+ }
609
+ if (empty($Containers)) {
610
+ echo '<span id="msazureContainer" style="color:red;">'.__('No Container found!','backwpup').'</span>';
611
+ if ($ajax)
612
+ die();
613
+ else
614
+ return;
615
+ }
616
+ echo '<select name="msazureContainer" id="msazureContainer">';
617
+ foreach ($Containers as $Container) {
618
+ echo "<option ".selected(strtolower($msazureselected),strtolower($Container->Name),false).">".$Container->Name."</option>";
619
+ }
620
+ echo '</select>';
621
+ if ($ajax)
622
+ die();
623
+ else
624
+ return;
625
  }
626
  ?>
app/js/options.js CHANGED
@@ -5,14 +5,18 @@ jQuery(document).ready( function($) {
5
  $('#fileformart').show();
6
  $('#toftp').show();
7
  $('#toamazon').show();
 
8
  $('#torsc').show();
 
9
  $('#todir').show();
10
  $('#tomail').show();
11
  } else {
12
  $('#fileformart').hide();
13
  $('#toftp').hide();
14
  $('#toamazon').hide();
 
15
  $('#torsc').hide();
 
16
  $('#todir').hide();
17
  $('#tomail').hide();
18
  }
@@ -66,6 +70,28 @@ jQuery(document).ready( function($) {
66
  $('#awsAccessKey').change(function() {awsgetbucket();});
67
  $('#awsSecretKey').change(function() {awsgetbucket();});
68
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  function rscgetcontainer() {
70
  var rscUsername = $('#rscUsername').val();
71
  var rscAPIKey = $('#rscAPIKey').val();
5
  $('#fileformart').show();
6
  $('#toftp').show();
7
  $('#toamazon').show();
8
+ $('#tomsazure').show();
9
  $('#torsc').show();
10
+ $('#todropbox').show();
11
  $('#todir').show();
12
  $('#tomail').show();
13
  } else {
14
  $('#fileformart').hide();
15
  $('#toftp').hide();
16
  $('#toamazon').hide();
17
+ $('#tomsazure').hide();
18
  $('#torsc').hide();
19
+ $('#todropbox').hide();
20
  $('#todir').hide();
21
  $('#tomail').hide();
22
  }
70
  $('#awsAccessKey').change(function() {awsgetbucket();});
71
  $('#awsSecretKey').change(function() {awsgetbucket();});
72
 
73
+ function msazuregetcontainer() {
74
+ var msazureHost = $('#msazureHost').val();
75
+ var msazureAccName = $('#msazureAccName').val();
76
+ var msazureKey = $('#msazureKey').val();
77
+ var msazureContainer = $('#msazureContainerselected').val();
78
+ var data = {
79
+ action: 'backwpup_get_msazure_container',
80
+ msazureHost: msazureHost,
81
+ msazureAccName: msazureAccName,
82
+ msazureKey: msazureKey,
83
+ msazureselected: msazureContainer
84
+ };
85
+ $.post(ajaxurl, data, function(response) {
86
+ $('#msazureContainer').remove();
87
+ $('#msazureContainerselected').after(response);
88
+ });
89
+ }
90
+
91
+ $('#msazureHost').change(function() {msazuregetcontainer();});
92
+ $('#msazureAccName').change(function() {msazuregetcontainer();});
93
+ $('#msazureKey').change(function() {msazuregetcontainer();});
94
+
95
  function rscgetcontainer() {
96
  var rscUsername = $('#rscUsername').val();
97
  var rscAPIKey = $('#rscAPIKey').val();
app/libs/Microsoft/Exception.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft
30
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
31
+ * @license http://phpazure.codeplex.com/license
32
+ */
33
+
34
+
35
+ /**
36
+ * @category Microsoft
37
+ * @package Microsoft
38
+ * @subpackage Exception
39
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
40
+ * @license http://phpazure.codeplex.com/license
41
+ */
42
+ class Microsoft_Exception extends Exception
43
+ {}
app/libs/Microsoft/Http/Client.php ADDED
@@ -0,0 +1,1444 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Zend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category Microsoft
17
+ * @package Microsoft_Http
18
+ * @subpackage Client
19
+ * @version $Id: Client.php 19661 2009-12-15 18:03:07Z matthew $
20
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
21
+ * @license http://framework.zend.com/license/new-bsd New BSD License
22
+ */
23
+
24
+
25
+ /**
26
+ * @see Microsoft_Uri
27
+ */
28
+ require_once 'Microsoft/Uri.php';
29
+
30
+
31
+ /**
32
+ * @see Microsoft_Http_Client_Adapter_Interface
33
+ */
34
+ require_once 'Microsoft/Http/Client/Adapter/Interface.php';
35
+
36
+
37
+ /**
38
+ * @see Microsoft_Http_Response
39
+ */
40
+ require_once 'Microsoft/Http/Response.php';
41
+
42
+ /**
43
+ * @see Microsoft_Http_Response_Stream
44
+ */
45
+ require_once 'Microsoft/Http/Response/Stream.php';
46
+
47
+ /**
48
+ * Microsoft_Http_Client is an implemetation of an HTTP client in PHP. The client
49
+ * supports basic features like sending different HTTP requests and handling
50
+ * redirections, as well as more advanced features like proxy settings, HTTP
51
+ * authentication and cookie persistance (using a Microsoft_Http_CookieJar object)
52
+ *
53
+ * @todo Implement proxy settings
54
+ * @category Microsoft
55
+ * @package Microsoft_Http
56
+ * @subpackage Client
57
+ * @throws Microsoft_Http_Client_Exception
58
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
59
+ * @license http://framework.zend.com/license/new-bsd New BSD License
60
+ */
61
+ class Microsoft_Http_Client
62
+ {
63
+ /**
64
+ * HTTP request methods
65
+ */
66
+ const GET = 'GET';
67
+ const POST = 'POST';
68
+ const PUT = 'PUT';
69
+ const HEAD = 'HEAD';
70
+ const DELETE = 'DELETE';
71
+ const TRACE = 'TRACE';
72
+ const OPTIONS = 'OPTIONS';
73
+ const CONNECT = 'CONNECT';
74
+ const MERGE = 'MERGE';
75
+
76
+ /**
77
+ * Supported HTTP Authentication methods
78
+ */
79
+ const AUTH_BASIC = 'basic';
80
+ //const AUTH_DIGEST = 'digest'; <-- not implemented yet
81
+
82
+ /**
83
+ * HTTP protocol versions
84
+ */
85
+ const HTTP_1 = '1.1';
86
+ const HTTP_0 = '1.0';
87
+
88
+ /**
89
+ * Content attributes
90
+ */
91
+ const CONTENT_TYPE = 'Content-Type';
92
+ const CONTENT_LENGTH = 'Content-Length';
93
+
94
+ /**
95
+ * POST data encoding methods
96
+ */
97
+ const ENC_URLENCODED = 'application/x-www-form-urlencoded';
98
+ const ENC_FORMDATA = 'multipart/form-data';
99
+
100
+ /**
101
+ * Configuration array, set using the constructor or using ::setConfig()
102
+ *
103
+ * @var array
104
+ */
105
+ protected $config = array(
106
+ 'maxredirects' => 5,
107
+ 'strictredirects' => false,
108
+ 'useragent' => 'Microsoft_Http_Client',
109
+ 'timeout' => 10,
110
+ 'adapter' => 'Microsoft_Http_Client_Adapter_Socket',
111
+ 'httpversion' => self::HTTP_1,
112
+ 'keepalive' => false,
113
+ 'storeresponse' => true,
114
+ 'strict' => true,
115
+ 'output_stream' => false,
116
+ );
117
+
118
+ /**
119
+ * The adapter used to preform the actual connection to the server
120
+ *
121
+ * @var Microsoft_Http_Client_Adapter_Interface
122
+ */
123
+ protected $adapter = null;
124
+
125
+ /**
126
+ * Request URI
127
+ *
128
+ * @var Microsoft_Uri_Http
129
+ */
130
+ protected $uri = null;
131
+
132
+ /**
133
+ * Associative array of request headers
134
+ *
135
+ * @var array
136
+ */
137
+ protected $headers = array();
138
+
139
+ /**
140
+ * HTTP request method
141
+ *
142
+ * @var string
143
+ */
144
+ protected $method = self::GET;
145
+
146
+ /**
147
+ * Associative array of GET parameters
148
+ *
149
+ * @var array
150
+ */
151
+ protected $paramsGet = array();
152
+
153
+ /**
154
+ * Assiciative array of POST parameters
155
+ *
156
+ * @var array
157
+ */
158
+ protected $paramsPost = array();
159
+
160
+ /**
161
+ * Request body content type (for POST requests)
162
+ *
163
+ * @var string
164
+ */
165
+ protected $enctype = null;
166
+
167
+ /**
168
+ * The raw post data to send. Could be set by setRawData($data, $enctype).
169
+ *
170
+ * @var string
171
+ */
172
+ protected $raw_post_data = null;
173
+
174
+ /**
175
+ * HTTP Authentication settings
176
+ *
177
+ * Expected to be an associative array with this structure:
178
+ * $this->auth = array('user' => 'username', 'password' => 'password', 'type' => 'basic')
179
+ * Where 'type' should be one of the supported authentication types (see the AUTH_*
180
+ * constants), for example 'basic' or 'digest'.
181
+ *
182
+ * If null, no authentication will be used.
183
+ *
184
+ * @var array|null
185
+ */
186
+ protected $auth;
187
+
188
+ /**
189
+ * File upload arrays (used in POST requests)
190
+ *
191
+ * An associative array, where each element is of the format:
192
+ * 'name' => array('filename.txt', 'text/plain', 'This is the actual file contents')
193
+ *
194
+ * @var array
195
+ */
196
+ protected $files = array();
197
+
198
+ /**
199
+ * The client's cookie jar
200
+ *
201
+ * @var Microsoft_Http_CookieJar
202
+ */
203
+ protected $cookiejar = null;
204
+
205
+ /**
206
+ * The last HTTP request sent by the client, as string
207
+ *
208
+ * @var string
209
+ */
210
+ protected $last_request = null;
211
+
212
+ /**
213
+ * The last HTTP response received by the client
214
+ *
215
+ * @var Microsoft_Http_Response
216
+ */
217
+ protected $last_response = null;
218
+
219
+ /**
220
+ * Redirection counter
221
+ *
222
+ * @var int
223
+ */
224
+ protected $redirectCounter = 0;
225
+
226
+ /**
227
+ * Fileinfo magic database resource
228
+ *
229
+ * This varaiable is populated the first time _detectFileMimeType is called
230
+ * and is then reused on every call to this method
231
+ *
232
+ * @var resource
233
+ */
234
+ static protected $_fileInfoDb = null;
235
+
236
+ /**
237
+ * Contructor method. Will create a new HTTP client. Accepts the target
238
+ * URL and optionally configuration array.
239
+ *
240
+ * @param Microsoft_Uri_Http|string $uri
241
+ * @param array $config Configuration key-value pairs.
242
+ */
243
+ public function __construct($uri = null, $config = null)
244
+ {
245
+ if ($uri !== null) {
246
+ $this->setUri($uri);
247
+ }
248
+ if ($config !== null) {
249
+ $this->setConfig($config);
250
+ }
251
+ }
252
+
253
+ /**
254
+ * Set the URI for the next request
255
+ *
256
+ * @param Microsoft_Uri_Http|string $uri
257
+ * @return Microsoft_Http_Client
258
+ * @throws Microsoft_Http_Client_Exception
259
+ */
260
+ public function setUri($uri)
261
+ {
262
+ if (is_string($uri)) {
263
+ $uri = Microsoft_Uri::factory($uri);
264
+ }
265
+
266
+ if (!$uri instanceof Microsoft_Uri_Http) {
267
+ /** @see Microsoft_Http_Client_Exception */
268
+ require_once 'Microsoft/Http/Client/Exception.php';
269
+ throw new Microsoft_Http_Client_Exception('Passed parameter is not a valid HTTP URI.');
270
+ }
271
+
272
+ // Set auth if username and password has been specified in the uri
273
+ if ($uri->getUsername() && $uri->getPassword()) {
274
+ $this->setAuth($uri->getUsername(), $uri->getPassword());
275
+ }
276
+
277
+ // We have no ports, set the defaults
278
+ if (! $uri->getPort()) {
279
+ $uri->setPort(($uri->getScheme() == 'https' ? 443 : 80));
280
+ }
281
+
282
+ $this->uri = $uri;
283
+
284
+ return $this;
285
+ }
286
+
287
+ /**
288
+ * Get the URI for the next request
289
+ *
290
+ * @param boolean $as_string If true, will return the URI as a string
291
+ * @return Microsoft_Uri_Http|string
292
+ */
293
+ public function getUri($as_string = false)
294
+ {
295
+ if ($as_string && $this->uri instanceof Microsoft_Uri_Http) {
296
+ return $this->uri->__toString();
297
+ } else {
298
+ return $this->uri;
299
+ }
300
+ }
301
+
302
+ /**
303
+ * Set configuration parameters for this HTTP client
304
+ *
305
+ * @param Microsoft_Config | array $config
306
+ * @return Microsoft_Http_Client
307
+ * @throws Microsoft_Http_Client_Exception
308
+ */
309
+ public function setConfig($config = array())
310
+ {
311
+ if ($config instanceof Microsoft_Config) {
312
+ $config = $config->toArray();
313
+
314
+ } elseif (! is_array($config)) {
315
+ /** @see Microsoft_Http_Client_Exception */
316
+ require_once 'Microsoft/Http/Client/Exception.php';
317
+ throw new Microsoft_Http_Client_Exception('Array expected, got ' . gettype($config));
318
+ }
319
+
320
+ foreach ($config as $k => $v) {
321
+ $this->config[strtolower($k)] = $v;
322
+ }
323
+
324
+ // Pass configuration options to the adapter if it exists
325
+ if ($this->adapter instanceof Microsoft_Http_Client_Adapter_Interface) {
326
+ $this->adapter->setConfig($config);
327
+ }
328
+
329
+ return $this;
330
+ }
331
+
332
+ /**
333
+ * Set the next request's method
334
+ *
335
+ * Validated the passed method and sets it. If we have files set for
336
+ * POST requests, and the new method is not POST, the files are silently
337
+ * dropped.
338
+ *
339
+ * @param string $method
340
+ * @return Microsoft_Http_Client
341
+ * @throws Microsoft_Http_Client_Exception
342
+ */
343
+ public function setMethod($method = self::GET)
344
+ {
345
+ if (! preg_match('/^[^\x00-\x1f\x7f-\xff\(\)<>@,;:\\\\"\/\[\]\?={}\s]+$/', $method)) {
346
+ /** @see Microsoft_Http_Client_Exception */
347
+ require_once 'Microsoft/Http/Client/Exception.php';
348
+ throw new Microsoft_Http_Client_Exception("'{$method}' is not a valid HTTP request method.");
349
+ }
350
+
351
+ if ($method == self::POST && $this->enctype === null) {
352
+ $this->setEncType(self::ENC_URLENCODED);
353
+ }
354
+
355
+ $this->method = $method;
356
+
357
+ return $this;
358
+ }
359
+
360
+ /**
361
+ * Set one or more request headers
362
+ *
363
+ * This function can be used in several ways to set the client's request
364
+ * headers:
365
+ * 1. By providing two parameters: $name as the header to set (eg. 'Host')
366
+ * and $value as it's value (eg. 'www.example.com').
367
+ * 2. By providing a single header string as the only parameter
368
+ * eg. 'Host: www.example.com'
369
+ * 3. By providing an array of headers as the first parameter
370
+ * eg. array('host' => 'www.example.com', 'x-foo: bar'). In This case
371
+ * the function will call itself recursively for each array item.
372
+ *
373
+ * @param string|array $name Header name, full header string ('Header: value')
374
+ * or an array of headers
375
+ * @param mixed $value Header value or null
376
+ * @return Microsoft_Http_Client
377
+ * @throws Microsoft_Http_Client_Exception
378
+ */
379
+ public function setHeaders($name, $value = null)
380
+ {
381
+ // If we got an array, go recusive!
382
+ if (is_array($name)) {
383
+ foreach ($name as $k => $v) {
384
+ if (is_string($k)) {
385
+ $this->setHeaders($k, $v);
386
+ } else {
387
+ $this->setHeaders($v, null);
388
+ }
389
+ }
390
+ } else {
391
+ // Check if $name needs to be split
392
+ if ($value === null && (strpos($name, ':') > 0)) {
393
+ list($name, $value) = explode(':', $name, 2);
394
+ }
395
+
396
+ // Make sure the name is valid if we are in strict mode
397
+ if ($this->config['strict'] && (! preg_match('/^[a-zA-Z0-9-]+$/', $name))) {
398
+ /** @see Microsoft_Http_Client_Exception */
399
+ require_once 'Microsoft/Http/Client/Exception.php';
400
+ throw new Microsoft_Http_Client_Exception("{$name} is not a valid HTTP header name");
401
+ }
402
+
403
+ $normalized_name = strtolower($name);
404
+
405
+ // If $value is null or false, unset the header
406
+ if ($value === null || $value === false) {
407
+ unset($this->headers[$normalized_name]);
408
+
409
+ // Else, set the header
410
+ } else {
411
+ // Header names are stored lowercase internally.
412
+ if (is_string($value)) {
413
+ $value = trim($value);
414
+ }
415
+ $this->headers[$normalized_name] = array($name, $value);
416
+ }
417
+ }
418
+
419
+ return $this;
420
+ }
421
+
422
+ /**
423
+ * Get the value of a specific header
424
+ *
425
+ * Note that if the header has more than one value, an array
426
+ * will be returned.
427
+ *
428
+ * @param string $key
429
+ * @return string|array|null The header value or null if it is not set
430
+ */
431
+ public function getHeader($key)
432
+ {
433
+ $key = strtolower($key);
434
+ if (isset($this->headers[$key])) {
435
+ return $this->headers[$key][1];
436
+ } else {
437
+ return null;
438
+ }
439
+ }
440
+
441
+ /**
442
+ * Set a GET parameter for the request. Wrapper around _setParameter
443
+ *
444
+ * @param string|array $name
445
+ * @param string $value
446
+ * @return Microsoft_Http_Client
447
+ */
448
+ public function setParameterGet($name, $value = null)
449
+ {
450
+ if (is_array($name)) {
451
+ foreach ($name as $k => $v)
452
+ $this->_setParameter('GET', $k, $v);
453
+ } else {
454
+ $this->_setParameter('GET', $name, $value);
455
+ }
456
+
457
+ return $this;
458
+ }
459
+
460
+ /**
461
+ * Set a POST parameter for the request. Wrapper around _setParameter
462
+ *
463
+ * @param string|array $name
464
+ * @param string $value
465
+ * @return Microsoft_Http_Client
466
+ */
467
+ public function setParameterPost($name, $value = null)
468
+ {
469
+ if (is_array($name)) {
470
+ foreach ($name as $k => $v)
471
+ $this->_setParameter('POST', $k, $v);
472
+ } else {
473
+ $this->_setParameter('POST', $name, $value);
474
+ }
475
+
476
+ return $this;
477
+ }
478
+
479
+ /**
480
+ * Set a GET or POST parameter - used by SetParameterGet and SetParameterPost
481
+ *
482
+ * @param string $type GET or POST
483
+ * @param string $name
484
+ * @param string $value
485
+ * @return null
486
+ */
487
+ protected function _setParameter($type, $name, $value)
488
+ {
489
+ $parray = array();
490
+ $type = strtolower($type);
491
+ switch ($type) {
492
+ case 'get':
493
+ $parray = &$this->paramsGet;
494
+ break;
495
+ case 'post':
496
+ $parray = &$this->paramsPost;
497
+ break;
498
+ }
499
+
500
+ if ($value === null) {
501
+ if (isset($parray[$name])) unset($parray[$name]);
502
+ } else {
503
+ $parray[$name] = $value;
504
+ }
505
+ }
506
+
507
+ /**
508
+ * Get the number of redirections done on the last request
509
+ *
510
+ * @return int
511
+ */
512
+ public function getRedirectionsCount()
513
+ {
514
+ return $this->redirectCounter;
515
+ }
516
+
517
+ /**
518
+ * Set HTTP authentication parameters
519
+ *
520
+ * $type should be one of the supported types - see the self::AUTH_*
521
+ * constants.
522
+ *
523
+ * To enable authentication:
524
+ * <code>
525
+ * $this->setAuth('shahar', 'secret', Microsoft_Http_Client::AUTH_BASIC);
526
+ * </code>
527
+ *
528
+ * To disable authentication:
529
+ * <code>
530
+ * $this->setAuth(false);
531
+ * </code>
532
+ *
533
+ * @see http://www.faqs.org/rfcs/rfc2617.html
534
+ * @param string|false $user User name or false disable authentication
535
+ * @param string $password Password
536
+ * @param string $type Authentication type
537
+ * @return Microsoft_Http_Client
538
+ * @throws Microsoft_Http_Client_Exception
539
+ */
540
+ public function setAuth($user, $password = '', $type = self::AUTH_BASIC)
541
+ {
542
+ // If we got false or null, disable authentication
543
+ if ($user === false || $user === null) {
544
+ $this->auth = null;
545
+
546
+ // Clear the auth information in the uri instance as well
547
+ if ($this->uri instanceof Microsoft_Uri_Http) {
548
+ $this->getUri()->setUsername('');
549
+ $this->getUri()->setPassword('');
550
+ }
551
+ // Else, set up authentication
552
+ } else {
553
+ // Check we got a proper authentication type
554
+ if (! defined('self::AUTH_' . strtoupper($type))) {
555
+ /** @see Microsoft_Http_Client_Exception */
556
+ require_once 'Microsoft/Http/Client/Exception.php';
557
+ throw new Microsoft_Http_Client_Exception("Invalid or not supported authentication type: '$type'");
558
+ }
559
+
560
+ $this->auth = array(
561
+ 'user' => (string) $user,
562
+ 'password' => (string) $password,
563
+ 'type' => $type
564
+ );
565
+ }
566
+
567
+ return $this;
568
+ }
569
+
570
+ /**
571
+ * Set the HTTP client's cookie jar.
572
+ *
573
+ * A cookie jar is an object that holds and maintains cookies across HTTP requests
574
+ * and responses.
575
+ *
576
+ * @param Microsoft_Http_CookieJar|boolean $cookiejar Existing cookiejar object, true to create a new one, false to disable
577
+ * @return Microsoft_Http_Client
578
+ * @throws Microsoft_Http_Client_Exception
579
+ */
580
+ public function setCookieJar($cookiejar = true)
581
+ {
582
+ if (! class_exists('Microsoft_Http_CookieJar')) {
583
+ require_once 'Microsoft/Http/CookieJar.php';
584
+ }
585
+
586
+ if ($cookiejar instanceof Microsoft_Http_CookieJar) {
587
+ $this->cookiejar = $cookiejar;
588
+ } elseif ($cookiejar === true) {
589
+ $this->cookiejar = new Microsoft_Http_CookieJar();
590
+ } elseif (! $cookiejar) {
591
+ $this->cookiejar = null;
592
+ } else {
593
+ /** @see Microsoft_Http_Client_Exception */
594
+ require_once 'Microsoft/Http/Client/Exception.php';
595
+ throw new Microsoft_Http_Client_Exception('Invalid parameter type passed as CookieJar');
596
+ }
597
+
598
+ return $this;
599
+ }
600
+
601
+ /**
602
+ * Return the current cookie jar or null if none.
603
+ *
604
+ * @return Microsoft_Http_CookieJar|null
605
+ */
606
+ public function getCookieJar()
607
+ {
608
+ return $this->cookiejar;
609
+ }
610
+
611
+ /**
612
+ * Add a cookie to the request. If the client has no Cookie Jar, the cookies
613
+ * will be added directly to the headers array as "Cookie" headers.
614
+ *
615
+ * @param Microsoft_Http_Cookie|string $cookie
616
+ * @param string|null $value If "cookie" is a string, this is the cookie value.
617
+ * @return Microsoft_Http_Client
618
+ * @throws Microsoft_Http_Client_Exception
619
+ */
620
+ public function setCookie($cookie, $value = null)
621
+ {
622
+ if (! class_exists('Microsoft_Http_Cookie')) {
623
+ require_once 'Microsoft/Http/Cookie.php';
624
+ }
625
+
626
+ if (is_array($cookie)) {
627
+ foreach ($cookie as $c => $v) {
628
+ if (is_string($c)) {
629
+ $this->setCookie($c, $v);
630
+ } else {
631
+ $this->setCookie($v);
632
+ }
633
+ }
634
+
635
+ return $this;
636
+ }
637
+
638
+ if ($value !== null) {
639
+ $value = urlencode($value);
640
+ }
641
+
642
+ if (isset($this->cookiejar)) {
643
+ if ($cookie instanceof Microsoft_Http_Cookie) {
644
+ $this->cookiejar->addCookie($cookie);
645
+ } elseif (is_string($cookie) && $value !== null) {
646
+ $cookie = Microsoft_Http_Cookie::fromString("{$cookie}={$value}", $this->uri);
647
+ $this->cookiejar->addCookie($cookie);
648
+ }
649
+ } else {
650
+ if ($cookie instanceof Microsoft_Http_Cookie) {
651
+ $name = $cookie->getName();
652
+ $value = $cookie->getValue();
653
+ $cookie = $name;
654
+ }
655
+
656
+ if (preg_match("/[=,; \t\r\n\013\014]/", $cookie)) {
657
+ /** @see Microsoft_Http_Client_Exception */
658
+ require_once 'Microsoft/Http/Client/Exception.php';
659
+ throw new Microsoft_Http_Client_Exception("Cookie name cannot contain these characters: =,; \t\r\n\013\014 ({$cookie})");
660
+ }
661
+
662
+ $value = addslashes($value);
663
+
664
+ if (! isset($this->headers['cookie'])) {
665
+ $this->headers['cookie'] = array('Cookie', '');
666
+ }
667
+ $this->headers['cookie'][1] .= $cookie . '=' . $value . '; ';
668
+ }
669
+
670
+ return $this;
671
+ }
672
+
673
+ /**
674
+ * Set a file to upload (using a POST request)
675
+ *
676
+ * Can be used in two ways:
677
+ *
678
+ * 1. $data is null (default): $filename is treated as the name if a local file which
679
+ * will be read and sent. Will try to guess the content type using mime_content_type().
680
+ * 2. $data is set - $filename is sent as the file name, but $data is sent as the file
681
+ * contents and no file is read from the file system. In this case, you need to
682
+ * manually set the Content-Type ($ctype) or it will default to
683
+ * application/octet-stream.
684
+ *
685
+ * @param string $filename Name of file to upload, or name to save as
686
+ * @param string $formname Name of form element to send as
687
+ * @param string $data Data to send (if null, $filename is read and sent)
688
+ * @param string $ctype Content type to use (if $data is set and $ctype is
689
+ * null, will be application/octet-stream)
690
+ * @return Microsoft_Http_Client
691
+ * @throws Microsoft_Http_Client_Exception
692
+ */
693
+ public function setFileUpload($filename, $formname, $data = null, $ctype = null)
694
+ {
695
+ if ($data === null) {
696
+ if (($data = @file_get_contents($filename)) === false) {
697
+ /** @see Microsoft_Http_Client_Exception */
698
+ require_once 'Microsoft/Http/Client/Exception.php';
699
+ throw new Microsoft_Http_Client_Exception("Unable to read file '{$filename}' for upload");
700
+ }
701
+
702
+ if (! $ctype) {
703
+ $ctype = $this->_detectFileMimeType($filename);
704
+ }
705
+ }
706
+
707
+ // Force enctype to multipart/form-data
708
+ $this->setEncType(self::ENC_FORMDATA);
709
+
710
+ $this->files[] = array(
711
+ 'formname' => $formname,
712
+ 'filename' => basename($filename),
713
+ 'ctype' => $ctype,
714
+ 'data' => $data
715
+ );
716
+
717
+ return $this;
718
+ }
719
+
720
+ /**
721
+ * Set the encoding type for POST data
722
+ *
723
+ * @param string $enctype
724
+ * @return Microsoft_Http_Client
725
+ */
726
+ public function setEncType($enctype = self::ENC_URLENCODED)
727
+ {
728
+ $this->enctype = $enctype;
729
+
730
+ return $this;
731
+ }
732
+
733
+ /**
734
+ * Set the raw (already encoded) POST data.
735
+ *
736
+ * This function is here for two reasons:
737
+ * 1. For advanced user who would like to set their own data, already encoded
738
+ * 2. For backwards compatibilty: If someone uses the old post($data) method.
739
+ * this method will be used to set the encoded data.
740
+ *
741
+ * $data can also be stream (such as file) from which the data will be read.
742
+ *
743
+ * @param string|resource $data
744
+ * @param string $enctype
745
+ * @return Microsoft_Http_Client
746
+ */
747
+ public function setRawData($data, $enctype = null)
748
+ {
749
+ $this->raw_post_data = $data;
750
+ $this->setEncType($enctype);
751
+ if (is_resource($data)) {
752
+ // We've got stream data
753
+ $stat = @fstat($data);
754
+ if($stat) {
755
+ $this->setHeaders(self::CONTENT_LENGTH, $stat['size']);
756
+ }
757
+ }
758
+ return $this;
759
+ }
760
+
761
+ /**
762
+ * Clear all GET and POST parameters
763
+ *
764
+ * Should be used to reset the request parameters if the client is
765
+ * used for several concurrent requests.
766
+ *
767
+ * clearAll parameter controls if we clean just parameters or also
768
+ * headers and last_*
769
+ *
770
+ * @param bool $clearAll Should all data be cleared?
771
+ * @return Microsoft_Http_Client
772
+ */
773
+ public function resetParameters($clearAll = false)
774
+ {
775
+ // Reset parameter data
776
+ $this->paramsGet = array();
777
+ $this->paramsPost = array();
778
+ $this->files = array();
779
+ $this->raw_post_data = null;
780
+
781
+ if($clearAll) {
782
+ $this->headers = array();
783
+ $this->last_request = null;
784
+ $this->last_response = null;
785
+ } else {
786
+ // Clear outdated headers
787
+ if (isset($this->headers[strtolower(self::CONTENT_TYPE)])) {
788
+ unset($this->headers[strtolower(self::CONTENT_TYPE)]);
789
+ }
790
+ if (isset($this->headers[strtolower(self::CONTENT_LENGTH)])) {
791
+ unset($this->headers[strtolower(self::CONTENT_LENGTH)]);
792
+ }
793
+ }
794
+
795
+ return $this;
796
+ }
797
+
798
+ /**
799
+ * Get the last HTTP request as string
800
+ *
801
+ * @return string
802
+ */
803
+ public function getLastRequest()
804
+ {
805
+ return $this->last_request;
806
+ }
807
+
808
+ /**
809
+ * Get the last HTTP response received by this client
810
+ *
811
+ * If $config['storeresponse'] is set to false, or no response was
812
+ * stored yet, will return null
813
+ *
814
+ * @return Microsoft_Http_Response or null if none
815
+ */
816
+ public function getLastResponse()
817
+ {
818
+ return $this->last_response;
819
+ }
820
+
821
+ /**
822
+ * Load the connection adapter
823
+ *
824
+ * While this method is not called more than one for a client, it is
825
+ * seperated from ->request() to preserve logic and readability
826
+ *
827
+ * @param Microsoft_Http_Client_Adapter_Interface|string $adapter
828
+ * @return null
829
+ * @throws Microsoft_Http_Client_Exception
830
+ */
831
+ public function setAdapter($adapter)
832
+ {
833
+ if (is_string($adapter)) {
834
+ if (!class_exists($adapter)) {
835
+ @require_once( str_replace('_', '/', $adapter) . '.php' );
836
+ }
837
+
838
+ $adapter = new $adapter;
839
+ }
840
+
841
+ if (! $adapter instanceof Microsoft_Http_Client_Adapter_Interface) {
842
+ /** @see Microsoft_Http_Client_Exception */
843
+ require_once 'Microsoft/Http/Client/Exception.php';
844
+ throw new Microsoft_Http_Client_Exception('Passed adapter is not a HTTP connection adapter');
845
+ }
846
+
847
+ $this->adapter = $adapter;
848
+ $config = $this->config;
849
+ unset($config['adapter']);
850
+ $this->adapter->setConfig($config);
851
+ }
852
+
853
+ /**
854
+ * Load the connection adapter
855
+ *
856
+ * @return Microsoft_Http_Client_Adapter_Interface $adapter
857
+ */
858
+ public function getAdapter()
859
+ {
860
+ return $this->adapter;
861
+ }
862
+
863
+ /**
864
+ * Set streaming for received data
865
+ *
866
+ * @param string|boolean $streamfile Stream file, true for temp file, false/null for no streaming
867
+ * @return Microsoft_Http_Client
868
+ */
869
+ public function setStream($streamfile = true)
870
+ {
871
+ $this->setConfig(array("output_stream" => $streamfile));
872
+ return $this;
873
+ }
874
+
875
+ /**
876
+ * Get status of streaming for received data
877
+ * @return boolean|string
878
+ */
879
+ public function getStream()
880
+ {
881
+ return $this->config["output_stream"];
882
+ }
883
+
884
+ /**
885
+ * Create temporary stream
886
+ *
887
+ * @return resource
888
+ */
889
+ protected function _openTempStream()
890
+ {
891
+ $this->_stream_name = $this->config['output_stream'];
892
+ if(!is_string($this->_stream_name)) {
893
+ // If name is not given, create temp name
894
+ $this->_stream_name = tempnam(isset($this->config['stream_tmp_dir'])?$this->config['stream_tmp_dir']:sys_get_temp_dir(),
895
+ 'Microsoft_Http_Client');
896
+ }
897
+
898
+ $fp = fopen($this->_stream_name, "w+b");
899
+ if(!$fp) {
900
+ $this->close();
901
+ require_once 'Microsoft/Http/Client/Exception.php';
902
+ throw new Microsoft_Http_Client_Exception("Could not open temp file $name");
903
+
904
+ }
905
+ return $fp;
906
+ }
907
+
908
+ /**
909
+ * Send the HTTP request and return an HTTP response object
910
+ *
911
+ * @param string $method
912
+ * @return Microsoft_Http_Response
913
+ * @throws Microsoft_Http_Client_Exception
914
+ */
915
+ public function request($method = null)
916
+ {
917
+ if (! $this->uri instanceof Microsoft_Uri_Http) {
918
+ /** @see Microsoft_Http_Client_Exception */
919
+ require_once 'Microsoft/Http/Client/Exception.php';
920
+ throw new Microsoft_Http_Client_Exception('No valid URI has been passed to the client');
921
+ }
922
+
923
+ if ($method) {
924
+ $this->setMethod($method);
925
+ }
926
+ $this->redirectCounter = 0;
927
+ $response = null;
928
+
929
+ // Make sure the adapter is loaded
930
+ if ($this->adapter == null) {
931
+ $this->setAdapter($this->config['adapter']);
932
+ }
933
+
934
+ // Send the first request. If redirected, continue.
935
+ do {
936
+ // Clone the URI and add the additional GET parameters to it
937
+ $uri = clone $this->uri;
938
+ if (! empty($this->paramsGet)) {
939
+ $query = $uri->getQuery();
940
+ if (! empty($query)) {
941
+ $query .= '&';
942
+ }
943
+ $query .= http_build_query($this->paramsGet, null, '&');
944
+
945
+ $uri->setQuery($query);
946
+ }
947
+
948
+ $body = $this->_prepareBody();
949
+ $headers = $this->_prepareHeaders();
950
+
951
+ // check that adapter supports streaming before using it
952
+ if(is_resource($body) && !($this->adapter instanceof Microsoft_Http_Client_Adapter_Stream)) {
953
+ /** @see Microsoft_Http_Client_Exception */
954
+ require_once 'Microsoft/Http/Client/Exception.php';
955
+ throw new Microsoft_Http_Client_Exception('Adapter does not support streaming');
956
+ }
957
+
958
+ // Open the connection, send the request and read the response
959
+ $this->adapter->connect($uri->getHost(), $uri->getPort(),
960
+ ($uri->getScheme() == 'https' ? true : false));
961
+
962
+ if($this->config['output_stream']) {
963
+ if($this->adapter instanceof Microsoft_Http_Client_Adapter_Stream) {
964
+ $stream = $this->_openTempStream();
965
+ $this->adapter->setOutputStream($stream);
966
+ } else {
967
+ /** @see Microsoft_Http_Client_Exception */
968
+ require_once 'Microsoft/Http/Client/Exception.php';
969
+ throw new Microsoft_Http_Client_Exception('Adapter does not support streaming');
970
+ }
971
+ }
972
+
973
+ $this->last_request = $this->adapter->write($this->method,
974
+ $uri, $this->config['httpversion'], $headers, $body);
975
+
976
+ $response = $this->adapter->read();
977
+ if (! $response) {
978
+ /** @see Microsoft_Http_Client_Exception */
979
+ require_once 'Microsoft/Http/Client/Exception.php';
980
+ throw new Microsoft_Http_Client_Exception('Unable to read response, or response is empty');
981
+ }
982
+
983
+ if($this->config['output_stream']) {
984
+ rewind($stream);
985
+ // cleanup the adapter
986
+ $this->adapter->setOutputStream(null);
987
+ $response = Microsoft_Http_Response_Stream::fromStream($response, $stream);
988
+ $response->setStreamName($this->_stream_name);
989
+ if(!is_string($this->config['output_stream'])) {
990
+ // we used temp name, will need to clean up
991
+ $response->setCleanup(true);
992
+ }
993
+ } else {
994
+ $response = Microsoft_Http_Response::fromString($response);
995
+ }
996
+
997
+ if ($this->config['storeresponse']) {
998
+ $this->last_response = $response;
999
+ }
1000
+
1001
+ // Load cookies into cookie jar
1002
+ if (isset($this->cookiejar)) {
1003
+ $this->cookiejar->addCookiesFromResponse($response, $uri);
1004
+ }
1005
+
1006
+ // If we got redirected, look for the Location header
1007
+ if ($response->isRedirect() && ($location = $response->getHeader('location'))) {
1008
+
1009
+ // Check whether we send the exact same request again, or drop the parameters
1010
+ // and send a GET request
1011
+ if ($response->getStatus() == 303 ||
1012
+ ((! $this->config['strictredirects']) && ($response->getStatus() == 302 ||
1013
+ $response->getStatus() == 301))) {
1014
+
1015
+ $this->resetParameters();
1016
+ $this->setMethod(self::GET);
1017
+ }
1018
+
1019
+ // If we got a well formed absolute URI
1020
+ if (Microsoft_Uri_Http::check($location)) {
1021
+ $this->setHeaders('host', null);
1022
+ $this->setUri($location);
1023
+
1024
+ } else {
1025
+
1026
+ // Split into path and query and set the query
1027
+ if (strpos($location, '?') !== false) {
1028
+ list($location, $query) = explode('?', $location, 2);
1029
+ } else {
1030
+ $query = '';
1031
+ }
1032
+ $this->uri->setQuery($query);
1033
+
1034
+ // Else, if we got just an absolute path, set it
1035
+ if(strpos($location, '/') === 0) {
1036
+ $this->uri->setPath($location);
1037
+
1038
+ // Else, assume we have a relative path
1039
+ } else {
1040
+ // Get the current path directory, removing any trailing slashes
1041
+ $path = $this->uri->getPath();
1042
+ $path = rtrim(substr($path, 0, strrpos($path, '/')), "/");
1043
+ $this->uri->setPath($path . '/' . $location);
1044
+ }
1045
+ }
1046
+ ++$this->redirectCounter;
1047
+
1048
+ } else {
1049
+ // If we didn't get any location, stop redirecting
1050
+ break;
1051
+ }
1052
+
1053
+ } while ($this->redirectCounter < $this->config['maxredirects']);
1054
+
1055
+ return $response;
1056
+ }
1057
+
1058
+ /**
1059
+ * Prepare the request headers
1060
+ *
1061
+ * @return array
1062
+ */
1063
+ protected function _prepareHeaders()
1064
+ {
1065
+ $headers = array();
1066
+
1067
+ // Set the host header
1068
+ if (! isset($this->headers['host'])) {
1069
+ $host = $this->uri->getHost();
1070
+
1071
+ // If the port is not default, add it
1072
+ if (! (($this->uri->getScheme() == 'http' && $this->uri->getPort() == 80) ||
1073
+ ($this->uri->getScheme() == 'https' && $this->uri->getPort() == 443))) {
1074
+ $host .= ':' . $this->uri->getPort();
1075
+ }
1076
+
1077
+ $headers[] = "Host: {$host}";
1078
+ }
1079
+
1080
+ // Set the connection header
1081
+ if (! isset($this->headers['connection'])) {
1082
+ if (! $this->config['keepalive']) {
1083
+ $headers[] = "Connection: close";
1084
+ }
1085
+ }
1086
+
1087
+ // Set the Accept-encoding header if not set - depending on whether
1088
+ // zlib is available or not.
1089
+ if (! isset($this->headers['accept-encoding'])) {
1090
+ if (function_exists('gzinflate')) {
1091
+ $headers[] = 'Accept-encoding: gzip, deflate';
1092
+ } else {
1093
+ $headers[] = 'Accept-encoding: identity';
1094
+ }
1095
+ }
1096
+
1097
+ // Set the Content-Type header
1098
+ if ($this->method == self::POST &&
1099
+ (! isset($this->headers[strtolower(self::CONTENT_TYPE)]) && isset($this->enctype))) {
1100
+
1101
+ $headers[] = self::CONTENT_TYPE . ': ' . $this->enctype;
1102
+ }
1103
+
1104
+ // Set the user agent header
1105
+ if (! isset($this->headers['user-agent']) && isset($this->config['useragent'])) {
1106
+ $headers[] = "User-Agent: {$this->config['useragent']}";
1107
+ }
1108
+
1109
+ // Set HTTP authentication if needed
1110
+ if (is_array($this->auth)) {
1111
+ $auth = self::encodeAuthHeader($this->auth['user'], $this->auth['password'], $this->auth['type']);
1112
+ $headers[] = "Authorization: {$auth}";
1113
+ }
1114
+
1115
+ // Load cookies from cookie jar
1116
+ if (isset($this->cookiejar)) {
1117
+ $cookstr = $this->cookiejar->getMatchingCookies($this->uri,
1118
+ true, Microsoft_Http_CookieJar::COOKIE_STRING_CONCAT);
1119
+
1120
+ if ($cookstr) {
1121
+ $headers[] = "Cookie: {$cookstr}";
1122
+ }
1123
+ }
1124
+
1125
+ // Add all other user defined headers
1126
+ foreach ($this->headers as $header) {
1127
+ list($name, $value) = $header;
1128
+ if (is_array($value)) {
1129
+ $value = implode(', ', $value);
1130
+ }
1131
+
1132
+ $headers[] = "$name: $value";
1133
+ }
1134
+
1135
+ return $headers;
1136
+ }
1137
+
1138
+ /**
1139
+ * Prepare the request body (for POST and PUT requests)
1140
+ *
1141
+ * @return string
1142
+ * @throws Microsoft_Http_Client_Exception
1143
+ */
1144
+ protected function _prepareBody()
1145
+ {
1146
+ // According to RFC2616, a TRACE request should not have a body.
1147
+ if ($this->method == self::TRACE) {
1148
+ return '';
1149
+ }
1150
+
1151
+ if (isset($this->raw_post_data) && is_resource($this->raw_post_data)) {
1152
+ return $this->raw_post_data;
1153
+ }
1154
+ // If mbstring overloads substr and strlen functions, we have to
1155
+ // override it's internal encoding
1156
+ if (function_exists('mb_internal_encoding') &&
1157
+ ((int) ini_get('mbstring.func_overload')) & 2) {
1158
+
1159
+ $mbIntEnc = mb_internal_encoding();
1160
+ mb_internal_encoding('ASCII');
1161
+ }
1162
+
1163
+ // If we have raw_post_data set, just use it as the body.
1164
+ if (isset($this->raw_post_data)) {
1165
+ $this->setHeaders(self::CONTENT_LENGTH, strlen($this->raw_post_data));
1166
+ if (isset($mbIntEnc)) {
1167
+ mb_internal_encoding($mbIntEnc);
1168
+ }
1169
+
1170
+ return $this->raw_post_data;
1171
+ }
1172
+
1173
+ $body = '';
1174
+
1175
+ // If we have files to upload, force enctype to multipart/form-data
1176
+ if (count ($this->files) > 0) {
1177
+ $this->setEncType(self::ENC_FORMDATA);
1178
+ }
1179
+
1180
+ // If we have POST parameters or files, encode and add them to the body
1181
+ if (count($this->paramsPost) > 0 || count($this->files) > 0) {
1182
+ switch($this->enctype) {
1183
+ case self::ENC_FORMDATA:
1184
+ // Encode body as multipart/form-data
1185
+ $boundary = '---ZENDHTTPCLIENT-' . md5(microtime());
1186
+ $this->setHeaders(self::CONTENT_TYPE, self::ENC_FORMDATA . "; boundary={$boundary}");
1187
+
1188
+ // Get POST parameters and encode them
1189
+ $params = self::_flattenParametersArray($this->paramsPost);
1190
+ foreach ($params as $pp) {
1191
+ $body .= self::encodeFormData($boundary, $pp[0], $pp[1]);
1192
+ }
1193
+
1194
+ // Encode files
1195
+ foreach ($this->files as $file) {
1196
+ $fhead = array(self::CONTENT_TYPE => $file['ctype']);
1197
+ $body .= self::encodeFormData($boundary, $file['formname'], $file['data'], $file['filename'], $fhead);
1198
+ }
1199
+
1200
+ $body .= "--{$boundary}--\r\n";
1201
+ break;
1202
+
1203
+ case self::ENC_URLENCODED:
1204
+ // Encode body as application/x-www-form-urlencoded
1205
+ $this->setHeaders(self::CONTENT_TYPE, self::ENC_URLENCODED);
1206
+ $body = http_build_query($this->paramsPost, '', '&');
1207
+ break;
1208
+
1209
+ default:
1210
+ if (isset($mbIntEnc)) {
1211
+ mb_internal_encoding($mbIntEnc);
1212
+ }
1213
+
1214
+ /** @see Microsoft_Http_Client_Exception */
1215
+ require_once 'Microsoft/Http/Client/Exception.php';
1216
+ throw new Microsoft_Http_Client_Exception("Cannot handle content type '{$this->enctype}' automatically." .
1217
+ " Please use Microsoft_Http_Client::setRawData to send this kind of content.");
1218
+ break;
1219
+ }
1220
+ }
1221
+
1222
+ // Set the Content-Length if we have a body or if request is POST/PUT
1223
+ if ($body || $this->method == self::POST || $this->method == self::PUT) {
1224
+ $this->setHeaders(self::CONTENT_LENGTH, strlen($body));
1225
+ }
1226
+
1227
+ if (isset($mbIntEnc)) {
1228
+ mb_internal_encoding($mbIntEnc);
1229
+ }
1230
+
1231
+ return $body;
1232
+ }
1233
+
1234
+ /**
1235
+ * Helper method that gets a possibly multi-level parameters array (get or
1236
+ * post) and flattens it.
1237
+ *
1238
+ * The method returns an array of (key, value) pairs (because keys are not
1239
+ * necessarily unique. If one of the parameters in as array, it will also
1240
+ * add a [] suffix to the key.
1241
+ *
1242
+ * This method is deprecated since Zend Framework 1.9 in favour of
1243
+ * self::_flattenParametersArray() and will be dropped in 2.0
1244
+ *
1245
+ * @deprecated since 1.9
1246
+ *
1247
+ * @param array $parray The parameters array
1248
+ * @param bool $urlencode Whether to urlencode the name and value
1249
+ * @return array
1250
+ */
1251
+ protected function _getParametersRecursive($parray, $urlencode = false)
1252
+ {
1253
+ // Issue a deprecated notice
1254
+ trigger_error("The " . __METHOD__ . " method is deprecated and will be dropped in 2.0.",
1255
+ E_USER_NOTICE);
1256
+
1257
+ if (! is_array($parray)) {
1258
+ return $parray;
1259
+ }
1260
+ $parameters = array();
1261
+
1262
+ foreach ($parray as $name => $value) {
1263
+ if ($urlencode) {
1264
+ $name = urlencode($name);
1265
+ }
1266
+
1267
+ // If $value is an array, iterate over it
1268
+ if (is_array($value)) {
1269
+ $name .= ($urlencode ? '%5B%5D' : '[]');
1270
+ foreach ($value as $subval) {
1271
+ if ($urlencode) {
1272
+ $subval = urlencode($subval);
1273
+ }
1274
+ $parameters[] = array($name, $subval);
1275
+ }
1276
+ } else {
1277
+ if ($urlencode) {
1278
+ $value = urlencode($value);
1279
+ }
1280
+ $parameters[] = array($name, $value);
1281
+ }
1282
+ }
1283
+
1284
+ return $parameters;
1285
+ }
1286
+
1287
+ /**
1288
+ * Attempt to detect the MIME type of a file using available extensions
1289
+ *
1290
+ * This method will try to detect the MIME type of a file. If the fileinfo
1291
+ * extension is available, it will be used. If not, the mime_magic
1292
+ * extension which is deprected but is still available in many PHP setups
1293
+ * will be tried.
1294
+ *
1295
+ * If neither extension is available, the default application/octet-stream
1296
+ * MIME type will be returned
1297
+ *
1298
+ * @param string $file File path
1299
+ * @return string MIME type
1300
+ */
1301
+ protected function _detectFileMimeType($file)
1302
+ {
1303
+ $type = null;
1304
+
1305
+ // First try with fileinfo functions
1306
+ if (function_exists('finfo_open')) {
1307
+ if (self::$_fileInfoDb === null) {
1308
+ self::$_fileInfoDb = @finfo_open(FILEINFO_MIME);
1309
+ }
1310
+
1311
+ if (self::$_fileInfoDb) {
1312
+ $type = finfo_file(self::$_fileInfoDb, $file);
1313
+ }
1314
+
1315
+ } elseif (function_exists('mime_content_type')) {
1316
+ $type = mime_content_type($file);
1317
+ }
1318
+
1319
+ // Fallback to the default application/octet-stream
1320
+ if (! $type) {
1321
+ $type = 'application/octet-stream';
1322
+ }
1323
+
1324
+ return $type;
1325
+ }
1326
+
1327
+ /**
1328
+ * Encode data to a multipart/form-data part suitable for a POST request.
1329
+ *
1330
+ * @param string $boundary
1331
+ * @param string $name
1332
+ * @param mixed $value
1333
+ * @param string $filename
1334
+ * @param array $headers Associative array of optional headers @example ("Content-Transfer-Encoding" => "binary")
1335
+ * @return string
1336
+ */
1337
+ public static function encodeFormData($boundary, $name, $value, $filename = null, $headers = array()) {
1338
+ $ret = "--{$boundary}\r\n" .
1339
+ 'Content-Disposition: form-data; name="' . $name .'"';
1340
+
1341
+ if ($filename) {
1342
+ $ret .= '; filename="' . $filename . '"';
1343
+ }
1344
+ $ret .= "\r\n";
1345
+
1346
+ foreach ($headers as $hname => $hvalue) {
1347
+ $ret .= "{$hname}: {$hvalue}\r\n";
1348
+ }
1349
+ $ret .= "\r\n";
1350
+
1351
+ $ret .= "{$value}\r\n";
1352
+
1353
+ return $ret;
1354
+ }
1355
+
1356
+ /**
1357
+ * Create a HTTP authentication "Authorization:" header according to the
1358
+ * specified user, password and authentication method.
1359
+ *
1360
+ * @see http://www.faqs.org/rfcs/rfc2617.html
1361
+ * @param string $user
1362
+ * @param string $password
1363
+ * @param string $type
1364
+ * @return string
1365
+ * @throws Microsoft_Http_Client_Exception
1366
+ */
1367
+ public static function encodeAuthHeader($user, $password, $type = self::AUTH_BASIC)
1368
+ {
1369
+ $authHeader = null;
1370
+
1371
+ switch ($type) {
1372
+ case self::AUTH_BASIC:
1373
+ // In basic authentication, the user name cannot contain ":"
1374
+ if (strpos($user, ':') !== false) {
1375
+ /** @see Microsoft_Http_Client_Exception */
1376
+ require_once 'Microsoft/Http/Client/Exception.php';
1377
+ throw new Microsoft_Http_Client_Exception("The user name cannot contain ':' in 'Basic' HTTP authentication");
1378
+ }
1379
+
1380
+ $authHeader = 'Basic ' . base64_encode($user . ':' . $password);
1381
+ break;
1382
+
1383
+ //case self::AUTH_DIGEST:
1384
+ /**
1385
+ * @todo Implement digest authentication
1386
+ */
1387
+ // break;
1388
+
1389
+ default:
1390
+ /** @see Microsoft_Http_Client_Exception */
1391
+ require_once 'Microsoft/Http/Client/Exception.php';
1392
+ throw new Microsoft_Http_Client_Exception("Not a supported HTTP authentication type: '$type'");
1393
+ }
1394
+
1395
+ return $authHeader;
1396
+ }
1397
+
1398
+ /**
1399
+ * Convert an array of parameters into a flat array of (key, value) pairs
1400
+ *
1401
+ * Will flatten a potentially multi-dimentional array of parameters (such
1402
+ * as POST parameters) into a flat array of (key, value) paris. In case
1403
+ * of multi-dimentional arrays, square brackets ([]) will be added to the
1404
+ * key to indicate an array.
1405
+ *
1406
+ * @since 1.9
1407
+ *
1408
+ * @param array $parray
1409
+ * @param string $prefix
1410
+ * @return array
1411
+ */
1412
+ static protected function _flattenParametersArray($parray, $prefix = null)
1413
+ {
1414
+ if (! is_array($parray)) {
1415
+ return $parray;
1416
+ }
1417
+
1418
+ $parameters = array();
1419
+
1420
+ foreach($parray as $name => $value) {
1421
+
1422
+ // Calculate array key
1423
+ if ($prefix) {
1424
+ if (is_int($name)) {
1425
+ $key = $prefix . '[]';
1426
+ } else {
1427
+ $key = $prefix . "[$name]";
1428
+ }
1429
+ } else {
1430
+ $key = $name;
1431
+ }
1432
+
1433
+ if (is_array($value)) {
1434
+ $parameters = array_merge($parameters, self::_flattenParametersArray($value, $key));
1435
+
1436
+ } else {
1437
+ $parameters[] = array($key, $value);
1438
+ }
1439
+ }
1440
+
1441
+ return $parameters;
1442
+ }
1443
+
1444
+ }
app/libs/Microsoft/Http/Client/Adapter/Curl.php ADDED
@@ -0,0 +1,498 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Zend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category Microsoft
17
+ * @package Microsoft_Http
18
+ * @subpackage Client_Adapter
19
+ * @version $Id: Curl.php 19238 2009-11-25 17:13:38Z bate $
20
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
21
+ * @license http://framework.zend.com/license/new-bsd New BSD License
22
+ */
23
+
24
+ /**
25
+ * @see Microsoft_Uri_Http
26
+ */
27
+ require_once 'Microsoft/Uri/Http.php';
28
+
29
+ /**
30
+ * @see Microsoft_Http_Client_Adapter_Interface
31
+ */
32
+ require_once 'Microsoft/Http/Client/Adapter/Interface.php';
33
+ /**
34
+ * @see Microsoft_Http_Client_Adapter_Stream
35
+ */
36
+ require_once 'Microsoft/Http/Client/Adapter/Stream.php';
37
+
38
+ /**
39
+ * An adapter class for Microsoft_Http_Client based on the curl extension.
40
+ * Curl requires libcurl. See for full requirements the PHP manual: http://php.net/curl
41
+ *
42
+ * @category Microsoft
43
+ * @package Microsoft_Http
44
+ * @subpackage Client_Adapter
45
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
46
+ * @license http://framework.zend.com/license/new-bsd New BSD License
47
+ */
48
+ class Microsoft_Http_Client_Adapter_Curl implements Microsoft_Http_Client_Adapter_Interface, Microsoft_Http_Client_Adapter_Stream
49
+ {
50
+ /**
51
+ * Parameters array
52
+ *
53
+ * @var array
54
+ */
55
+ protected $_config = array();
56
+
57
+ /**
58
+ * What host/port are we connected to?
59
+ *
60
+ * @var array
61
+ */
62
+ protected $_connected_to = array(null, null);
63
+
64
+ /**
65
+ * The curl session handle
66
+ *
67
+ * @var resource|null
68
+ */
69
+ protected $_curl = null;
70
+
71
+ /**
72
+ * List of cURL options that should never be overwritten
73
+ *
74
+ * @var array
75
+ */
76
+ protected $_invalidOverwritableCurlOptions = array(
77
+ CURLOPT_HTTPGET,
78
+ CURLOPT_POST,
79
+ CURLOPT_PUT,
80
+ CURLOPT_CUSTOMREQUEST,
81
+ CURLOPT_HEADER,
82
+ CURLOPT_RETURNTRANSFER,
83
+ CURLOPT_HTTPHEADER,
84
+ CURLOPT_POSTFIELDS,
85
+ CURLOPT_INFILE,
86
+ CURLOPT_INFILESIZE,
87
+ CURLOPT_PORT,
88
+ CURLOPT_MAXREDIRS,
89
+ CURLOPT_CONNECTTIMEOUT,
90
+ CURL_HTTP_VERSION_1_1,
91
+ CURL_HTTP_VERSION_1_0,
92
+ );
93
+
94
+ /**
95
+ * Response gotten from server
96
+ *
97
+ * @var string
98
+ */
99
+ protected $_response = null;
100
+
101
+ /**
102
+ * Stream for storing output
103
+ *
104
+ * @var resource
105
+ */
106
+ protected $out_stream;
107
+
108
+ /**
109
+ * Adapter constructor
110
+ *
111
+ * Config is set using setConfig()
112
+ *
113
+ * @return void
114
+ * @throws Microsoft_Http_Client_Adapter_Exception
115
+ */
116
+ public function __construct()
117
+ {
118
+ if (!extension_loaded('curl')) {
119
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
120
+ throw new Microsoft_Http_Client_Adapter_Exception('cURL extension has to be loaded to use this Microsoft_Http_Client adapter.');
121
+ }
122
+ }
123
+
124
+ /**
125
+ * Set the configuration array for the adapter
126
+ *
127
+ * @throws Microsoft_Http_Client_Adapter_Exception
128
+ * @param array $config
129
+ * @return Microsoft_Http_Client_Adapter_Curl
130
+ */
131
+ public function setConfig($config = array())
132
+ {
133
+ if (! is_array($config)) {
134
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
135
+ throw new Microsoft_Http_Client_Adapter_Exception(
136
+ 'Array expected, got ' . gettype($config)
137
+ );
138
+ }
139
+
140
+ if(isset($config['proxy_user']) && isset($config['proxy_pass'])) {
141
+ $this->setCurlOption(CURLOPT_PROXYUSERPWD, $config['proxy_user'].":".$config['proxy_pass']);
142
+ unset($config['proxy_user'], $config['proxy_pass']);
143
+ }
144
+
145
+ foreach ($config as $k => $v) {
146
+ $option = strtolower($k);
147
+ switch($option) {
148
+ case 'proxy_host':
149
+ $this->setCurlOption(CURLOPT_PROXY, $v);
150
+ break;
151
+ case 'proxy_port':
152
+ $this->setCurlOption(CURLOPT_PROXYPORT, $v);
153
+ break;
154
+ default:
155
+ $this->_config[$option] = $v;
156
+ break;
157
+ }
158
+ }
159
+
160
+ return $this;
161
+ }
162
+
163
+ /**
164
+ * Retrieve the array of all configuration options
165
+ *
166
+ * @return array
167
+ */
168
+ public function getConfig()
169
+ {
170
+ return $this->_config;
171
+ }
172
+
173
+ /**
174
+ * Direct setter for cURL adapter related options.
175
+ *
176
+ * @param string|int $option
177
+ * @param mixed $value
178
+ * @return Microsoft_Http_Adapter_Curl
179
+ */
180
+ public function setCurlOption($option, $value)
181
+ {
182
+ if (!isset($this->_config['curloptions'])) {
183
+ $this->_config['curloptions'] = array();
184
+ }
185
+ $this->_config['curloptions'][$option] = $value;
186
+ return $this;
187
+ }
188
+
189
+ /**
190
+ * Initialize curl
191
+ *
192
+ * @param string $host
193
+ * @param int $port
194
+ * @param boolean $secure
195
+ * @return void
196
+ * @throws Microsoft_Http_Client_Adapter_Exception if unable to connect
197
+ */
198
+ public function connect($host, $port = 80, $secure = false)
199
+ {
200
+ // If we're already connected, disconnect first
201
+ if ($this->_curl) {
202
+ $this->close();
203
+ }
204
+
205
+ // If we are connected to a different server or port, disconnect first
206
+ if ($this->_curl
207
+ && is_array($this->_connected_to)
208
+ && ($this->_connected_to[0] != $host
209
+ || $this->_connected_to[1] != $port)
210
+ ) {
211
+ $this->close();
212
+ }
213
+
214
+ // Do the actual connection
215
+ $this->_curl = curl_init();
216
+ if ($port != 80) {
217
+ curl_setopt($this->_curl, CURLOPT_PORT, intval($port));
218
+ }
219
+
220
+ // Set timeout
221
+ curl_setopt($this->_curl, CURLOPT_CONNECTTIMEOUT, $this->_config['timeout']);
222
+
223
+ // Set Max redirects
224
+ curl_setopt($this->_curl, CURLOPT_MAXREDIRS, $this->_config['maxredirects']);
225
+
226
+ if (!$this->_curl) {
227
+ $this->close();
228
+
229
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
230
+ throw new Microsoft_Http_Client_Adapter_Exception('Unable to Connect to ' . $host . ':' . $port);
231
+ }
232
+
233
+ if ($secure !== false) {
234
+ // Behave the same like Microsoft_Http_Adapter_Socket on SSL options.
235
+ if (isset($this->_config['sslcert'])) {
236
+ curl_setopt($this->_curl, CURLOPT_SSLCERT, $this->_config['sslcert']);
237
+ }
238
+ if (isset($this->_config['sslpassphrase'])) {
239
+ curl_setopt($this->_curl, CURLOPT_SSLCERTPASSWD, $this->_config['sslpassphrase']);
240
+ }
241
+ }
242
+
243
+ // Update connected_to
244
+ $this->_connected_to = array($host, $port);
245
+ }
246
+
247
+ /**
248
+ * Send request to the remote server
249
+ *
250
+ * @param string $method
251
+ * @param Microsoft_Uri_Http $uri
252
+ * @param float $http_ver
253
+ * @param array $headers
254
+ * @param string $body
255
+ * @return string $request
256
+ * @throws Microsoft_Http_Client_Adapter_Exception If connection fails, connected to wrong host, no PUT file defined, unsupported method, or unsupported cURL option
257
+ */
258
+ public function write($method, $uri, $httpVersion = 1.1, $headers = array(), $body = '')
259
+ {
260
+ // Make sure we're properly connected
261
+ if (!$this->_curl) {
262
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
263
+ throw new Microsoft_Http_Client_Adapter_Exception("Trying to write but we are not connected");
264
+ }
265
+
266
+ if ($this->_connected_to[0] != $uri->getHost() || $this->_connected_to[1] != $uri->getPort()) {
267
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
268
+ throw new Microsoft_Http_Client_Adapter_Exception("Trying to write but we are connected to the wrong host");
269
+ }
270
+
271
+ // set URL
272
+ curl_setopt($this->_curl, CURLOPT_URL, $uri->__toString());
273
+
274
+ // ensure correct curl call
275
+ $curlValue = true;
276
+ switch ($method) {
277
+ case Microsoft_Http_Client::GET:
278
+ $curlMethod = CURLOPT_HTTPGET;
279
+ break;
280
+
281
+ case Microsoft_Http_Client::POST:
282
+ $curlMethod = CURLOPT_POST;
283
+ break;
284
+
285
+ case Microsoft_Http_Client::PUT:
286
+ // There are two different types of PUT request, either a Raw Data string has been set
287
+ // or CURLOPT_INFILE and CURLOPT_INFILESIZE are used.
288
+ if(is_resource($body)) {
289
+ $this->_config['curloptions'][CURLOPT_INFILE] = $body;
290
+ }
291
+ if (isset($this->_config['curloptions'][CURLOPT_INFILE])) {
292
+ // Now we will probably already have Content-Length set, so that we have to delete it
293
+ // from $headers at this point:
294
+ foreach ($headers AS $k => $header) {
295
+ if (preg_match('/Content-Length:\s*(\d+)/i', $header, $m)) {
296
+ if(is_resource($body)) {
297
+ $this->_config['curloptions'][CURLOPT_INFILESIZE] = (int)$m[1];
298
+ }
299
+ unset($headers[$k]);
300
+ }
301
+ }
302
+
303
+ if (!isset($this->_config['curloptions'][CURLOPT_INFILESIZE])) {
304
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
305
+ throw new Microsoft_Http_Client_Adapter_Exception("Cannot set a file-handle for cURL option CURLOPT_INFILE without also setting its size in CURLOPT_INFILESIZE.");
306
+ }
307
+
308
+ if(is_resource($body)) {
309
+ $body = '';
310
+ }
311
+
312
+ $curlMethod = CURLOPT_PUT;
313
+ } else {
314
+ $curlMethod = CURLOPT_CUSTOMREQUEST;
315
+ $curlValue = "PUT";
316
+ }
317
+ break;
318
+
319
+ case Microsoft_Http_Client::DELETE:
320
+ $curlMethod = CURLOPT_CUSTOMREQUEST;
321
+ $curlValue = "DELETE";
322
+ break;
323
+
324
+ case Microsoft_Http_Client::OPTIONS:
325
+ $curlMethod = CURLOPT_CUSTOMREQUEST;
326
+ $curlValue = "OPTIONS";
327
+ break;
328
+
329
+ case Microsoft_Http_Client::TRACE:
330
+ $curlMethod = CURLOPT_CUSTOMREQUEST;
331
+ $curlValue = "TRACE";
332
+ break;
333
+
334
+ default:
335
+ // For now, through an exception for unsupported request methods
336
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
337
+ throw new Microsoft_Http_Client_Adapter_Exception("Method currently not supported");
338
+ }
339
+
340
+ if(is_resource($body) && $curlMethod != CURLOPT_PUT) {
341
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
342
+ throw new Microsoft_Http_Client_Adapter_Exception("Streaming requests are allowed only with PUT");
343
+ }
344
+
345
+ // get http version to use
346
+ $curlHttp = ($httpVersion == 1.1) ? CURL_HTTP_VERSION_1_1 : CURL_HTTP_VERSION_1_0;
347
+
348
+ // mark as HTTP request and set HTTP method
349
+ curl_setopt($this->_curl, $curlHttp, true);
350
+ curl_setopt($this->_curl, $curlMethod, $curlValue);
351
+
352
+ if($this->out_stream) {
353
+ // headers will be read into the response
354
+ curl_setopt($this->_curl, CURLOPT_HEADER, false);
355
+ curl_setopt($this->_curl, CURLOPT_HEADERFUNCTION, array($this, "readHeader"));
356
+ // and data will be written into the file
357
+ curl_setopt($this->_curl, CURLOPT_FILE, $this->out_stream);
358
+ } else {
359
+ // ensure headers are also returned
360
+ curl_setopt($this->_curl, CURLOPT_HEADER, true);
361
+
362
+ // ensure actual response is returned
363
+ curl_setopt($this->_curl, CURLOPT_RETURNTRANSFER, true);
364
+ }
365
+
366
+ // set additional headers
367
+ $headers['Accept'] = '';
368
+ curl_setopt($this->_curl, CURLOPT_HTTPHEADER, $headers);
369
+
370
+ /**
371
+ * Make sure POSTFIELDS is set after $curlMethod is set:
372
+ * @link http://de2.php.net/manual/en/function.curl-setopt.php#81161
373
+ */
374
+ if ($method == Microsoft_Http_Client::POST) {
375
+ curl_setopt($this->_curl, CURLOPT_POSTFIELDS, $body);
376
+ } elseif ($curlMethod == CURLOPT_PUT) {
377
+ // this covers a PUT by file-handle:
378
+ // Make the setting of this options explicit (rather than setting it through the loop following a bit lower)
379
+ // to group common functionality together.
380
+ curl_setopt($this->_curl, CURLOPT_INFILE, $this->_config['curloptions'][CURLOPT_INFILE]);
381
+ curl_setopt($this->_curl, CURLOPT_INFILESIZE, $this->_config['curloptions'][CURLOPT_INFILESIZE]);
382
+ unset($this->_config['curloptions'][CURLOPT_INFILE]);
383
+ unset($this->_config['curloptions'][CURLOPT_INFILESIZE]);
384
+ } elseif ($method == Microsoft_Http_Client::PUT) {
385
+ // This is a PUT by a setRawData string, not by file-handle
386
+ curl_setopt($this->_curl, CURLOPT_POSTFIELDS, $body);
387
+ }
388
+
389
+ // set additional curl options
390
+ if (isset($this->_config['curloptions'])) {
391
+ foreach ((array)$this->_config['curloptions'] as $k => $v) {
392
+ if (!in_array($k, $this->_invalidOverwritableCurlOptions)) {
393
+ if (curl_setopt($this->_curl, $k, $v) == false) {
394
+ require_once 'Microsoft/Http/Client/Exception.php';
395
+ throw new Microsoft_Http_Client_Exception(sprintf("Unknown or erroreous cURL option '%s' set", $k));
396
+ }
397
+ }
398
+ }
399
+ }
400
+
401
+ // send the request
402
+ $response = curl_exec($this->_curl);
403
+
404
+ // if we used streaming, headers are already there
405
+ if(!is_resource($this->out_stream)) {
406
+ $this->_response = $response;
407
+ }
408
+
409
+ $request = curl_getinfo($this->_curl, CURLINFO_HEADER_OUT);
410
+ $request .= $body;
411
+
412
+ if (empty($this->_response)) {
413
+ require_once 'Microsoft/Http/Client/Exception.php';
414
+ throw new Microsoft_Http_Client_Exception("Error in cURL request: " . curl_error($this->_curl));
415
+ }
416
+
417
+ // cURL automatically decodes chunked-messages, this means we have to disallow the Microsoft_Http_Response to do it again
418
+ if (stripos($this->_response, "Transfer-Encoding: chunked\r\n")) {
419
+ $this->_response = str_ireplace("Transfer-Encoding: chunked\r\n", '', $this->_response);
420
+ }
421
+
422
+ // Eliminate multiple HTTP responses.
423
+ do {
424
+ $parts = preg_split('|(?:\r?\n){2}|m', $this->_response, 2);
425
+ $again = false;
426
+
427
+ if (isset($parts[1]) && preg_match("|^HTTP/1\.[01](.*?)\r\n|mi", $parts[1])) {
428
+ $this->_response = $parts[1];
429
+ $again = true;
430
+ }
431
+ } while ($again);
432
+
433
+ // cURL automatically handles Proxy rewrites, remove the "HTTP/1.0 200 Connection established" string:
434
+ if (stripos($this->_response, "HTTP/1.0 200 Connection established\r\n\r\n") !== false) {
435
+ $this->_response = str_ireplace("HTTP/1.0 200 Connection established\r\n\r\n", '', $this->_response);
436
+ }
437
+
438
+ return $request;
439
+ }
440
+
441
+ /**
442
+ * Return read response from server
443
+ *
444
+ * @return string
445
+ */
446
+ public function read()
447
+ {
448
+ return $this->_response;
449
+ }
450
+
451
+ /**
452
+ * Close the connection to the server
453
+ *
454
+ */
455
+ public function close()
456
+ {
457
+ if(is_resource($this->_curl)) {
458
+ curl_close($this->_curl);
459
+ }
460
+ $this->_curl = null;
461
+ $this->_connected_to = array(null, null);
462
+ }
463
+
464
+ /**
465
+ * Get cUrl Handle
466
+ *
467
+ * @return resource
468
+ */
469
+ public function getHandle()
470
+ {
471
+ return $this->_curl;
472
+ }
473
+
474
+ /**
475
+ * Set output stream for the response
476
+ *
477
+ * @param resource $stream
478
+ * @return Microsoft_Http_Client_Adapter_Socket
479
+ */
480
+ public function setOutputStream($stream)
481
+ {
482
+ $this->out_stream = $stream;
483
+ return $this;
484
+ }
485
+
486
+ /**
487
+ * Header reader function for CURL
488
+ *
489
+ * @param resource $curl
490
+ * @param string $header
491
+ * @return int
492
+ */
493
+ public function readHeader($curl, $header)
494
+ {
495
+ $this->_response .= $header;
496
+ return strlen($header);
497
+ }
498
+ }
app/libs/Microsoft/Http/Client/Adapter/Exception.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework
4
+ *
5
+ * LICENSE
6
+ *
7
+ * This source file is subject to the new BSD license that is bundled
8
+ * with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://framework.zend.com/license/new-bsd
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@zend.com so we can send you a copy immediately.
14
+ *
15
+ * @category Microsoft
16
+ * @package Microsoft_Http
17
+ * @subpackage Client_Adapter_Exception
18
+ * @version $Id: Exception.php 17026 2009-07-24 09:09:19Z shahar $
19
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
20
+ * @license http://framework.zend.com/license/new-bsd New BSD License
21
+ */
22
+
23
+ /**
24
+ * @see Microsoft_Http_Client_Exception
25
+ */
26
+ require_once 'Microsoft/Http/Client/Exception.php';
27
+
28
+ /**
29
+ * @category Microsoft
30
+ * @package Microsoft_Http
31
+ * @subpackage Client_Adapter
32
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
33
+ * @license http://framework.zend.com/license/new-bsd New BSD License
34
+ */
35
+ class Microsoft_Http_Client_Adapter_Exception extends Microsoft_Http_Client_Exception
36
+ {
37
+ const READ_TIMEOUT = 1000;
38
+ }
app/libs/Microsoft/Http/Client/Adapter/Interface.php ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Zend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category Microsoft
17
+ * @package Microsoft_Http
18
+ * @subpackage Client_Adapter
19
+ * @version $Id: Interface.php 16214 2009-06-21 19:34:03Z thomas $
20
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
21
+ * @license http://framework.zend.com/license/new-bsd New BSD License
22
+ */
23
+
24
+ /**
25
+ * An interface description for Microsoft_Http_Client_Adapter classes.
26
+ *
27
+ * These classes are used as connectors for Microsoft_Http_Client, performing the
28
+ * tasks of connecting, writing, reading and closing connection to the server.
29
+ *
30
+ * @category Microsoft
31
+ * @package Microsoft_Http
32
+ * @subpackage Client_Adapter
33
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ interface Microsoft_Http_Client_Adapter_Interface
37
+ {
38
+ /**
39
+ * Set the configuration array for the adapter
40
+ *
41
+ * @param array $config
42
+ */
43
+ public function setConfig($config = array());
44
+
45
+ /**
46
+ * Connect to the remote server
47
+ *
48
+ * @param string $host
49
+ * @param int $port
50
+ * @param boolean $secure
51
+ */
52
+ public function connect($host, $port = 80, $secure = false);
53
+
54
+ /**
55
+ * Send request to the remote server
56
+ *
57
+ * @param string $method
58
+ * @param Microsoft_Uri_Http $url
59
+ * @param string $http_ver
60
+ * @param array $headers
61
+ * @param string $body
62
+ * @return string Request as text
63
+ */
64
+ public function write($method, $url, $http_ver = '1.1', $headers = array(), $body = '');
65
+
66
+ /**
67
+ * Read response from server
68
+ *
69
+ * @return string
70
+ */
71
+ public function read();
72
+
73
+ /**
74
+ * Close the connection to the server
75
+ *
76
+ */
77
+ public function close();
78
+ }
app/libs/Microsoft/Http/Client/Adapter/Proxy.php ADDED
@@ -0,0 +1,267 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Zend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category Microsoft
17
+ * @package Microsoft_Http
18
+ * @subpackage Client_Adapter
19
+ * @version $Id: Proxy.php 17059 2009-07-25 11:24:49Z shahar $
20
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
21
+ * @license http://framework.zend.com/license/new-bsd New BSD License
22
+ */
23
+
24
+ /**
25
+ * @see Microsoft_Uri_Http
26
+ */
27
+ require_once 'Microsoft/Uri/Http.php';
28
+ /**
29
+ * @see Microsoft_Http_Client
30
+ */
31
+ require_once 'Microsoft/Http/Client.php';
32
+ /**
33
+ * @see Microsoft_Http_Client_Adapter_Socket
34
+ */
35
+ require_once 'Microsoft/Http/Client/Adapter/Socket.php';
36
+
37
+ /**
38
+ * HTTP Proxy-supporting Microsoft_Http_Client adapter class, based on the default
39
+ * socket based adapter.
40
+ *
41
+ * Should be used if proxy HTTP access is required. If no proxy is set, will
42
+ * fall back to Microsoft_Http_Client_Adapter_Socket behavior. Just like the
43
+ * default Socket adapter, this adapter does not require any special extensions
44
+ * installed.
45
+ *
46
+ * @category Microsoft
47
+ * @package Microsoft_Http
48
+ * @subpackage Client_Adapter
49
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
50
+ * @license http://framework.zend.com/license/new-bsd New BSD License
51
+ */
52
+ class Microsoft_Http_Client_Adapter_Proxy extends Microsoft_Http_Client_Adapter_Socket
53
+ {
54
+ /**
55
+ * Parameters array
56
+ *
57
+ * @var array
58
+ */
59
+ protected $config = array(
60
+ 'ssltransport' => 'ssl',
61
+ 'sslcert' => null,
62
+ 'sslpassphrase' => null,
63
+ 'proxy_host' => '',
64
+ 'proxy_port' => 8080,
65
+ 'proxy_user' => '',
66
+ 'proxy_pass' => '',
67
+ 'proxy_auth' => Microsoft_Http_Client::AUTH_BASIC,
68
+ 'persistent' => false
69
+ );
70
+
71
+ /**
72
+ * Whether HTTPS CONNECT was already negotiated with the proxy or not
73
+ *
74
+ * @var boolean
75
+ */
76
+ protected $negotiated = false;
77
+
78
+ /**
79
+ * Connect to the remote server
80
+ *
81
+ * Will try to connect to the proxy server. If no proxy was set, will
82
+ * fall back to the target server (behave like regular Socket adapter)
83
+ *
84
+ * @param string $host
85
+ * @param int $port
86
+ * @param boolean $secure
87
+ */
88
+ public function connect($host, $port = 80, $secure = false)
89
+ {
90
+ // If no proxy is set, fall back to Socket adapter
91
+ if (! $this->config['proxy_host']) {
92
+ return parent::connect($host, $port, $secure);
93
+ }
94
+
95
+ // Connect (a non-secure connection) to the proxy server
96
+ return parent::connect(
97
+ $this->config['proxy_host'],
98
+ $this->config['proxy_port'],
99
+ false
100
+ );
101
+ }
102
+
103
+ /**
104
+ * Send request to the proxy server
105
+ *
106
+ * @param string $method
107
+ * @param Microsoft_Uri_Http $uri
108
+ * @param string $http_ver
109
+ * @param array $headers
110
+ * @param string $body
111
+ * @return string Request as string
112
+ */
113
+ public function write($method, $uri, $http_ver = '1.1', $headers = array(), $body = '')
114
+ {
115
+ // If no proxy is set, fall back to default Socket adapter
116
+ if (! $this->config['proxy_host']) return parent::write($method, $uri, $http_ver, $headers, $body);
117
+
118
+ // Make sure we're properly connected
119
+ if (! $this->socket) {
120
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
121
+ throw new Microsoft_Http_Client_Adapter_Exception("Trying to write but we are not connected");
122
+ }
123
+
124
+ $host = $this->config['proxy_host'];
125
+ $port = $this->config['proxy_port'];
126
+
127
+ if ($this->connected_to[0] != "tcp://$host" || $this->connected_to[1] != $port) {
128
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
129
+ throw new Microsoft_Http_Client_Adapter_Exception("Trying to write but we are connected to the wrong proxy server");
130
+ }
131
+
132
+ // Add Proxy-Authorization header
133
+ if ($this->config['proxy_user'] && ! isset($headers['proxy-authorization'])) {
134
+ $headers['proxy-authorization'] = Microsoft_Http_Client::encodeAuthHeader(
135
+ $this->config['proxy_user'], $this->config['proxy_pass'], $this->config['proxy_auth']
136
+ );
137
+ }
138
+
139
+ // if we are proxying HTTPS, preform CONNECT handshake with the proxy
140
+ if ($uri->getScheme() == 'https' && (! $this->negotiated)) {
141
+ $this->connectHandshake($uri->getHost(), $uri->getPort(), $http_ver, $headers);
142
+ $this->negotiated = true;
143
+ }
144
+
145
+ // Save request method for later
146
+ $this->method = $method;
147
+
148
+ // Build request headers
149
+ if ($this->negotiated) {
150
+ $path = $uri->getPath();
151
+ if ($uri->getQuery()) {
152
+ $path .= '?' . $uri->getQuery();
153
+ }
154
+ $request = "$method $path HTTP/$http_ver\r\n";
155
+ } else {
156
+ $request = "$method $uri HTTP/$http_ver\r\n";
157
+ }
158
+
159
+ // Add all headers to the request string
160
+ foreach ($headers as $k => $v) {
161
+ if (is_string($k)) $v = "$k: $v";
162
+ $request .= "$v\r\n";
163
+ }
164
+
165
+ // Add the request body
166
+ $request .= "\r\n" . $body;
167
+
168
+ // Send the request
169
+ if (! @fwrite($this->socket, $request)) {
170
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
171
+ throw new Microsoft_Http_Client_Adapter_Exception("Error writing request to proxy server");
172
+ }
173
+
174
+ return $request;
175
+ }
176
+
177
+ /**
178
+ * Preform handshaking with HTTPS proxy using CONNECT method
179
+ *
180
+ * @param string $host
181
+ * @param integer $port
182
+ * @param string $http_ver
183
+ * @param array $headers
184
+ */
185
+ protected function connectHandshake($host, $port = 443, $http_ver = '1.1', array &$headers = array())
186
+ {
187
+ $request = "CONNECT $host:$port HTTP/$http_ver\r\n" .
188
+ "Host: " . $this->config['proxy_host'] . "\r\n";
189
+
190
+ // Add the user-agent header
191
+ if (isset($this->config['useragent'])) {
192
+ $request .= "User-agent: " . $this->config['useragent'] . "\r\n";
193
+ }
194
+
195
+ // If the proxy-authorization header is set, send it to proxy but remove
196
+ // it from headers sent to target host
197
+ if (isset($headers['proxy-authorization'])) {
198
+ $request .= "Proxy-authorization: " . $headers['proxy-authorization'] . "\r\n";
199
+ unset($headers['proxy-authorization']);
200
+ }
201
+
202
+ $request .= "\r\n";
203
+
204
+ // Send the request
205
+ if (! @fwrite($this->socket, $request)) {
206
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
207
+ throw new Microsoft_Http_Client_Adapter_Exception("Error writing request to proxy server");
208
+ }
209
+
210
+ // Read response headers only
211
+ $response = '';
212
+ $gotStatus = false;
213
+ while ($line = @fgets($this->socket)) {
214
+ $gotStatus = $gotStatus || (strpos($line, 'HTTP') !== false);
215
+ if ($gotStatus) {
216
+ $response .= $line;
217
+ if (!chop($line)) break;
218
+ }
219
+ }
220
+
221
+ // Check that the response from the proxy is 200
222
+ if (Microsoft_Http_Response::extractCode($response) != 200) {
223
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
224
+ throw new Microsoft_Http_Client_Adapter_Exception("Unable to connect to HTTPS proxy. Server response: " . $response);
225
+ }
226
+
227
+ // If all is good, switch socket to secure mode. We have to fall back
228
+ // through the different modes
229
+ $modes = array(
230
+ STREAM_CRYPTO_METHOD_TLS_CLIENT,
231
+ STREAM_CRYPTO_METHOD_SSLv3_CLIENT,
232
+ STREAM_CRYPTO_METHOD_SSLv23_CLIENT,
233
+ STREAM_CRYPTO_METHOD_SSLv2_CLIENT
234
+ );
235
+
236
+ $success = false;
237
+ foreach($modes as $mode) {
238
+ $success = stream_socket_enable_crypto($this->socket, true, $mode);
239
+ if ($success) break;
240
+ }
241
+
242
+ if (! $success) {
243
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
244
+ throw new Microsoft_Http_Client_Adapter_Exception("Unable to connect to" .
245
+ " HTTPS server through proxy: could not negotiate secure connection.");
246
+ }
247
+ }
248
+
249
+ /**
250
+ * Close the connection to the server
251
+ *
252
+ */
253
+ public function close()
254
+ {
255
+ parent::close();
256
+ $this->negotiated = false;
257
+ }
258
+
259
+ /**
260
+ * Destructor: make sure the socket is disconnected
261
+ *
262
+ */
263
+ public function __destruct()
264
+ {
265
+ if ($this->socket) $this->close();
266
+ }
267
+ }
app/libs/Microsoft/Http/Client/Adapter/Socket.php ADDED
@@ -0,0 +1,531 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Zend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category Microsoft
17
+ * @package Microsoft_Http
18
+ * @subpackage Client_Adapter
19
+ * @version $Id: Socket.php 19219 2009-11-24 22:25:36Z stas $
20
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
21
+ * @license http://framework.zend.com/license/new-bsd New BSD License
22
+ */
23
+
24
+ /**
25
+ * @see Microsoft_Uri_Http
26
+ */
27
+ require_once 'Microsoft/Uri/Http.php';
28
+ /**
29
+ * @see Microsoft_Http_Client_Adapter_Interface
30
+ */
31
+ require_once 'Microsoft/Http/Client/Adapter/Interface.php';
32
+ /**
33
+ * @see Microsoft_Http_Client_Adapter_Stream
34
+ */
35
+ require_once 'Microsoft/Http/Client/Adapter/Stream.php';
36
+
37
+ /**
38
+ * A sockets based (stream_socket_client) adapter class for Microsoft_Http_Client. Can be used
39
+ * on almost every PHP environment, and does not require any special extensions.
40
+ *
41
+ * @category Microsoft
42
+ * @package Microsoft_Http
43
+ * @subpackage Client_Adapter
44
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
45
+ * @license http://framework.zend.com/license/new-bsd New BSD License
46
+ */
47
+ class Microsoft_Http_Client_Adapter_Socket implements Microsoft_Http_Client_Adapter_Interface, Microsoft_Http_Client_Adapter_Stream
48
+ {
49
+ /**
50
+ * The socket for server connection
51
+ *
52
+ * @var resource|null
53
+ */
54
+ protected $socket = null;
55
+
56
+ /**
57
+ * What host/port are we connected to?
58
+ *
59
+ * @var array
60
+ */
61
+ protected $connected_to = array(null, null);
62
+
63
+ /**
64
+ * Stream for storing output
65
+ *
66
+ * @var resource
67
+ */
68
+ protected $out_stream = null;
69
+
70
+ /**
71
+ * Parameters array
72
+ *
73
+ * @var array
74
+ */
75
+ protected $config = array(
76
+ 'persistent' => false,
77
+ 'ssltransport' => 'ssl',
78
+ 'sslcert' => null,
79
+ 'sslpassphrase' => null
80
+ );
81
+
82
+ /**
83
+ * Request method - will be set by write() and might be used by read()
84
+ *
85
+ * @var string
86
+ */
87
+ protected $method = null;
88
+
89
+ /**
90
+ * Stream context
91
+ *
92
+ * @var resource
93
+ */
94
+ protected $_context = null;
95
+
96
+ /**
97
+ * Adapter constructor, currently empty. Config is set using setConfig()
98
+ *
99
+ */
100
+ public function __construct()
101
+ {
102
+ }
103
+
104
+ /**
105
+ * Set the configuration array for the adapter
106
+ *
107
+ * @param array $config
108
+ */
109
+ public function setConfig($config = array())
110
+ {
111
+ if (! is_array($config)) {
112
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
113
+ throw new Microsoft_Http_Client_Adapter_Exception(
114
+ 'Array expected, got ' . gettype($config)
115
+ );
116
+ }
117
+
118
+ foreach ($config as $k => $v) {
119
+ $this->config[strtolower($k)] = $v;
120
+ }
121
+ }
122
+
123
+ /**
124
+ * Retrieve the array of all configuration options
125
+ *
126
+ * @return array
127
+ */
128
+ public function getConfig()
129
+ {
130
+ return $this->config;
131
+ }
132
+
133
+ /**
134
+ * Set the stream context for the TCP connection to the server
135
+ *
136
+ * Can accept either a pre-existing stream context resource, or an array
137
+ * of stream options, similar to the options array passed to the
138
+ * stream_context_create() PHP function. In such case a new stream context
139
+ * will be created using the passed options.
140
+ *
141
+ * @since Zend Framework 1.9
142
+ *
143
+ * @param mixed $context Stream context or array of context options
144
+ * @return Microsoft_Http_Client_Adapter_Socket
145
+ */
146
+ public function setStreamContext($context)
147
+ {
148
+ if (is_resource($context) && get_resource_type($context) == 'stream-context') {
149
+ $this->_context = $context;
150
+
151
+ } elseif (is_array($context)) {
152
+ $this->_context = stream_context_create($context);
153
+
154
+ } else {
155
+ // Invalid parameter
156
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
157
+ throw new Microsoft_Http_Client_Adapter_Exception(
158
+ "Expecting either a stream context resource or array, got " . gettype($context)
159
+ );
160
+ }
161
+
162
+ return $this;
163
+ }
164
+
165
+ /**
166
+ * Get the stream context for the TCP connection to the server.
167
+ *
168
+ * If no stream context is set, will create a default one.
169
+ *
170
+ * @return resource
171
+ */
172
+ public function getStreamContext()
173
+ {
174
+ if (! $this->_context) {
175
+ $this->_context = stream_context_create();
176
+ }
177
+
178
+ return $this->_context;
179
+ }
180
+
181
+ /**
182
+ * Connect to the remote server
183
+ *
184
+ * @param string $host
185
+ * @param int $port
186
+ * @param boolean $secure
187
+ */
188
+ public function connect($host, $port = 80, $secure = false)
189
+ {
190
+ // If the URI should be accessed via SSL, prepend the Hostname with ssl://
191
+ $host = ($secure ? $this->config['ssltransport'] : 'tcp') . '://' . $host;
192
+
193
+ // If we are connected to the wrong host, disconnect first
194
+ if (($this->connected_to[0] != $host || $this->connected_to[1] != $port)) {
195
+ if (is_resource($this->socket)) $this->close();
196
+ }
197
+
198
+ // Now, if we are not connected, connect
199
+ if (! is_resource($this->socket) || ! $this->config['keepalive']) {
200
+ $context = $this->getStreamContext();
201
+ if ($secure) {
202
+ if ($this->config['sslcert'] !== null) {
203
+ if (! stream_context_set_option($context, 'ssl', 'local_cert',
204
+ $this->config['sslcert'])) {
205
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
206
+ throw new Microsoft_Http_Client_Adapter_Exception('Unable to set sslcert option');
207
+ }
208
+ }
209
+ if ($this->config['sslpassphrase'] !== null) {
210
+ if (! stream_context_set_option($context, 'ssl', 'passphrase',
211
+ $this->config['sslpassphrase'])) {
212
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
213
+ throw new Microsoft_Http_Client_Adapter_Exception('Unable to set sslpassphrase option');
214
+ }
215
+ }
216
+ }
217
+
218
+ $flags = STREAM_CLIENT_CONNECT;
219
+ if ($this->config['persistent']) $flags |= STREAM_CLIENT_PERSISTENT;
220
+
221
+ $this->socket = @stream_socket_client($host . ':' . $port,
222
+ $errno,
223
+ $errstr,
224
+ (int) $this->config['timeout'],
225
+ $flags,
226
+ $context);
227
+
228
+ if (! $this->socket) {
229
+ $this->close();
230
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
231
+ throw new Microsoft_Http_Client_Adapter_Exception(
232
+ 'Unable to Connect to ' . $host . ':' . $port . '. Error #' . $errno . ': ' . $errstr);
233
+ }
234
+
235
+ // Set the stream timeout
236
+ if (! stream_set_timeout($this->socket, (int) $this->config['timeout'])) {
237
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
238
+ throw new Microsoft_Http_Client_Adapter_Exception('Unable to set the connection timeout');
239
+ }
240
+
241
+ // Update connected_to
242
+ $this->connected_to = array($host, $port);
243
+ }
244
+ }
245
+
246
+ /**
247
+ * Send request to the remote server
248
+ *
249
+ * @param string $method
250
+ * @param Microsoft_Uri_Http $uri
251
+ * @param string $http_ver
252
+ * @param array $headers
253
+ * @param string $body
254
+ * @return string Request as string
255
+ */
256
+ public function write($method, $uri, $http_ver = '1.1', $headers = array(), $body = '')
257
+ {
258
+ // Make sure we're properly connected
259
+ if (! $this->socket) {
260
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
261
+ throw new Microsoft_Http_Client_Adapter_Exception('Trying to write but we are not connected');
262
+ }
263
+
264
+ $host = $uri->getHost();
265
+ $host = (strtolower($uri->getScheme()) == 'https' ? $this->config['ssltransport'] : 'tcp') . '://' . $host;
266
+ if ($this->connected_to[0] != $host || $this->connected_to[1] != $uri->getPort()) {
267
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
268
+ throw new Microsoft_Http_Client_Adapter_Exception('Trying to write but we are connected to the wrong host');
269
+ }
270
+
271
+ // Save request method for later
272
+ $this->method = $method;
273
+
274
+ // Build request headers
275
+ $path = $uri->getPath();
276
+ if ($uri->getQuery()) $path .= '?' . $uri->getQuery();
277
+ $request = "{$method} {$path} HTTP/{$http_ver}\r\n";
278
+ foreach ($headers as $k => $v) {
279
+ if (is_string($k)) $v = ucfirst($k) . ": $v";
280
+ $request .= "$v\r\n";
281
+ }
282
+
283
+ if(is_resource($body)) {
284
+ $request .= "\r\n";
285
+ } else {
286
+ // Add the request body
287
+ $request .= "\r\n" . $body;
288
+ }
289
+
290
+ // Send the request
291
+ if (! @fwrite($this->socket, $request)) {
292
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
293
+ throw new Microsoft_Http_Client_Adapter_Exception('Error writing request to server');
294
+ }
295
+
296
+ if(is_resource($body)) {
297
+ if(stream_copy_to_stream($body, $this->socket) == 0) {
298
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
299
+ throw new Microsoft_Http_Client_Adapter_Exception('Error writing request to server');
300
+ }
301
+ }
302
+
303
+ return $request;
304
+ }
305
+
306
+ /**
307
+ * Read response from server
308
+ *
309
+ * @return string
310
+ */
311
+ public function read()
312
+ {
313
+ // First, read headers only
314
+ $response = '';
315
+ $gotStatus = false;
316
+ $stream = !empty($this->config['stream']);
317
+
318
+ while (($line = @fgets($this->socket)) !== false) {
319
+ $gotStatus = $gotStatus || (strpos($line, 'HTTP') !== false);
320
+ if ($gotStatus) {
321
+ $response .= $line;
322
+ if (rtrim($line) === '') break;
323
+ }
324
+ }
325
+
326
+ $this->_checkSocketReadTimeout();
327
+
328
+ $statusCode = Microsoft_Http_Response::extractCode($response);
329
+
330
+ // Handle 100 and 101 responses internally by restarting the read again
331
+ if ($statusCode == 100 || $statusCode == 101) return $this->read();
332
+
333
+ // Check headers to see what kind of connection / transfer encoding we have
334
+ $headers = Microsoft_Http_Response::extractHeaders($response);
335
+
336
+ /**
337
+ * Responses to HEAD requests and 204 or 304 responses are not expected
338
+ * to have a body - stop reading here
339
+ */
340
+ if ($statusCode == 304 || $statusCode == 204 ||
341
+ $this->method == Microsoft_Http_Client::HEAD) {
342
+
343
+ // Close the connection if requested to do so by the server
344
+ if (isset($headers['connection']) && $headers['connection'] == 'close') {
345
+ $this->close();
346
+ }
347
+ return $response;
348
+ }
349
+
350
+ // If we got a 'transfer-encoding: chunked' header
351
+ if (isset($headers['transfer-encoding'])) {
352
+
353
+ if (strtolower($headers['transfer-encoding']) == 'chunked') {
354
+
355
+ do {
356
+ $line = @fgets($this->socket);
357
+ $this->_checkSocketReadTimeout();
358
+
359
+ $chunk = $line;
360
+
361
+ // Figure out the next chunk size
362
+ $chunksize = trim($line);
363
+ if (! ctype_xdigit($chunksize)) {
364
+ $this->close();
365
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
366
+ throw new Microsoft_Http_Client_Adapter_Exception('Invalid chunk size "' .
367
+ $chunksize . '" unable to read chunked body');
368
+ }
369
+
370
+ // Convert the hexadecimal value to plain integer
371
+ $chunksize = hexdec($chunksize);
372
+
373
+ // Read next chunk
374
+ $read_to = ftell($this->socket) + $chunksize;
375
+
376
+ do {
377
+ $current_pos = ftell($this->socket);
378
+ if ($current_pos >= $read_to) break;
379
+
380
+ if($this->out_stream) {
381
+ if(stream_copy_to_stream($this->socket, $this->out_stream, $read_to - $current_pos) == 0) {
382
+ $this->_checkSocketReadTimeout();
383
+ break;
384
+ }
385
+ } else {
386
+ $line = @fread($this->socket, $read_to - $current_pos);
387
+ if ($line === false || strlen($line) === 0) {
388
+ $this->_checkSocketReadTimeout();
389
+ break;
390
+ }
391
+ $chunk .= $line;
392
+ }
393
+ } while (! feof($this->socket));
394
+
395
+ $chunk .= @fgets($this->socket);
396
+ $this->_checkSocketReadTimeout();
397
+
398
+ if(!$this->out_stream) {
399
+ $response .= $chunk;
400
+ }
401
+ } while ($chunksize > 0);
402
+ } else {
403
+ $this->close();
404
+ throw new Microsoft_Http_Client_Adapter_Exception('Cannot handle "' .
405
+ $headers['transfer-encoding'] . '" transfer encoding');
406
+ }
407
+
408
+ // We automatically decode chunked-messages when writing to a stream
409
+ // this means we have to disallow the Microsoft_Http_Response to do it again
410
+ if ($this->out_stream) {
411
+ $response = str_ireplace("Transfer-Encoding: chunked\r\n", '', $response);
412
+ }
413
+ // Else, if we got the content-length header, read this number of bytes
414
+ } elseif (isset($headers['content-length'])) {
415
+
416
+ $current_pos = ftell($this->socket);
417
+ $chunk = '';
418
+
419
+ for ($read_to = $current_pos + $headers['content-length'];
420
+ $read_to > $current_pos;
421
+ $current_pos = ftell($this->socket)) {
422
+
423
+ if($this->out_stream) {
424
+ if(@stream_copy_to_stream($this->socket, $this->out_stream, $read_to - $current_pos) == 0) {
425
+ $this->_checkSocketReadTimeout();
426
+ break;
427
+ }
428
+ } else {
429
+ $chunk = @fread($this->socket, $read_to - $current_pos);
430
+ if ($chunk === false || strlen($chunk) === 0) {
431
+ $this->_checkSocketReadTimeout();
432
+ break;
433
+ }
434
+
435
+ $response .= $chunk;
436
+ }
437
+
438
+ // Break if the connection ended prematurely
439
+ if (feof($this->socket)) break;
440
+ }
441
+
442
+ // Fallback: just read the response until EOF
443
+ } else {
444
+
445
+ do {
446
+ if($this->out_stream) {
447
+ if(@stream_copy_to_stream($this->socket, $this->out_stream) == 0) {
448
+ $this->_checkSocketReadTimeout();
449
+ break;
450
+ }
451
+ } else {
452
+ $buff = @fread($this->socket, 8192);
453
+ if ($buff === false || strlen($buff) === 0) {
454
+ $this->_checkSocketReadTimeout();
455
+ break;
456
+ } else {
457
+ $response .= $buff;
458
+ }
459
+ }
460
+
461
+ } while (feof($this->socket) === false);
462
+
463
+ $this->close();
464
+ }
465
+
466
+ // Close the connection if requested to do so by the server
467
+ if (isset($headers['connection']) && $headers['connection'] == 'close') {
468
+ $this->close();
469
+ }
470
+
471
+ return $response;
472
+ }
473
+
474
+ /**
475
+ * Close the connection to the server
476
+ *
477
+ */
478
+ public function close()
479
+ {
480
+ if (is_resource($this->socket)) @fclose($this->socket);
481
+ $this->socket = null;
482
+ $this->connected_to = array(null, null);
483
+ }
484
+
485
+ /**
486
+ * Check if the socket has timed out - if so close connection and throw
487
+ * an exception
488
+ *
489
+ * @throws Microsoft_Http_Client_Adapter_Exception with READ_TIMEOUT code
490
+ */
491
+ protected function _checkSocketReadTimeout()
492
+ {
493
+ if ($this->socket) {
494
+ $info = stream_get_meta_data($this->socket);
495
+ $timedout = $info['timed_out'];
496
+ if ($timedout) {
497
+ $this->close();
498
+ require_once 'Microsoft/Http/Client/Adapter/Exception.php';
499
+ throw new Microsoft_Http_Client_Adapter_Exception(
500
+ "Read timed out after {$this->config['timeout']} seconds",
501
+ Microsoft_Http_Client_Adapter_Exception::READ_TIMEOUT
502
+ );
503
+ }
504
+ }
505
+ }
506
+
507
+ /**
508
+ * Set output stream for the response
509
+ *
510
+ * @param resource $stream
511
+ * @return Microsoft_Http_Client_Adapter_Socket
512
+ */
513
+ public function setOutputStream($stream)
514
+ {
515
+ $this->out_stream = $stream;
516
+ return $this;
517
+ }
518
+
519
+ /**
520
+ * Destructor: make sure the socket is disconnected
521
+ *
522
+ * If we are in persistent TCP mode, will not close the connection
523
+ *
524
+ */
525
+ public function __destruct()
526
+ {
527
+ if (! $this->config['persistent']) {
528
+ if ($this->socket) $this->close();
529
+ }
530
+ }
531
+ }
app/libs/Microsoft/Http/Client/Adapter/Stream.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Zend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category Microsoft
17
+ * @package Microsoft_Http
18
+ * @subpackage Client_Adapter
19
+ * @version $Id: Interface.php 16214 2009-06-21 19:34:03Z thomas $
20
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
21
+ * @license http://framework.zend.com/license/new-bsd New BSD License
22
+ */
23
+
24
+ /**
25
+ * An interface description for Microsoft_Http_Client_Adapter_Stream classes.
26
+ *
27
+ * This interface decribes Microsoft_Http_Client_Adapter which supports streaming.
28
+ *
29
+ * @category Microsoft
30
+ * @package Microsoft_Http
31
+ * @subpackage Client_Adapter
32
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
33
+ * @license http://framework.zend.com/license/new-bsd New BSD License
34
+ */
35
+ interface Microsoft_Http_Client_Adapter_Stream
36
+ {
37
+ /**
38
+ * Set output stream
39
+ *
40
+ * This function sets output stream where the result will be stored.
41
+ *
42
+ * @param resource $stream Stream to write the output to
43
+ *
44
+ */
45
+ function setOutputStream($stream);
46
+ }
app/libs/Microsoft/Http/Client/Exception.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework
4
+ *
5
+ * LICENSE
6
+ *
7
+ * This source file is subject to the new BSD license that is bundled
8
+ * with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://framework.zend.com/license/new-bsd
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@zend.com so we can send you a copy immediately.
14
+ *
15
+ * @category Microsoft
16
+ * @package Microsoft_Http
17
+ * @subpackage Client_Exception
18
+ * @version $Id: Exception.php 16872 2009-07-20 11:47:08Z mikaelkael $
19
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
20
+ * @license http://framework.zend.com/license/new-bsd New BSD License
21
+ */
22
+
23
+ /**
24
+ * @see Microsoft_Http_Exception
25
+ */
26
+ require_once 'Microsoft/Http/Exception.php';
27
+
28
+ /**
29
+ * @category Microsoft
30
+ * @package Microsoft_Http
31
+ * @subpackage Client
32
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
33
+ * @license http://framework.zend.com/license/new-bsd New BSD License
34
+ */
35
+ class Microsoft_Http_Client_Exception extends Microsoft_Http_Exception
36
+ {}
app/libs/Microsoft/Http/Cookie.php ADDED
@@ -0,0 +1,408 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Zend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category Microsoft
17
+ * @package Microsoft_Http
18
+ * @subpackage Cookie
19
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
20
+ * @version $Id: Cookie.php 17131 2009-07-26 10:03:39Z shahar $
21
+ * @license http://framework.zend.com/license/new-bsd New BSD License
22
+ */
23
+
24
+ /**
25
+ * @see Microsoft_Uri_Http
26
+ */
27
+ require_once 'Microsoft/Uri/Http.php';
28
+
29
+
30
+ /**
31
+ * Microsoft_Http_Cookie is a class describing an HTTP cookie and all it's parameters.
32
+ *
33
+ * Microsoft_Http_Cookie is a class describing an HTTP cookie and all it's parameters. The
34
+ * class also enables validating whether the cookie should be sent to the server in
35
+ * a specified scenario according to the request URI, the expiry time and whether
36
+ * session cookies should be used or not. Generally speaking cookies should be
37
+ * contained in a Cookiejar object, or instantiated manually and added to an HTTP
38
+ * request.
39
+ *
40
+ * See http://wp.netscape.com/newsref/std/cookie_spec.html for some specs.
41
+ *
42
+ * @category Microsoft
43
+ * @package Microsoft_Http
44
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
45
+ * @license http://framework.zend.com/license/new-bsd New BSD License
46
+ */
47
+ class Microsoft_Http_Cookie
48
+ {
49
+ /**
50
+ * Cookie name
51
+ *
52
+ * @var string
53
+ */
54
+ protected $name;
55
+
56
+ /**
57
+ * Cookie value
58
+ *
59
+ * @var string
60
+ */
61
+ protected $value;
62
+
63
+ /**
64
+ * Cookie expiry date
65
+ *
66
+ * @var int
67
+ */
68
+ protected $expires;
69
+
70
+ /**
71
+ * Cookie domain
72
+ *
73
+ * @var string
74
+ */
75
+ protected $domain;
76
+
77
+ /**
78
+ * Cookie path
79
+ *
80
+ * @var string
81
+ */
82
+ protected $path;
83
+
84
+ /**
85
+ * Whether the cookie is secure or not
86
+ *
87
+ * @var boolean
88
+ */
89
+ protected $secure;
90
+
91
+ /**
92
+ * Cookie object constructor
93
+ *
94
+ * @todo Add validation of each one of the parameters (legal domain, etc.)
95
+ *
96
+ * @param string $name
97
+ * @param string $value
98
+ * @param string $domain
99
+ * @param int $expires
100
+ * @param string $path
101
+ * @param bool $secure
102
+ */
103
+ public function __construct($name, $value, $domain, $expires = null, $path = null, $secure = false)
104
+ {
105
+ if (preg_match("/[=,; \t\r\n\013\014]/", $name)) {
106
+ require_once 'Microsoft/Http/Exception.php';
107
+ throw new Microsoft_Http_Exception("Cookie name cannot contain these characters: =,; \\t\\r\\n\\013\\014 ({$name})");
108
+ }
109
+
110
+ if (! $this->name = (string) $name) {
111
+ require_once 'Microsoft/Http/Exception.php';
112
+ throw new Microsoft_Http_Exception('Cookies must have a name');
113
+ }
114
+
115
+ if (! $this->domain = (string) $domain) {
116
+ require_once 'Microsoft/Http/Exception.php';
117
+ throw new Microsoft_Http_Exception('Cookies must have a domain');
118
+ }
119
+
120
+ $this->value = (string) $value;
121
+ $this->expires = ($expires === null ? null : (int) $expires);
122
+ $this->path = ($path ? $path : '/');
123
+ $this->secure = $secure;
124
+ }
125
+
126
+ /**
127
+ * Get Cookie name
128
+ *
129
+ * @return string
130
+ */
131
+ public function getName()
132
+ {
133
+ return $this->name;
134
+ }
135
+
136
+ /**
137
+ * Get cookie value
138
+ *
139
+ * @return string
140
+ */
141
+ public function getValue()
142
+ {
143
+ return $this->value;
144
+ }
145
+
146
+ /**
147
+ * Get cookie domain
148
+ *
149
+ * @return string
150
+ */
151
+ public function getDomain()
152
+ {
153
+ return $this->domain;
154
+ }
155
+
156
+ /**
157
+ * Get the cookie path
158
+ *
159
+ * @return string
160
+ */
161
+ public function getPath()
162
+ {
163
+ return $this->path;
164
+ }
165
+
166
+ /**
167
+ * Get the expiry time of the cookie, or null if no expiry time is set
168
+ *
169
+ * @return int|null
170
+ */
171
+ public function getExpiryTime()
172
+ {
173
+ return $this->expires;
174
+ }
175
+
176
+ /**
177
+ * Check whether the cookie should only be sent over secure connections
178
+ *
179
+ * @return boolean
180
+ */
181
+ public function isSecure()
182
+ {
183
+ return $this->secure;
184
+ }
185
+
186
+ /**
187
+ * Check whether the cookie has expired
188
+ *
189
+ * Always returns false if the cookie is a session cookie (has no expiry time)
190
+ *
191
+ * @param int $now Timestamp to consider as "now"
192
+ * @return boolean
193
+ */
194
+ public function isExpired($now = null)
195
+ {
196
+ if ($now === null) $now = time();
197
+ if (is_int($this->expires) && $this->expires < $now) {
198
+ return true;
199
+ } else {
200
+ return false;
201
+ }
202
+ }
203
+
204
+ /**
205
+ * Check whether the cookie is a session cookie (has no expiry time set)
206
+ *
207
+ * @return boolean
208
+ */
209
+ public function isSessionCookie()
210
+ {
211
+ return ($this->expires === null);
212
+ }
213
+
214
+ /**
215
+ * Checks whether the cookie should be sent or not in a specific scenario
216
+ *
217
+ * @param string|Microsoft_Uri_Http $uri URI to check against (secure, domain, path)
218
+ * @param boolean $matchSessionCookies Whether to send session cookies
219
+ * @param int $now Override the current time when checking for expiry time
220
+ * @return boolean
221
+ */
222
+ public function match($uri, $matchSessionCookies = true, $now = null)
223
+ {
224
+ if (is_string ($uri)) {
225
+ $uri = Microsoft_Uri_Http::factory($uri);
226
+ }
227
+
228
+ // Make sure we have a valid Microsoft_Uri_Http object
229
+ if (! ($uri->valid() && ($uri->getScheme() == 'http' || $uri->getScheme() =='https'))) {
230
+ require_once 'Microsoft/Http/Exception.php';
231
+ throw new Microsoft_Http_Exception('Passed URI is not a valid HTTP or HTTPS URI');
232
+ }
233
+
234
+ // Check that the cookie is secure (if required) and not expired
235
+ if ($this->secure && $uri->getScheme() != 'https') return false;
236
+ if ($this->isExpired($now)) return false;
237
+ if ($this->isSessionCookie() && ! $matchSessionCookies) return false;
238
+
239
+ // Check if the domain matches
240
+ if (! self::matchCookieDomain($this->getDomain(), $uri->getHost())) {
241
+ return false;
242
+ }
243
+
244
+ // Check that path matches using prefix match
245
+ if (! self::matchCookiePath($this->getPath(), $uri->getPath())) {
246
+ return false;
247
+ }
248
+
249
+ // If we didn't die until now, return true.
250
+ return true;
251
+ }
252
+
253
+ /**
254
+ * Get the cookie as a string, suitable for sending as a "Cookie" header in an
255
+ * HTTP request
256
+ *
257
+ * @return string
258
+ */
259
+ public function __toString()
260
+ {
261
+ return $this->name . '=' . urlencode($this->value) . ';';
262
+ }
263
+
264
+ /**
265
+ * Generate a new Cookie object from a cookie string
266
+ * (for example the value of the Set-Cookie HTTP header)
267
+ *
268
+ * @param string $cookieStr
269
+ * @param Microsoft_Uri_Http|string $ref_uri Reference URI for default values (domain, path)
270
+ * @return Microsoft_Http_Cookie A new Microsoft_Http_Cookie object or false on failure.
271
+ */
272
+ public static function fromString($cookieStr, $ref_uri = null)
273
+ {
274
+ // Set default values
275
+ if (is_string($ref_uri)) {
276
+ $ref_uri = Microsoft_Uri_Http::factory($ref_uri);
277
+ }
278
+
279
+ $name = '';
280
+ $value = '';
281
+ $domain = '';
282
+ $path = '';
283
+ $expires = null;
284
+ $secure = false;
285
+ $parts = explode(';', $cookieStr);
286
+
287
+ // If first part does not include '=', fail
288
+ if (strpos($parts[0], '=') === false) return false;
289
+
290
+ // Get the name and value of the cookie
291
+ list($name, $value) = explode('=', trim(array_shift($parts)), 2);
292
+ $name = trim($name);
293
+ $value = urldecode(trim($value));
294
+
295
+ // Set default domain and path
296
+ if ($ref_uri instanceof Microsoft_Uri_Http) {
297
+ $domain = $ref_uri->getHost();
298
+ $path = $ref_uri->getPath();
299
+ $path = substr($path, 0, strrpos($path, '/'));
300
+ }
301
+
302
+ // Set other cookie parameters
303
+ foreach ($parts as $part) {
304
+ $part = trim($part);
305
+ if (strtolower($part) == 'secure') {
306
+ $secure = true;
307
+ continue;
308
+ }
309
+
310
+ $keyValue = explode('=', $part, 2);
311
+ if (count($keyValue) == 2) {
312
+ list($k, $v) = $keyValue;
313
+ switch (strtolower($k)) {
314
+ case 'expires':
315
+ if(($expires = strtotime($v)) === false) {
316
+ /**
317
+ * The expiration is past Tue, 19 Jan 2038 03:14:07 UTC
318
+ * the maximum for 32-bit signed integer. Microsoft_Date
319
+ * can get around that limit.
320
+ *
321
+ * @see Microsoft_Date
322
+ */
323
+ require_once 'Microsoft/Date.php';
324
+
325
+ $expireDate = new Microsoft_Date($v);
326
+ $expires = $expireDate->getTimestamp();
327
+ }
328
+ break;
329
+
330
+ case 'path':
331
+ $path = $v;
332
+ break;
333
+
334
+ case 'domain':
335
+ $domain = $v;
336
+ break;
337
+
338
+ default:
339
+ break;
340
+ }
341
+ }
342
+ }
343
+
344
+ if ($name !== '') {
345
+ return new self($name, $value, $domain, $expires, $path, $secure);
346
+ } else {
347
+ return false;
348
+ }
349
+ }
350
+
351
+ /**
352
+ * Check if a cookie's domain matches a host name.
353
+ *
354
+ * Used by Microsoft_Http_Cookie and Microsoft_Http_CookieJar for cookie matching
355
+ *
356
+ * @param string $cookieDomain
357
+ * @param string $host
358
+ *
359
+ * @return boolean
360
+ */
361
+ public static function matchCookieDomain($cookieDomain, $host)
362
+ {
363
+ if (! $cookieDomain) {
364
+ require_once 'Microsoft/Http/Exception.php';
365
+ throw new Microsoft_Http_Exception("\$cookieDomain is expected to be a cookie domain");
366
+ }
367
+
368
+ if (! $host) {
369
+ require_once 'Microsoft/Http/Exception.php';
370
+ throw new Microsoft_Http_Exception("\$host is expected to be a host name");
371
+ }
372
+
373
+ $cookieDomain = strtolower($cookieDomain);
374
+ $host = strtolower($host);
375
+
376
+ if ($cookieDomain[0] == '.') {
377
+ $cookieDomain = substr($cookieDomain, 1);
378
+ }
379
+
380
+ // Check for either exact match or suffix match
381
+ return ($cookieDomain == $host ||
382
+ preg_match("/\.$cookieDomain$/", $host));
383
+ }
384
+
385
+ /**
386
+ * Check if a cookie's path matches a URL path
387
+ *
388
+ * Used by Microsoft_Http_Cookie and Microsoft_Http_CookieJar for cookie matching
389
+ *
390
+ * @param string $cookiePath
391
+ * @param string $path
392
+ * @return boolean
393
+ */
394
+ public static function matchCookiePath($cookiePath, $path)
395
+ {
396
+ if (! $cookiePath) {
397
+ require_once 'Microsoft/Http/Exception.php';
398
+ throw new Microsoft_Http_Exception("\$cookiePath is expected to be a cookie path");
399
+ }
400
+
401
+ if (! $path) {
402
+ require_once 'Microsoft/Http/Exception.php';
403
+ throw new Microsoft_Http_Exception("\$path is expected to be a host name");
404
+ }
405
+
406
+ return (strpos($path, $cookiePath) === 0);
407
+ }
408
+ }
app/libs/Microsoft/Http/CookieJar.php ADDED
@@ -0,0 +1,403 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework
4
+ *
5
+ * LICENSE
6
+ *
7
+ * This source file is subject to the new BSD license that is bundled
8
+ * with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://framework.zend.com/license/new-bsd
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@zend.com so we can send you a copy immediately.
14
+ *
15
+ * @category Microsoft
16
+ * @package Microsoft_Http
17
+ * @subpackage CookieJar
18
+ * @version $Id: CookieJar.php 17131 2009-07-26 10:03:39Z shahar $
19
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
20
+ * @license http://framework.zend.com/license/new-bsd New BSD License
21
+ */
22
+
23
+ /**
24
+ * @see Microsoft_Uri
25
+ */
26
+ require_once "Microsoft/Uri.php";
27
+ /**
28
+ * @see Microsoft_Http_Cookie
29
+ */
30
+ require_once "Microsoft/Http/Cookie.php";
31
+ /**
32
+ * @see Microsoft_Http_Response
33
+ */
34
+ require_once "Microsoft/Http/Response.php";
35
+
36
+ /**
37
+ * A Microsoft_Http_CookieJar object is designed to contain and maintain HTTP cookies, and should
38
+ * be used along with Microsoft_Http_Client in order to manage cookies across HTTP requests and
39
+ * responses.
40
+ *
41
+ * The class contains an array of Microsoft_Http_Cookie objects. Cookies can be added to the jar
42
+ * automatically from a request or manually. Then, the jar can find and return the cookies
43
+ * needed for a specific HTTP request.
44
+ *
45
+ * A special parameter can be passed to all methods of this class that return cookies: Cookies
46
+ * can be returned either in their native form (as Microsoft_Http_Cookie objects) or as strings -
47
+ * the later is suitable for sending as the value of the "Cookie" header in an HTTP request.
48
+ * You can also choose, when returning more than one cookie, whether to get an array of strings
49
+ * (by passing Microsoft_Http_CookieJar::COOKIE_STRING_ARRAY) or one unified string for all cookies
50
+ * (by passing Microsoft_Http_CookieJar::COOKIE_STRING_CONCAT).
51
+ *
52
+ * @link http://wp.netscape.com/newsref/std/cookie_spec.html for some specs.
53
+ *
54
+ * @category Microsoft
55
+ * @package Microsoft_Http
56
+ * @subpackage CookieJar
57
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
58
+ * @license http://framework.zend.com/license/new-bsd New BSD License
59
+ */
60
+ class Microsoft_Http_CookieJar implements Countable, IteratorAggregate
61
+ {
62
+ /**
63
+ * Return cookie(s) as a Microsoft_Http_Cookie object
64
+ *
65
+ */
66
+ const COOKIE_OBJECT = 0;
67
+
68
+ /**
69
+ * Return cookie(s) as a string (suitable for sending in an HTTP request)
70
+ *
71
+ */
72
+ const COOKIE_STRING_ARRAY = 1;
73
+
74
+ /**
75
+ * Return all cookies as one long string (suitable for sending in an HTTP request)
76
+ *
77
+ */
78
+ const COOKIE_STRING_CONCAT = 2;
79
+
80
+ /**
81
+ * Array storing cookies
82
+ *
83
+ * Cookies are stored according to domain and path:
84
+ * $cookies
85
+ * + www.mydomain.com
86
+ * + /
87
+ * - cookie1
88
+ * - cookie2
89
+ * + /somepath
90
+ * - othercookie
91
+ * + www.otherdomain.net
92
+ * + /
93
+ * - alsocookie
94
+ *
95
+ * @var array
96
+ */
97
+ protected $cookies = array();
98
+
99
+ /**
100
+ * The Microsoft_Http_Cookie array
101
+ *
102
+ * @var array
103
+ */
104
+ protected $_rawCookies = array();
105
+
106
+ /**
107
+ * Construct a new CookieJar object
108
+ *
109
+ */
110
+ public function __construct()
111
+ { }
112
+
113
+ /**
114
+ * Add a cookie to the jar. Cookie should be passed either as a Microsoft_Http_Cookie object
115
+ * or as a string - in which case an object is created from the string.
116
+ *
117
+ * @param Microsoft_Http_Cookie|string $cookie
118
+ * @param Microsoft_Uri_Http|string $ref_uri Optional reference URI (for domain, path, secure)
119
+ */
120
+ public function addCookie($cookie, $ref_uri = null)
121
+ {
122
+ if (is_string($cookie)) {
123
+ $cookie = Microsoft_Http_Cookie::fromString($cookie, $ref_uri);
124
+ }
125
+
126
+ if ($cookie instanceof Microsoft_Http_Cookie) {
127
+ $domain = $cookie->getDomain();
128
+ $path = $cookie->getPath();
129
+ if (! isset($this->cookies[$domain])) $this->cookies[$domain] = array();
130
+ if (! isset($this->cookies[$domain][$path])) $this->cookies[$domain][$path] = array();
131
+ $this->cookies[$domain][$path][$cookie->getName()] = $cookie;
132
+ $this->_rawCookies[] = $cookie;
133
+ } else {
134
+ require_once 'Microsoft/Http/Exception.php';
135
+ throw new Microsoft_Http_Exception('Supplient argument is not a valid cookie string or object');
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Parse an HTTP response, adding all the cookies set in that response
141
+ * to the cookie jar.
142
+ *
143
+ * @param Microsoft_Http_Response $response
144
+ * @param Microsoft_Uri_Http|string $ref_uri Requested URI
145
+ */
146
+ public function addCookiesFromResponse($response, $ref_uri)
147
+ {
148
+ if (! $response instanceof Microsoft_Http_Response) {
149
+ require_once 'Microsoft/Http/Exception.php';
150
+ throw new Microsoft_Http_Exception('$response is expected to be a Response object, ' .
151
+ gettype($response) . ' was passed');
152
+ }
153
+
154
+ $cookie_hdrs = $response->getHeader('Set-Cookie');
155
+
156
+ if (is_array($cookie_hdrs)) {
157
+ foreach ($cookie_hdrs as $cookie) {
158
+ $this->addCookie($cookie, $ref_uri);
159
+ }
160
+ } elseif (is_string($cookie_hdrs)) {
161
+ $this->addCookie($cookie_hdrs, $ref_uri);
162
+ }
163
+ }
164
+
165
+ /**
166
+ * Get all cookies in the cookie jar as an array
167
+ *
168
+ * @param int $ret_as Whether to return cookies as objects of Microsoft_Http_Cookie or as strings
169
+ * @return array|string
170
+ */
171
+ public function getAllCookies($ret_as = self::COOKIE_OBJECT)
172
+ {
173
+ $cookies = $this->_flattenCookiesArray($this->cookies, $ret_as);
174
+ return $cookies;
175
+ }
176
+
177
+ /**
178
+ * Return an array of all cookies matching a specific request according to the request URI,
179
+ * whether session cookies should be sent or not, and the time to consider as "now" when
180
+ * checking cookie expiry time.
181
+ *
182
+ * @param string|Microsoft_Uri_Http $uri URI to check against (secure, domain, path)
183
+ * @param boolean $matchSessionCookies Whether to send session cookies
184
+ * @param int $ret_as Whether to return cookies as objects of Microsoft_Http_Cookie or as strings
185
+ * @param int $now Override the current time when checking for expiry time
186
+ * @return array|string
187
+ */
188
+ public function getMatchingCookies($uri, $matchSessionCookies = true,
189
+ $ret_as = self::COOKIE_OBJECT, $now = null)
190
+ {
191
+ if (is_string($uri)) $uri = Microsoft_Uri::factory($uri);
192
+ if (! $uri instanceof Microsoft_Uri_Http) {
193
+ require_once 'Microsoft/Http/Exception.php';
194
+ throw new Microsoft_Http_Exception("Invalid URI string or object passed");
195
+ }
196
+
197
+ // First, reduce the array of cookies to only those matching domain and path
198
+ $cookies = $this->_matchDomain($uri->getHost());
199
+ $cookies = $this->_matchPath($cookies, $uri->getPath());
200
+ $cookies = $this->_flattenCookiesArray($cookies, self::COOKIE_OBJECT);
201
+
202
+ // Next, run Cookie->match on all cookies to check secure, time and session mathcing
203
+ $ret = array();
204
+ foreach ($cookies as $cookie)
205
+ if ($cookie->match($uri, $matchSessionCookies, $now))
206
+ $ret[] = $cookie;
207
+
208
+ // Now, use self::_flattenCookiesArray again - only to convert to the return format ;)
209
+ $ret = $this->_flattenCookiesArray($ret, $ret_as);
210
+
211
+ return $ret;
212
+ }
213
+
214
+ /**
215
+ * Get a specific cookie according to a URI and name
216
+ *
217
+ * @param Microsoft_Uri_Http|string $uri The uri (domain and path) to match
218
+ * @param string $cookie_name The cookie's name
219
+ * @param int $ret_as Whether to return cookies as objects of Microsoft_Http_Cookie or as strings
220
+ * @return Microsoft_Http_Cookie|string
221
+ */
222
+ public function getCookie($uri, $cookie_name, $ret_as = self::COOKIE_OBJECT)
223
+ {
224
+ if (is_string($uri)) {
225
+ $uri = Microsoft_Uri::factory($uri);
226
+ }
227
+
228
+ if (! $uri instanceof Microsoft_Uri_Http) {
229
+ require_once 'Microsoft/Http/Exception.php';
230
+ throw new Microsoft_Http_Exception('Invalid URI specified');
231
+ }
232
+
233
+ // Get correct cookie path
234
+ $path = $uri->getPath();
235
+ $path = substr($path, 0, strrpos($path, '/'));
236
+ if (! $path) $path = '/';
237
+
238
+ if (isset($this->cookies[$uri->getHost()][$path][$cookie_name])) {
239
+ $cookie = $this->cookies[$uri->getHost()][$path][$cookie_name];
240
+
241
+ switch ($ret_as) {
242
+ case self::COOKIE_OBJECT:
243
+ return $cookie;
244
+ break;
245
+
246
+ case self::COOKIE_STRING_ARRAY:
247
+ case self::COOKIE_STRING_CONCAT:
248
+ return $cookie->__toString();
249
+ break;
250
+
251
+ default:
252
+ require_once 'Microsoft/Http/Exception.php';
253
+ throw new Microsoft_Http_Exception("Invalid value passed for \$ret_as: {$ret_as}");
254
+ break;
255
+ }
256
+ } else {
257
+ return false;
258
+ }
259
+ }
260
+
261
+ /**
262
+ * Helper function to recursivly flatten an array. Shoud be used when exporting the
263
+ * cookies array (or parts of it)
264
+ *
265
+ * @param Microsoft_Http_Cookie|array $ptr
266
+ * @param int $ret_as What value to return
267
+ * @return array|string
268
+ */
269
+ protected function _flattenCookiesArray($ptr, $ret_as = self::COOKIE_OBJECT) {
270
+ if (is_array($ptr)) {
271
+ $ret = ($ret_as == self::COOKIE_STRING_CONCAT ? '' : array());
272
+ foreach ($ptr as $item) {
273
+ if ($ret_as == self::COOKIE_STRING_CONCAT) {
274
+ $ret .= $this->_flattenCookiesArray($item, $ret_as);
275
+ } else {
276
+ $ret = array_merge($ret, $this->_flattenCookiesArray($item, $ret_as));
277
+ }
278
+ }
279
+ return $ret;
280
+ } elseif ($ptr instanceof Microsoft_Http_Cookie) {
281
+ switch ($ret_as) {
282
+ case self::COOKIE_STRING_ARRAY:
283
+ return array($ptr->__toString());
284
+ break;
285
+
286
+ case self::COOKIE_STRING_CONCAT:
287
+ return $ptr->__toString();
288
+ break;
289
+
290
+ case self::COOKIE_OBJECT:
291
+ default:
292
+ return array($ptr);
293
+ break;
294
+ }
295
+ }
296
+
297
+ return null;
298
+ }
299
+
300
+ /**
301
+ * Return a subset of the cookies array matching a specific domain
302
+ *
303
+ * @param string $domain
304
+ * @return array
305
+ */
306
+ protected function _matchDomain($domain)
307
+ {
308
+ $ret = array();
309
+
310
+ foreach (array_keys($this->cookies) as $cdom) {
311
+ if (Microsoft_Http_Cookie::matchCookieDomain($cdom, $domain)) {
312
+ $ret[$cdom] = $this->cookies[$cdom];
313
+ }
314
+ }
315
+
316
+ return $ret;
317
+ }
318
+
319
+ /**
320
+ * Return a subset of a domain-matching cookies that also match a specified path
321
+ *
322
+ * @param array $dom_array
323
+ * @param string $path
324
+ * @return array
325
+ */
326
+ protected function _matchPath($domains, $path)
327
+ {
328
+ $ret = array();
329
+
330
+ foreach ($domains as $dom => $paths_array) {
331
+ foreach (array_keys($paths_array) as $cpath) {
332
+ if (Microsoft_Http_Cookie::matchCookiePath($cpath, $path)) {
333
+ if (! isset($ret[$dom])) {
334
+ $ret[$dom] = array();
335
+ }
336
+
337
+ $ret[$dom][$cpath] = $paths_array[$cpath];
338
+ }
339
+ }
340
+ }
341
+
342
+ return $ret;
343
+ }
344
+
345
+ /**
346
+ * Create a new CookieJar object and automatically load into it all the
347
+ * cookies set in an Http_Response object. If $uri is set, it will be
348
+ * considered as the requested URI for setting default domain and path
349
+ * of the cookie.
350
+ *
351
+ * @param Microsoft_Http_Response $response HTTP Response object
352
+ * @param Microsoft_Uri_Http|string $uri The requested URI
353
+ * @return Microsoft_Http_CookieJar
354
+ * @todo Add the $uri functionality.
355
+ */
356
+ public static function fromResponse(Microsoft_Http_Response $response, $ref_uri)
357
+ {
358
+ $jar = new self();
359
+ $jar->addCookiesFromResponse($response, $ref_uri);
360
+ return $jar;
361
+ }
362
+
363
+ /**
364
+ * Required by Countable interface
365
+ *
366
+ * @return int
367
+ */
368
+ public function count()
369
+ {
370
+ return count($this->_rawCookies);
371
+ }
372
+
373
+ /**
374
+ * Required by IteratorAggregate interface
375
+ *
376
+ * @return ArrayIterator
377
+ */
378
+ public function getIterator()
379
+ {
380
+ return new ArrayIterator($this->_rawCookies);
381
+ }
382
+
383
+ /**
384
+ * Tells if the jar is empty of any cookie
385
+ *
386
+ * @return bool
387
+ */
388
+ public function isEmpty()
389
+ {
390
+ return count($this) == 0;
391
+ }
392
+
393
+ /**
394
+ * Empties the cookieJar of any cookie
395
+ *
396
+ * @return Microsoft_Http_CookieJar
397
+ */
398
+ public function reset()
399
+ {
400
+ $this->cookies = $this->_rawCookies = array();
401
+ return $this;
402
+ }
403
+ }
app/libs/Microsoft/Http/Exception.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_Http
30
+ * @subpackage Exception
31
+ * @version $Id: Exception.php 45259 2010-04-16 12:13:55Z unknown $
32
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
33
+ * @license http://phpazure.codeplex.com/license
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_Exception
38
+ */
39
+ require_once 'Microsoft/Exception.php';
40
+
41
+ /**
42
+ * @category Microsoft
43
+ * @package Microsoft_Http
44
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
45
+ * @license http://phpazure.codeplex.com/license
46
+ */
47
+ class Microsoft_Http_Exception extends Microsoft_Exception
48
+ {}
app/libs/Microsoft/Http/Response.php ADDED
@@ -0,0 +1,664 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Zend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category Microsoft
17
+ * @package Microsoft_Http
18
+ * @subpackage Response
19
+ * @version $Id: Response.php 35835 2009-12-17 09:40:36Z unknown $
20
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
21
+ * @license http://framework.zend.com/license/new-bsd New BSD License
22
+ */
23
+
24
+ /**
25
+ * Microsoft_Http_Response represents an HTTP 1.0 / 1.1 response message. It
26
+ * includes easy access to all the response's different elemts, as well as some
27
+ * convenience methods for parsing and validating HTTP responses.
28
+ *
29
+ * @package Microsoft_Http
30
+ * @subpackage Response
31
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
32
+ * @license http://framework.zend.com/license/new-bsd New BSD License
33
+ */
34
+ class Microsoft_Http_Response
35
+ {
36
+ /**
37
+ * List of all known HTTP response codes - used by responseCodeAsText() to
38
+ * translate numeric codes to messages.
39
+ *
40
+ * @var array
41
+ */
42
+ protected static $messages = array(
43
+ // Informational 1xx
44
+ 100 => 'Continue',
45
+ 101 => 'Switching Protocols',
46
+
47
+ // Success 2xx
48
+ 200 => 'OK',
49
+ 201 => 'Created',
50
+ 202 => 'Accepted',
51
+ 203 => 'Non-Authoritative Information',
52
+ 204 => 'No Content',
53
+ 205 => 'Reset Content',
54
+ 206 => 'Partial Content',
55
+
56
+ // Redirection 3xx
57
+ 300 => 'Multiple Choices',
58
+ 301 => 'Moved Permanently',
59
+ 302 => 'Found', // 1.1
60
+ 303 => 'See Other',
61
+ 304 => 'Not Modified',
62
+ 305 => 'Use Proxy',
63
+ // 306 is deprecated but reserved
64
+ 307 => 'Temporary Redirect',
65
+
66
+ // Client Error 4xx
67
+ 400 => 'Bad Request',
68
+ 401 => 'Unauthorized',
69
+ 402 => 'Payment Required',
70
+ 403 => 'Forbidden',
71
+ 404 => 'Not Found',
72
+ 405 => 'Method Not Allowed',
73
+ 406 => 'Not Acceptable',
74
+ 407 => 'Proxy Authentication Required',
75
+ 408 => 'Request Timeout',
76
+ 409 => 'Conflict',
77
+ 410 => 'Gone',
78
+ 411 => 'Length Required',
79
+ 412 => 'Precondition Failed',
80
+ 413 => 'Request Entity Too Large',
81
+ 414 => 'Request-URI Too Long',
82
+ 415 => 'Unsupported Media Type',
83
+ 416 => 'Requested Range Not Satisfiable',
84
+ 417 => 'Expectation Failed',
85
+
86
+ // Server Error 5xx
87
+ 500 => 'Internal Server Error',
88
+ 501 => 'Not Implemented',
89
+ 502 => 'Bad Gateway',
90
+ 503 => 'Service Unavailable',
91
+ 504 => 'Gateway Timeout',
92
+ 505 => 'HTTP Version Not Supported',
93
+ 509 => 'Bandwidth Limit Exceeded'
94
+ );
95
+
96
+ /**
97
+ * The HTTP version (1.0, 1.1)
98
+ *
99
+ * @var string
100
+ */
101
+ protected $version;
102
+
103
+ /**
104
+ * The HTTP response code
105
+ *
106
+ * @var int
107
+ */
108
+ protected $code;
109
+
110
+ /**
111
+ * The HTTP response code as string
112
+ * (e.g. 'Not Found' for 404 or 'Internal Server Error' for 500)
113
+ *
114
+ * @var string
115
+ */
116
+ protected $message;
117
+
118
+ /**
119
+ * The HTTP response headers array
120
+ *
121
+ * @var array
122
+ */
123
+ protected $headers = array();
124
+
125
+ /**
126
+ * The HTTP response body
127
+ *
128
+ * @var string
129
+ */
130
+ protected $body;
131
+
132
+ /**
133
+ * HTTP response constructor
134
+ *
135
+ * In most cases, you would use Microsoft_Http_Response::fromString to parse an HTTP
136
+ * response string and create a new Microsoft_Http_Response object.
137
+ *
138
+ * NOTE: The constructor no longer accepts nulls or empty values for the code and
139
+ * headers and will throw an exception if the passed values do not form a valid HTTP
140
+ * responses.
141
+ *
142
+ * If no message is passed, the message will be guessed according to the response code.
143
+ *
144
+ * @param int $code Response code (200, 404, ...)
145
+ * @param array $headers Headers array
146
+ * @param string $body Response body
147
+ * @param string $version HTTP version
148
+ * @param string $message Response code as text
149
+ * @throws Microsoft_Http_Exception
150
+ */
151
+ public function __construct($code, $headers, $body = null, $version = '1.1', $message = null)
152
+ {
153
+ // Make sure the response code is valid and set it
154
+ if (self::responseCodeAsText($code) === null) {
155
+ require_once 'Microsoft/Http/Exception.php';
156
+ throw new Microsoft_Http_Exception("{$code} is not a valid HTTP response code");
157
+ }
158
+
159
+ $this->code = $code;
160
+
161
+ // Make sure we got valid headers and set them
162
+ if (! is_array($headers)) {
163
+ require_once 'Microsoft/Http/Exception.php';
164
+ throw new Microsoft_Http_Exception('No valid headers were passed');
165
+ }
166
+
167
+ foreach ($headers as $name => $value) {
168
+ if (is_int($name))
169
+ list($name, $value) = explode(": ", $value, 1);
170
+
171
+ $this->headers[ucwords(strtolower($name))] = $value;
172
+ }
173
+
174
+ // Set the body
175
+ $this->body = $body;
176
+
177
+ // Set the HTTP version
178
+ if (! preg_match('|^\d\.\d$|', $version)) {
179
+ require_once 'Microsoft/Http/Exception.php';
180
+ throw new Microsoft_Http_Exception("Invalid HTTP response version: $version");
181
+ }
182
+
183
+ $this->version = $version;
184
+
185
+ // If we got the response message, set it. Else, set it according to
186
+ // the response code
187
+ if (is_string($message)) {
188
+ $this->message = $message;
189
+ } else {
190
+ $this->message = self::responseCodeAsText($code);
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Check whether the response is an error
196
+ *
197
+ * @return boolean
198
+ */
199
+ public function isError()
200
+ {
201
+ $restype = floor($this->code / 100);
202
+ if ($restype == 4 || $restype == 5) {
203
+ return true;
204
+ }
205
+
206
+ return false;
207
+ }
208
+
209
+ /**
210
+ * Check whether the response in successful
211
+ *
212
+ * @return boolean
213
+ */
214
+ public function isSuccessful()
215
+ {
216
+ $restype = floor($this->code / 100);
217
+ if ($restype == 2 || $restype == 1) { // Shouldn't 3xx count as success as well ???
218
+ return true;
219
+ }
220
+
221
+ return false;
222
+ }
223
+
224
+ /**
225
+ * Check whether the response is a redirection
226
+ *
227
+ * @return boolean
228
+ */
229
+ public function isRedirect()
230
+ {
231
+ $restype = floor($this->code / 100);
232
+ if ($restype == 3) {
233
+ return true;
234
+ }
235
+
236
+ return false;
237
+ }
238
+
239
+ /**
240
+ * Get the response body as string
241
+ *
242
+ * This method returns the body of the HTTP response (the content), as it
243
+ * should be in it's readable version - that is, after decoding it (if it
244
+ * was decoded), deflating it (if it was gzip compressed), etc.
245
+ *
246
+ * If you want to get the raw body (as transfered on wire) use
247
+ * $this->getRawBody() instead.
248
+ *
249
+ * @return string
250
+ */
251
+ public function getBody()
252
+ {
253
+ $body = '';
254
+
255
+ // Decode the body if it was transfer-encoded
256
+ switch (strtolower($this->getHeader('transfer-encoding'))) {
257
+
258
+ // Handle chunked body
259
+ case 'chunked':
260
+ $body = self::decodeChunkedBody($this->body);
261
+ break;
262
+
263
+ // No transfer encoding, or unknown encoding extension:
264
+ // return body as is
265
+ default:
266
+ $body = $this->body;
267
+ break;
268
+ }
269
+
270
+ // Decode any content-encoding (gzip or deflate) if needed
271
+ switch (strtolower($this->getHeader('content-encoding'))) {
272
+
273
+ // Handle gzip encoding
274
+ case 'gzip':
275
+ $body = self::decodeGzip($body);
276
+ break;
277
+
278
+ // Handle deflate encoding
279
+ case 'deflate':
280
+ $body = self::decodeDeflate($body);
281
+ break;
282
+
283
+ default:
284
+ break;
285
+ }
286
+
287
+ return $body;
288
+ }
289
+
290
+ /**
291
+ * Get the raw response body (as transfered "on wire") as string
292
+ *
293
+ * If the body is encoded (with Transfer-Encoding, not content-encoding -
294
+ * IE "chunked" body), gzip compressed, etc. it will not be decoded.
295
+ *
296
+ * @return string
297
+ */
298
+ public function getRawBody()
299
+ {
300
+ return $this->body;
301
+ }
302
+
303
+ /**
304
+ * Get the HTTP version of the response
305
+ *
306
+ * @return string
307
+ */
308
+ public function getVersion()
309
+ {
310
+ return $this->version;
311
+ }
312
+
313
+ /**
314
+ * Get the HTTP response status code
315
+ *
316
+ * @return int
317
+ */
318
+ public function getStatus()
319
+ {
320
+ return $this->code;
321
+ }
322
+
323
+ /**
324
+ * Return a message describing the HTTP response code
325
+ * (Eg. "OK", "Not Found", "Moved Permanently")
326
+ *
327
+ * @return string
328
+ */
329
+ public function getMessage()
330
+ {
331
+ return $this->message;
332
+ }
333
+
334
+ /**
335
+ * Get the response headers
336
+ *
337
+ * @return array
338
+ */
339
+ public function getHeaders()
340
+ {
341
+ return $this->headers;
342
+ }
343
+
344
+ /**
345
+ * Get a specific header as string, or null if it is not set
346
+ *
347
+ * @param string$header
348
+ * @return string|array|null
349
+ */
350
+ public function getHeader($header)
351
+ {
352
+ $header = ucwords(strtolower($header));
353
+ if (! is_string($header) || ! isset($this->headers[$header])) return null;
354
+
355
+ return $this->headers[$header];
356
+ }
357
+
358
+ /**
359
+ * Get all headers as string
360
+ *
361
+ * @param boolean $status_line Whether to return the first status line (IE "HTTP 200 OK")
362
+ * @param string $br Line breaks (eg. "\n", "\r\n", "<br />")
363
+ * @return string
364
+ */
365
+ public function getHeadersAsString($status_line = true, $br = "\n")
366
+ {
367
+ $str = '';
368
+
369
+ if ($status_line) {
370
+ $str = "HTTP/{$this->version} {$this->code} {$this->message}{$br}";
371
+ }
372
+
373
+ // Iterate over the headers and stringify them
374
+ foreach ($this->headers as $name => $value)
375
+ {
376
+ if (is_string($value))
377
+ $str .= "{$name}: {$value}{$br}";
378
+
379
+ elseif (is_array($value)) {
380
+ foreach ($value as $subval) {
381
+ $str .= "{$name}: {$subval}{$br}";
382
+ }
383
+ }
384
+ }
385
+
386
+ return $str;
387
+ }
388
+
389
+ /**
390
+ * Get the entire response as string
391
+ *
392
+ * @param string $br Line breaks (eg. "\n", "\r\n", "<br />")
393
+ * @return string
394
+ */
395
+ public function asString($br = "\n")
396
+ {
397
+ return $this->getHeadersAsString(true, $br) . $br . $this->getRawBody();
398
+ }
399
+
400
+ /**
401
+ * Implements magic __toString()
402
+ *
403
+ * @return string
404
+ */
405
+ public function __toString()
406
+ {
407
+ return $this->asString();
408
+ }
409
+
410
+ /**
411
+ * A convenience function that returns a text representation of
412
+ * HTTP response codes. Returns 'Unknown' for unknown codes.
413
+ * Returns array of all codes, if $code is not specified.
414
+ *
415
+ * Conforms to HTTP/1.1 as defined in RFC 2616 (except for 'Unknown')
416
+ * See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10 for reference
417
+ *
418
+ * @param int $code HTTP response code
419
+ * @param boolean $http11 Use HTTP version 1.1
420
+ * @return string
421
+ */
422
+ public static function responseCodeAsText($code = null, $http11 = true)
423
+ {
424
+ $messages = self::$messages;
425
+ if (! $http11) $messages[302] = 'Moved Temporarily';
426
+
427
+ if ($code === null) {
428
+ return $messages;
429
+ } elseif (isset($messages[$code])) {
430
+ return $messages[$code];
431
+ } else {
432
+ return 'Unknown';
433
+ }
434
+ }
435
+
436
+ /**
437
+ * Extract the response code from a response string
438
+ *
439
+ * @param string $response_str
440
+ * @return int
441
+ */
442
+ public static function extractCode($response_str)
443
+ {
444
+ preg_match("|^HTTP/[\d\.x]+ (\d+)|", $response_str, $m);
445
+
446
+ if (isset($m[1])) {
447
+ return (int) $m[1];
448
+ } else {
449
+ return false;
450
+ }
451
+ }
452
+
453
+ /**
454
+ * Extract the HTTP message from a response
455
+ *
456
+ * @param string $response_str
457
+ * @return string
458
+ */
459
+ public static function extractMessage($response_str)
460
+ {
461
+ preg_match("|^HTTP/[\d\.x]+ \d+ ([^\r\n]+)|", $response_str, $m);
462
+
463
+ if (isset($m[1])) {
464
+ return $m[1];
465
+ } else {
466
+ return false;
467
+ }
468
+ }
469
+
470
+ /**
471
+ * Extract the HTTP version from a response
472
+ *
473
+ * @param string $response_str
474
+ * @return string
475
+ */
476
+ public static function extractVersion($response_str)
477
+ {
478
+ preg_match("|^HTTP/([\d\.x]+) \d+|", $response_str, $m);
479
+
480
+ if (isset($m[1])) {
481
+ return $m[1];
482
+ } else {
483
+ return false;
484
+ }
485
+ }
486
+
487
+ /**
488
+ * Extract the headers from a response string
489
+ *
490
+ * @param string $response_str
491
+ * @return array
492
+ */
493
+ public static function extractHeaders($response_str)
494
+ {
495
+ $headers = array();
496
+
497
+ // First, split body and headers
498
+ $parts = preg_split('|(?:\r?\n){2}|m', $response_str, 2);
499
+ if (! $parts[0]) return $headers;
500
+
501
+ // Split headers part to lines
502
+ $lines = explode("\n", $parts[0]);
503
+ unset($parts);
504
+ $last_header = null;
505
+
506
+ foreach($lines as $line) {
507
+ $line = trim($line, "\r\n");
508
+ if ($line == "") break;
509
+
510
+ if (preg_match("|^([\w-]+):\s+(.+)|", $line, $m)) {
511
+ unset($last_header);
512
+ $h_name = strtolower($m[1]);
513
+ $h_value = $m[2];
514
+
515
+ if (isset($headers[$h_name])) {
516
+ if (! is_array($headers[$h_name])) {
517
+ $headers[$h_name] = array($headers[$h_name]);
518
+ }
519
+
520
+ $headers[$h_name][] = $h_value;
521
+ } else {
522
+ $headers[$h_name] = $h_value;
523
+ }
524
+ $last_header = $h_name;
525
+ } elseif (preg_match("|^\s+(.+)$|", $line, $m) && $last_header !== null) {
526
+ if (is_array($headers[$last_header])) {
527
+ end($headers[$last_header]);
528
+ $last_header_key = key($headers[$last_header]);
529
+ $headers[$last_header][$last_header_key] .= $m[1];
530
+ } else {
531
+ $headers[$last_header] .= $m[1];
532
+ }
533
+ }
534
+ }
535
+
536
+ return $headers;
537
+ }
538
+
539
+ /**
540
+ * Extract the body from a response string
541
+ *
542
+ * @param string $response_str
543
+ * @return string
544
+ */
545
+ public static function extractBody($response_str)
546
+ {
547
+ $parts = preg_split('|(?:\r?\n){2}|m', $response_str, 2);
548
+ if (isset($parts[1])) {
549
+ return $parts[1];
550
+ }
551
+ return '';
552
+ }
553
+
554
+ /**
555
+ * Decode a "chunked" transfer-encoded body and return the decoded text
556
+ *
557
+ * @param string $body
558
+ * @return string
559
+ */
560
+ public static function decodeChunkedBody($body)
561
+ {
562
+ $decBody = '';
563
+
564
+ // If mbstring overloads substr and strlen functions, we have to
565
+ // override it's internal encoding
566
+ if (function_exists('mb_internal_encoding') &&
567
+ ((int) ini_get('mbstring.func_overload')) & 2) {
568
+
569
+ $mbIntEnc = mb_internal_encoding();
570
+ mb_internal_encoding('ASCII');
571
+ }
572
+
573
+ while (trim($body)) {
574
+ if (! preg_match("/^([\da-fA-F]+)[^\r\n]*\r\n/sm", $body, $m)) {
575
+ require_once 'Microsoft/Http/Exception.php';
576
+ throw new Microsoft_Http_Exception("Error parsing body - doesn't seem to be a chunked message");
577
+ }
578
+
579
+ $length = hexdec(trim($m[1]));
580
+ $cut = strlen($m[0]);
581
+ $decBody .= substr($body, $cut, $length);
582
+ $body = substr($body, $cut + $length + 2);
583
+ }
584
+
585
+ if (isset($mbIntEnc)) {
586
+ mb_internal_encoding($mbIntEnc);
587
+ }
588
+
589
+ return $decBody;
590
+ }
591
+
592
+ /**
593
+ * Decode a gzip encoded message (when Content-encoding = gzip)
594
+ *
595
+ * Currently requires PHP with zlib support
596
+ *
597
+ * @param string $body
598
+ * @return string
599
+ */
600
+ public static function decodeGzip($body)
601
+ {
602
+ if (! function_exists('gzinflate')) {
603
+ require_once 'Microsoft/Http/Exception.php';
604
+ throw new Microsoft_Http_Exception(
605
+ 'zlib extension is required in order to decode "gzip" encoding'
606
+ );
607
+ }
608
+
609
+ return gzinflate(substr($body, 10));
610
+ }
611
+
612
+ /**
613
+ * Decode a zlib deflated message (when Content-encoding = deflate)
614
+ *
615
+ * Currently requires PHP with zlib support
616
+ *
617
+ * @param string $body
618
+ * @return string
619
+ */
620
+ public static function decodeDeflate($body)
621
+ {
622
+ if (! function_exists('gzuncompress')) {
623
+ require_once 'Microsoft/Http/Exception.php';
624
+ throw new Microsoft_Http_Exception(
625
+ 'zlib extension is required in order to decode "deflate" encoding'
626
+ );
627
+ }
628
+
629
+ /**
630
+ * Some servers (IIS ?) send a broken deflate response, without the
631
+ * RFC-required zlib header.
632
+ *
633
+ * We try to detect the zlib header, and if it does not exsit we
634
+ * teat the body is plain DEFLATE content.
635
+ *
636
+ * This method was adapted from PEAR HTTP_Request2 by (c) Alexey Borzov
637
+ *
638
+ * @link http://framework.zend.com/issues/browse/ZF-6040
639
+ */
640
+ $zlibHeader = unpack('n', substr($body, 0, 2));
641
+ if ($zlibHeader[1] % 31 == 0) {
642
+ return gzuncompress($body);
643
+ } else {
644
+ return gzinflate($body);
645
+ }
646
+ }
647
+
648
+ /**
649
+ * Create a new Microsoft_Http_Response object from a string
650
+ *
651
+ * @param string $response_str
652
+ * @return Microsoft_Http_Response
653
+ */
654
+ public static function fromString($response_str)
655
+ {
656
+ $code = self::extractCode($response_str);
657
+ $headers = self::extractHeaders($response_str);
658
+ $body = self::extractBody($response_str);
659
+ $version = self::extractVersion($response_str);
660
+ $message = self::extractMessage($response_str);
661
+
662
+ return new Microsoft_Http_Response($code, $headers, $body, $version, $message);
663
+ }
664
+ }
app/libs/Microsoft/Http/Response/Stream.php ADDED
@@ -0,0 +1,235 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Zend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category Microsoft
17
+ * @package Microsoft_Http
18
+ * @subpackage Response
19
+ * @version $Id: Response.php 17131 2009-07-26 10:03:39Z shahar $
20
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
21
+ * @license http://framework.zend.com/license/new-bsd New BSD License
22
+ */
23
+
24
+ /**
25
+ * Microsoft_Http_Response represents an HTTP 1.0 / 1.1 response message. It
26
+ * includes easy access to all the response's different elemts, as well as some
27
+ * convenience methods for parsing and validating HTTP responses.
28
+ *
29
+ * @package Microsoft_Http
30
+ * @subpackage Response
31
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
32
+ * @license http://framework.zend.com/license/new-bsd New BSD License
33
+ */
34
+ class Microsoft_Http_Response_Stream extends Microsoft_Http_Response
35
+ {
36
+ /**
37
+ * Response as stream
38
+ *
39
+ * @var resource
40
+ */
41
+ protected $stream;
42
+
43
+ /**
44
+ * The name of the file containing the stream
45
+ *
46
+ * Will be empty if stream is not file-based.
47
+ *
48
+ * @var string
49
+ */
50
+ protected $stream_name;
51
+
52
+ /**
53
+ * Should we clean up the stream file when this response is closed?
54
+ *
55
+ * @var boolean
56
+ */
57
+ protected $_cleanup;
58
+
59
+ /**
60
+ * Get the response as stream
61
+ *
62
+ * @return resourse
63
+ */
64
+ public function getStream()
65
+ {
66
+ return $this->stream;
67
+ }
68
+
69
+ /**
70
+ * Set the response stream
71
+ *
72
+ * @param resourse $stream
73
+ * @return Microsoft_Http_Response_Stream
74
+ */
75
+ public function setStream($stream)
76
+ {
77
+ $this->stream = $stream;
78
+ return $this;
79
+ }
80
+
81
+ /**
82
+ * Get the cleanup trigger
83
+ *
84
+ * @return boolean
85
+ */
86
+ public function getCleanup() {
87
+ return $this->_cleanup;
88
+ }
89
+
90
+ /**
91
+ * Set the cleanup trigger
92
+ *
93
+ * @param $cleanup Set cleanup trigger
94
+ */
95
+ public function setCleanup($cleanup = true) {
96
+ $this->_cleanup = $cleanup;
97
+ }
98
+
99
+ /**
100
+ * Get file name associated with the stream
101
+ *
102
+ * @return string
103
+ */
104
+ public function getStreamName() {
105
+ return $this->stream_name;
106
+ }
107
+
108
+ /**
109
+ * Set file name associated with the stream
110
+ *
111
+ * @param string $stream_name Name to set
112
+ * @return Microsoft_Http_Response_Stream
113
+ */
114
+ public function setStreamName($stream_name) {
115
+ $this->stream_name = $stream_name;
116
+ return $this;
117
+ }
118
+
119
+
120
+ /**
121
+ * HTTP response constructor
122
+ *
123
+ * In most cases, you would use Microsoft_Http_Response::fromString to parse an HTTP
124
+ * response string and create a new Microsoft_Http_Response object.
125
+ *
126
+ * NOTE: The constructor no longer accepts nulls or empty values for the code and
127
+ * headers and will throw an exception if the passed values do not form a valid HTTP
128
+ * responses.
129
+ *
130
+ * If no message is passed, the message will be guessed according to the response code.
131
+ *
132
+ * @param int $code Response code (200, 404, ...)
133
+ * @param array $headers Headers array
134
+ * @param string $body Response body
135
+ * @param string $version HTTP version
136
+ * @param string $message Response code as text
137
+ * @throws Microsoft_Http_Exception
138
+ */
139
+ public function __construct($code, $headers, $body = null, $version = '1.1', $message = null)
140
+ {
141
+
142
+ if(is_resource($body)) {
143
+ $this->setStream($body);
144
+ $body = '';
145
+ }
146
+ parent::__construct($code, $headers, $body, $version, $message);
147
+ }
148
+
149
+ /**
150
+ * Create a new Microsoft_Http_Response_Stream object from a string
151
+ *
152
+ * @param string $response_str
153
+ * @param resource $stream
154
+ * @return Microsoft_Http_Response_Stream
155
+ */
156
+ public static function fromStream($response_str, $stream)
157
+ {
158
+ $code = self::extractCode($response_str);
159
+ $headers = self::extractHeaders($response_str);
160
+ $version = self::extractVersion($response_str);
161
+ $message = self::extractMessage($response_str);
162
+
163
+ return new self($code, $headers, $stream, $version, $message);
164
+ }
165
+
166
+ /**
167
+ * Get the response body as string
168
+ *
169
+ * This method returns the body of the HTTP response (the content), as it
170
+ * should be in it's readable version - that is, after decoding it (if it
171
+ * was decoded), deflating it (if it was gzip compressed), etc.
172
+ *
173
+ * If you want to get the raw body (as transfered on wire) use
174
+ * $this->getRawBody() instead.
175
+ *
176
+ * @return string
177
+ */
178
+ public function getBody()
179
+ {
180
+ if($this->stream != null) {
181
+ $this->readStream();
182
+ }
183
+ return parent::getBody();
184
+ }
185
+
186
+ /**
187
+ * Get the raw response body (as transfered "on wire") as string
188
+ *
189
+ * If the body is encoded (with Transfer-Encoding, not content-encoding -
190
+ * IE "chunked" body), gzip compressed, etc. it will not be decoded.
191
+ *
192
+ * @return string
193
+ */
194
+ public function getRawBody()
195
+ {
196
+ if($this->stream) {
197
+ $this->readStream();
198
+ }
199
+ return $this->body;
200
+ }
201
+
202
+ /**
203
+ * Read stream content and return it as string
204
+ *
205
+ * Function reads the remainder of the body from the stream and closes the stream.
206
+ *
207
+ * @return string
208
+ */
209
+ protected function readStream()
210
+ {
211
+ if(!is_resource($this->stream)) {
212
+ return '';
213
+ }
214
+
215
+ if(isset($headers['content-length'])) {
216
+ $this->body = stream_get_contents($this->stream, $headers['content-length']);
217
+ } else {
218
+ $this->body = stream_get_contents($this->stream);
219
+ }
220
+ fclose($this->stream);
221
+ $this->stream = null;
222
+ }
223
+
224
+ public function __destruct()
225
+ {
226
+ if(is_resource($this->stream)) {
227
+ fclose($this->stream);
228
+ $this->stream = null;
229
+ }
230
+ if($this->_cleanup) {
231
+ @unlink($this->stream_name);
232
+ }
233
+ }
234
+
235
+ }
app/libs/Microsoft/Uri.php ADDED
@@ -0,0 +1,188 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework
4
+ *
5
+ * LICENSE
6
+ *
7
+ * This source file is subject to the new BSD license that is bundled
8
+ * with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://framework.zend.com/license/new-bsd
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@zend.com so we can send you a copy immediately.
14
+ *
15
+ * @category Microsoft
16
+ * @package Microsoft_Uri
17
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ * @version $Id: Uri.php 18950 2009-11-12 15:37:56Z alexander $
20
+ */
21
+
22
+ /**
23
+ * Abstract class for all Microsoft_Uri handlers
24
+ *
25
+ * @category Microsoft
26
+ * @package Microsoft_Uri
27
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
28
+ * @license http://framework.zend.com/license/new-bsd New BSD License
29
+ */
30
+ abstract class Microsoft_Uri
31
+ {
32
+ /**
33
+ * Scheme of this URI (http, ftp, etc.)
34
+ *
35
+ * @var string
36
+ */
37
+ protected $_scheme = '';
38
+
39
+ /**
40
+ * Global configuration array
41
+ *
42
+ * @var array
43
+ */
44
+ static protected $_config = array(
45
+ 'allow_unwise' => false
46
+ );
47
+
48
+ /**
49
+ * Return a string representation of this URI.
50
+ *
51
+ * @see getUri()
52
+ * @return string
53
+ */
54
+ public function __toString()
55
+ {
56
+ return $this->getUri();
57
+ }
58
+
59
+ /**
60
+ * Convenience function, checks that a $uri string is well-formed
61
+ * by validating it but not returning an object. Returns TRUE if
62
+ * $uri is a well-formed URI, or FALSE otherwise.
63
+ *
64
+ * @param string $uri The URI to check
65
+ * @return boolean
66
+ */
67
+ public static function check($uri)
68
+ {
69
+ try {
70
+ $uri = self::factory($uri);
71
+ } catch (Exception $e) {
72
+ return false;
73
+ }
74
+
75
+ return $uri->valid();
76
+ }
77
+
78
+ /**
79
+ * Create a new Microsoft_Uri object for a URI. If building a new URI, then $uri should contain
80
+ * only the scheme (http, ftp, etc). Otherwise, supply $uri with the complete URI.
81
+ *
82
+ * @param string $uri The URI form which a Microsoft_Uri instance is created
83
+ * @throws Microsoft_Uri_Exception When an empty string was supplied for the scheme
84
+ * @throws Microsoft_Uri_Exception When an illegal scheme is supplied
85
+ * @throws Microsoft_Uri_Exception When the scheme is not supported
86
+ * @return Microsoft_Uri
87
+ * @link http://www.faqs.org/rfcs/rfc2396.html
88
+ */
89
+ public static function factory($uri = 'http')
90
+ {
91
+ // Separate the scheme from the scheme-specific parts
92
+ $uri = explode(':', $uri, 2);
93
+ $scheme = strtolower($uri[0]);
94
+ $schemeSpecific = isset($uri[1]) === true ? $uri[1] : '';
95
+
96
+ if (strlen($scheme) === 0) {
97
+ require_once 'Microsoft/Uri/Exception.php';
98
+ throw new Microsoft_Uri_Exception('An empty string was supplied for the scheme');
99
+ }
100
+
101
+ // Security check: $scheme is used to load a class file, so only alphanumerics are allowed.
102
+ if (ctype_alnum($scheme) === false) {
103
+ require_once 'Microsoft/Uri/Exception.php';
104
+ throw new Microsoft_Uri_Exception('Illegal scheme supplied, only alphanumeric characters are permitted');
105
+ }
106
+
107
+ /**
108
+ * Create a new Microsoft_Uri object for the $uri. If a subclass of Microsoft_Uri exists for the
109
+ * scheme, return an instance of that class. Otherwise, a Microsoft_Uri_Exception is thrown.
110
+ */
111
+ switch ($scheme) {
112
+ case 'http':
113
+ // Break intentionally omitted
114
+ case 'https':
115
+ $className = 'Microsoft_Uri_Http';
116
+ break;
117
+
118
+ case 'mailto':
119
+ // TODO
120
+ default:
121
+ require_once 'Microsoft/Uri/Exception.php';
122
+ throw new Microsoft_Uri_Exception("Scheme \"$scheme\" is not supported");
123
+ break;
124
+ }
125
+
126
+ if (!class_exists($className)) {
127
+ require_once str_replace('_', '/', $className) . '.php';
128
+ }
129
+ $schemeHandler = new $className($scheme, $schemeSpecific);
130
+
131
+ return $schemeHandler;
132
+ }
133
+
134
+ /**
135
+ * Get the URI's scheme
136
+ *
137
+ * @return string|false Scheme or false if no scheme is set.
138
+ */
139
+ public function getScheme()
140
+ {
141
+ if (empty($this->_scheme) === false) {
142
+ return $this->_scheme;
143
+ } else {
144
+ return false;
145
+ }
146
+ }
147
+
148
+ /**
149
+ * Set global configuration options
150
+ *
151
+ * @param Microsoft_Config|array $config
152
+ */
153
+ static public function setConfig($config)
154
+ {
155
+ if ($config instanceof Microsoft_Config) {
156
+ $config = $config->toArray();
157
+ } elseif (!is_array($config)) {
158
+ throw new Microsoft_Uri_Exception("Config must be an array or an instance of Microsoft_Config.");
159
+ }
160
+
161
+ foreach ($config as $k => $v) {
162
+ self::$_config[$k] = $v;
163
+ }
164
+ }
165
+
166
+ /**
167
+ * Microsoft_Uri and its subclasses cannot be instantiated directly.
168
+ * Use Microsoft_Uri::factory() to return a new Microsoft_Uri object.
169
+ *
170
+ * @param string $scheme The scheme of the URI
171
+ * @param string $schemeSpecific The scheme-specific part of the URI
172
+ */
173
+ abstract protected function __construct($scheme, $schemeSpecific = '');
174
+
175
+ /**
176
+ * Return a string representation of this URI.
177
+ *
178
+ * @return string
179
+ */
180
+ abstract public function getUri();
181
+
182
+ /**
183
+ * Returns TRUE if this URI is valid, or FALSE otherwise.
184
+ *
185
+ * @return boolean
186
+ */
187
+ abstract public function valid();
188
+ }
app/libs/Microsoft/Uri/Exception.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework
4
+ *
5
+ * LICENSE
6
+ *
7
+ * This source file is subject to the new BSD license that is bundled
8
+ * with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://framework.zend.com/license/new-bsd
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@zend.com so we can send you a copy immediately.
14
+ *
15
+ * @category Microsoft
16
+ * @package Microsoft_Uri
17
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ * @version $Id: Exception.php 16208 2009-06-21 19:19:26Z thomas $
20
+ */
21
+
22
+ /**
23
+ * @see Microsoft_Exception
24
+ */
25
+ require_once 'Microsoft/Exception.php';
26
+
27
+ /**
28
+ * Exceptions for Microsoft_Uri
29
+ *
30
+ * @category Microsoft
31
+ * @package Microsoft_Uri
32
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
33
+ * @license http://framework.zend.com/license/new-bsd New BSD License
34
+ */
35
+ class Microsoft_Uri_Exception extends Microsoft_Exception
36
+ {
37
+ }
app/libs/Microsoft/Uri/Http.php ADDED
@@ -0,0 +1,761 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zend Framework
4
+ *
5
+ * LICENSE
6
+ *
7
+ * This source file is subject to the new BSD license that is bundled
8
+ * with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://framework.zend.com/license/new-bsd
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@zend.com so we can send you a copy immediately.
14
+ *
15
+ * @category Microsoft
16
+ * @package Microsoft_Uri
17
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ * @version $Id: Http.php 19041 2009-11-19 15:19:07Z sgehrig $
20
+ */
21
+
22
+ /**
23
+ * @see Microsoft_Uri
24
+ */
25
+ require_once 'Microsoft/Uri.php';
26
+
27
+ /**
28
+ * HTTP(S) URI handler
29
+ *
30
+ * @category Microsoft
31
+ * @package Microsoft_Uri
32
+ * @uses Microsoft_Uri
33
+ * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class Microsoft_Uri_Http extends Microsoft_Uri
37
+ {
38
+ /**
39
+ * Character classes for validation regular expressions
40
+ */
41
+ const CHAR_ALNUM = 'A-Za-z0-9';
42
+ const CHAR_MARK = '-_.!~*\'()\[\]';
43
+ const CHAR_RESERVED = ';\/?:@&=+$,';
44
+ const CHAR_SEGMENT = ':@&=+$,;';
45
+ const CHAR_UNWISE = '{}|\\\\^`';
46
+
47
+ /**
48
+ * HTTP username
49
+ *
50
+ * @var string
51
+ */
52
+ protected $_username = '';
53
+
54
+ /**
55
+ * HTTP password
56
+ *
57
+ * @var string
58
+ */
59
+ protected $_password = '';
60
+
61
+ /**
62
+ * HTTP host
63
+ *
64
+ * @var string
65
+ */
66
+ protected $_host = '';
67
+
68
+ /**
69
+ * HTTP post
70
+ *
71
+ * @var string
72
+ */
73
+ protected $_port = '';
74
+
75
+ /**
76
+ * HTTP part
77
+ *
78
+ * @var string
79
+ */
80
+ protected $_path = '';
81
+
82
+ /**
83
+ * HTTP query
84
+ *
85
+ * @var string
86
+ */
87
+ protected $_query = '';
88
+
89
+ /**
90
+ * HTTP fragment
91
+ *
92
+ * @var string
93
+ */
94
+ protected $_fragment = '';
95
+
96
+ /**
97
+ * Regular expression grammar rules for validation; values added by constructor
98
+ *
99
+ * @var array
100
+ */
101
+ protected $_regex = array();
102
+
103
+ /**
104
+ * Constructor accepts a string $scheme (e.g., http, https) and a scheme-specific part of the URI
105
+ * (e.g., example.com/path/to/resource?query=param#fragment)
106
+ *
107
+ * @param string $scheme The scheme of the URI
108
+ * @param string $schemeSpecific The scheme-specific part of the URI
109
+ * @throws Microsoft_Uri_Exception When the URI is not valid
110
+ */
111
+ protected function __construct($scheme, $schemeSpecific = '')
112
+ {
113
+ // Set the scheme
114
+ $this->_scheme = $scheme;
115
+
116
+ // Set up grammar rules for validation via regular expressions. These
117
+ // are to be used with slash-delimited regular expression strings.
118
+
119
+ // Escaped special characters (eg. '%25' for '%')
120
+ $this->_regex['escaped'] = '%[[:xdigit:]]{2}';
121
+
122
+ // Unreserved characters
123
+ $this->_regex['unreserved'] = '[' . self::CHAR_ALNUM . self::CHAR_MARK . ']';
124
+
125
+ // Segment can use escaped, unreserved or a set of additional chars
126
+ $this->_regex['segment'] = '(?:' . $this->_regex['escaped'] . '|[' .
127
+ self::CHAR_ALNUM . self::CHAR_MARK . self::CHAR_SEGMENT . '])*';
128
+
129
+ // Path can be a series of segmets char strings seperated by '/'
130
+ $this->_regex['path'] = '(?:\/(?:' . $this->_regex['segment'] . ')?)+';
131
+
132
+ // URI characters can be escaped, alphanumeric, mark or reserved chars
133
+ $this->_regex['uric'] = '(?:' . $this->_regex['escaped'] . '|[' .
134
+ self::CHAR_ALNUM . self::CHAR_MARK . self::CHAR_RESERVED .
135
+
136
+ // If unwise chars are allowed, add them to the URI chars class
137
+ (self::$_config['allow_unwise'] ? self::CHAR_UNWISE : '') . '])';
138
+
139
+ // If no scheme-specific part was supplied, the user intends to create
140
+ // a new URI with this object. No further parsing is required.
141
+ if (strlen($schemeSpecific) === 0) {
142
+ return;
143
+ }
144
+
145
+ // Parse the scheme-specific URI parts into the instance variables.
146
+ $this->_parseUri($schemeSpecific);
147
+
148
+ // Validate the URI
149
+ if ($this->valid() === false) {
150
+ require_once 'Microsoft/Uri/Exception.php';
151
+ throw new Microsoft_Uri_Exception('Invalid URI supplied');
152
+ }
153
+ }
154
+
155
+ /**
156
+ * Creates a Microsoft_Uri_Http from the given string
157
+ *
158
+ * @param string $uri String to create URI from, must start with
159
+ * 'http://' or 'https://'
160
+ * @throws InvalidArgumentException When the given $uri is not a string or
161
+ * does not start with http:// or https://
162
+ * @throws Microsoft_Uri_Exception When the given $uri is invalid
163
+ * @return Microsoft_Uri_Http
164
+ */
165
+ public static function fromString($uri)
166
+ {
167
+ if (is_string($uri) === false) {
168
+ require_once 'Microsoft/Uri/Exception.php';
169
+ throw new Microsoft_Uri_Exception('$uri is not a string');
170
+ }
171
+
172
+ $uri = explode(':', $uri, 2);
173
+ $scheme = strtolower($uri[0]);
174
+ $schemeSpecific = isset($uri[1]) === true ? $uri[1] : '';
175
+
176
+ if (in_array($scheme, array('http', 'https')) === false) {
177
+ require_once 'Microsoft/Uri/Exception.php';
178
+ throw new Microsoft_Uri_Exception("Invalid scheme: '$scheme'");
179
+ }
180
+
181
+ $schemeHandler = new Microsoft_Uri_Http($scheme, $schemeSpecific);
182
+ return $schemeHandler;
183
+ }
184
+
185
+ /**
186
+ * Parse the scheme-specific portion of the URI and place its parts into instance variables.
187
+ *
188
+ * @param string $schemeSpecific The scheme-specific portion to parse
189
+ * @throws Microsoft_Uri_Exception When scheme-specific decoposition fails
190
+ * @throws Microsoft_Uri_Exception When authority decomposition fails
191
+ * @return void
192
+ */
193
+ protected function _parseUri($schemeSpecific)
194
+ {
195
+ // High-level decomposition parser
196
+ $pattern = '~^((//)([^/?#]*))([^?#]*)(\?([^#]*))?(#(.*))?$~';
197
+ $status = @preg_match($pattern, $schemeSpecific, $matches);
198
+ if ($status === false) {
199
+ require_once 'Microsoft/Uri/Exception.php';
200
+ throw new Microsoft_Uri_Exception('Internal error: scheme-specific decomposition failed');
201
+ }
202
+
203
+ // Failed decomposition; no further processing needed
204
+ if ($status === false) {
205
+ return;
206
+ }
207
+
208
+ // Save URI components that need no further decomposition
209
+ $this->_path = isset($matches[4]) === true ? $matches[4] : '';
210
+ $this->_query = isset($matches[6]) === true ? $matches[6] : '';
211
+ $this->_fragment = isset($matches[8]) === true ? $matches[8] : '';
212
+
213
+ // Additional decomposition to get username, password, host, and port
214
+ $combo = isset($matches[3]) === true ? $matches[3] : '';
215
+ $pattern = '~^(([^:@]*)(:([^@]*))?@)?([^:]+)(:(.*))?$~';
216
+ $status = @preg_match($pattern, $combo, $matches);
217
+ if ($status === false) {
218
+ require_once 'Microsoft/Uri/Exception.php';
219
+ throw new Microsoft_Uri_Exception('Internal error: authority decomposition failed');
220
+ }
221
+
222
+ // Failed decomposition; no further processing needed
223
+ if ($status === false) {
224
+ return;
225
+ }
226
+
227
+ // Save remaining URI components
228
+ $this->_username = isset($matches[2]) === true ? $matches[2] : '';
229
+ $this->_password = isset($matches[4]) === true ? $matches[4] : '';
230
+ $this->_host = isset($matches[5]) === true ? $matches[5] : '';
231
+ $this->_port = isset($matches[7]) === true ? $matches[7] : '';
232
+
233
+ }
234
+
235
+ /**
236
+ * Returns a URI based on current values of the instance variables. If any
237
+ * part of the URI does not pass validation, then an exception is thrown.
238
+ *
239
+ * @throws Microsoft_Uri_Exception When one or more parts of the URI are invalid
240
+ * @return string
241
+ */
242
+ public function getUri()
243
+ {
244
+ if ($this->valid() === false) {
245
+ require_once 'Microsoft/Uri/Exception.php';
246
+ throw new Microsoft_Uri_Exception('One or more parts of the URI are invalid');
247
+ }
248
+
249
+ $password = strlen($this->_password) > 0 ? ":$this->_password" : '';
250
+ $auth = strlen($this->_username) > 0 ? "$this->_username$password@" : '';
251
+ $port = strlen($this->_port) > 0 ? ":$this->_port" : '';
252
+ $query = strlen($this->_query) > 0 ? "?$this->_query" : '';
253
+ $fragment = strlen($this->_fragment) > 0 ? "#$this->_fragment" : '';
254
+
255
+ return $this->_scheme
256
+ . '://'
257
+ . $auth
258
+ . $this->_host
259
+ . $port
260
+ . $this->_path
261
+ . $query
262
+ . $fragment;
263
+ }
264
+
265
+ /**
266
+ * Validate the current URI from the instance variables. Returns true if and only if all
267
+ * parts pass validation.
268
+ *
269
+ * @return boolean
270
+ */
271
+ public function valid()
272
+ {
273
+ // Return true if and only if all parts of the URI have passed validation
274
+ return $this->validateUsername()
275
+ and $this->validatePassword()
276
+ and $this->validateHost()
277
+ and $this->validatePort()
278
+ and $this->validatePath()
279
+ and $this->validateQuery()
280
+ and $this->validateFragment();
281
+ }
282
+
283
+ /**
284
+ * Returns the username portion of the URL, or FALSE if none.
285
+ *
286
+ * @return string
287
+ */
288
+ public function getUsername()
289
+ {
290
+ return strlen($this->_username) > 0 ? $this->_username : false;
291
+ }
292
+
293
+ /**
294
+ * Returns true if and only if the username passes validation. If no username is passed,
295
+ * then the username contained in the instance variable is used.
296
+ *
297
+ * @param string $username The HTTP username
298
+ * @throws Microsoft_Uri_Exception When username validation fails
299
+ * @return boolean
300
+ * @link http://www.faqs.org/rfcs/rfc2396.html
301
+ */
302
+ public function validateUsername($username = null)
303
+ {
304
+ if ($username === null) {
305
+ $username = $this->_username;
306
+ }
307
+
308
+ // If the username is empty, then it is considered valid
309
+ if (strlen($username) === 0) {
310
+ return true;
311
+ }
312
+
313
+ // Check the username against the allowed values
314
+ $status = @preg_match('/^(?:' . $this->_regex['escaped'] . '|[' .
315
+ self::CHAR_ALNUM . self::CHAR_MARK . ';:&=+$,' . '])+$/', $username);
316
+
317
+ if ($status === false) {
318
+ require_once 'Microsoft/Uri/Exception.php';
319
+ throw new Microsoft_Uri_Exception('Internal error: username validation failed');
320
+ }
321
+
322
+ return $status === 1;
323
+ }
324
+
325
+ /**
326
+ * Sets the username for the current URI, and returns the old username
327
+ *
328
+ * @param string $username The HTTP username
329
+ * @throws Microsoft_Uri_Exception When $username is not a valid HTTP username
330
+ * @return string
331
+ */
332
+ public function setUsername($username)
333
+ {
334
+ if ($this->validateUsername($username) === false) {
335
+ require_once 'Microsoft/Uri/Exception.php';
336
+ throw new Microsoft_Uri_Exception("Username \"$username\" is not a valid HTTP username");
337
+ }
338
+
339
+ $oldUsername = $this->_username;
340
+ $this->_username = $username;
341
+
342
+ return $oldUsername;
343
+ }
344
+
345
+ /**
346
+ * Returns the password portion of the URL, or FALSE if none.
347
+ *
348
+ * @return string
349
+ */
350
+ public function getPassword()
351
+ {
352
+ return strlen($this->_password) > 0 ? $this->_password : false;
353
+ }
354
+
355
+ /**
356
+ * Returns true if and only if the password passes validation. If no password is passed,
357
+ * then the password contained in the instance variable is used.
358
+ *
359
+ * @param string $password The HTTP password
360
+ * @throws Microsoft_Uri_Exception When password validation fails
361
+ * @return boolean
362
+ * @link http://www.faqs.org/rfcs/rfc2396.html
363
+ */
364
+ public function validatePassword($password = null)
365
+ {
366
+ if ($password === null) {
367
+ $password = $this->_password;
368
+ }
369
+
370
+ // If the password is empty, then it is considered valid
371
+ if (strlen($password) === 0) {
372
+ return true;
373
+ }
374
+
375
+ // If the password is nonempty, but there is no username, then it is considered invalid
376
+ if (strlen($password) > 0 and strlen($this->_username) === 0) {
377
+ return false;
378
+ }
379
+
380
+ // Check the password against the allowed values
381
+ $status = @preg_match('/^(?:' . $this->_regex['escaped'] . '|[' .
382
+ self::CHAR_ALNUM . self::CHAR_MARK . ';:&=+$,' . '])+$/', $password);
383
+
384
+ if ($status === false) {
385
+ require_once 'Microsoft/Uri/Exception.php';
386
+ throw new Microsoft_Uri_Exception('Internal error: password validation failed.');
387
+ }
388
+
389
+ return $status == 1;
390
+ }
391
+
392
+ /**
393
+ * Sets the password for the current URI, and returns the old password
394
+ *
395
+ * @param string $password The HTTP password
396
+ * @throws Microsoft_Uri_Exception When $password is not a valid HTTP password
397
+ * @return string
398
+ */
399
+ public function setPassword($password)
400
+ {
401
+ if ($this->validatePassword($password) === false) {
402
+ require_once 'Microsoft/Uri/Exception.php';
403
+ throw new Microsoft_Uri_Exception("Password \"$password\" is not a valid HTTP password.");
404
+ }
405
+
406
+ $oldPassword = $this->_password;
407
+ $this->_password = $password;
408
+
409
+ return $oldPassword;
410
+ }
411
+
412
+ /**
413
+ * Returns the domain or host IP portion of the URL, or FALSE if none.
414
+ *
415
+ * @return string
416
+ */
417
+ public function getHost()
418
+ {
419
+ return strlen($this->_host) > 0 ? $this->_host : false;
420
+ }
421
+
422
+ /**
423
+ * Returns true if and only if the host string passes validation. If no host is passed,
424
+ * then the host contained in the instance variable is used.
425
+ *
426
+ * @param string $host The HTTP host
427
+ * @return boolean
428
+ * @uses Microsoft_Filter
429
+ */
430
+ public function validateHost($host = null)
431
+ {
432
+ if ($host === null) {
433
+ $host = $this->_host;
434
+ }
435
+
436
+ // If the host is empty, then it is considered invalid
437
+ if (strlen($host) === 0) {
438
+ return false;
439
+ }
440
+
441
+ return true;
442
+ }
443
+
444
+ /**
445
+ * Sets the host for the current URI, and returns the old host
446
+ *
447
+ * @param string $host The HTTP host
448
+ * @throws Microsoft_Uri_Exception When $host is nota valid HTTP host
449
+ * @return string
450
+ */
451
+ public function setHost($host)
452
+ {
453
+ if ($this->validateHost($host) === false) {
454
+ require_once 'Microsoft/Uri/Exception.php';
455
+ throw new Microsoft_Uri_Exception("Host \"$host\" is not a valid HTTP host");
456
+ }
457
+
458
+ $oldHost = $this->_host;
459
+ $this->_host = $host;
460
+
461
+ return $oldHost;
462
+ }
463
+
464
+ /**
465
+ * Returns the TCP port, or FALSE if none.
466
+ *
467
+ * @return string
468
+ */
469
+ public function getPort()
470
+ {
471
+ return strlen($this->_port) > 0 ? $this->_port : false;
472
+ }
473
+
474
+ /**
475
+ * Returns true if and only if the TCP port string passes validation. If no port is passed,
476
+ * then the port contained in the instance variable is used.
477
+ *
478
+ * @param string $port The HTTP port
479
+ * @return boolean
480
+ */
481
+ public function validatePort($port = null)
482
+ {
483
+ if ($port === null) {
484
+ $port = $this->_port;
485
+ }
486
+
487
+ // If the port is empty, then it is considered valid
488
+ if (strlen($port) === 0) {
489
+ return true;
490
+ }
491
+
492
+ // Check the port against the allowed values
493
+ return ctype_digit((string) $port) and 1 <= $port and $port <= 65535;
494
+ }
495
+
496
+ /**
497
+ * Sets the port for the current URI, and returns the old port
498
+ *
499
+ * @param string $port The HTTP port
500
+ * @throws Microsoft_Uri_Exception When $port is not a valid HTTP port
501
+ * @return string
502
+ */
503
+ public function setPort($port)
504
+ {
505
+ if ($this->validatePort($port) === false) {
506
+ require_once 'Microsoft/Uri/Exception.php';
507
+ throw new Microsoft_Uri_Exception("Port \"$port\" is not a valid HTTP port.");
508
+ }
509
+
510
+ $oldPort = $this->_port;
511
+ $this->_port = $port;
512
+
513
+ return $oldPort;
514
+ }
515
+
516
+ /**
517
+ * Returns the path and filename portion of the URL, or FALSE if none.
518
+ *
519
+ * @return string
520
+ */
521
+ public function getPath()
522
+ {
523
+ return strlen($this->_path) > 0 ? $this->_path : '/';
524
+ }
525
+
526
+ /**
527
+ * Returns true if and only if the path string passes validation. If no path is passed,
528
+ * then the path contained in the instance variable is used.
529
+ *
530
+ * @param string $path The HTTP path
531
+ * @throws Microsoft_Uri_Exception When path validation fails
532
+ * @return boolean
533
+ */
534
+ public function validatePath($path = null)
535
+ {
536
+ if ($path === null) {
537
+ $path = $this->_path;
538
+ }
539
+
540
+ // If the path is empty, then it is considered valid
541
+ if (strlen($path) === 0) {
542
+ return true;
543
+ }
544
+
545
+ // Determine whether the path is well-formed
546
+ $pattern = '/^' . $this->_regex['path'] . '$/';
547
+ $status = @preg_match($pattern, $path);
548
+ if ($status === false) {
549
+ require_once 'Microsoft/Uri/Exception.php';
550
+ throw new Microsoft_Uri_Exception('Internal error: path validation failed');
551
+ }
552
+
553
+ return (boolean) $status;
554
+ }
555
+
556
+ /**
557
+ * Sets the path for the current URI, and returns the old path
558
+ *
559
+ * @param string $path The HTTP path
560
+ * @throws Microsoft_Uri_Exception When $path is not a valid HTTP path
561
+ * @return string
562
+ */
563
+ public function setPath($path)
564
+ {
565
+ if ($this->validatePath($path) === false) {
566
+ require_once 'Microsoft/Uri/Exception.php';
567
+ throw new Microsoft_Uri_Exception("Path \"$path\" is not a valid HTTP path");
568
+ }
569
+
570
+ $oldPath = $this->_path;
571
+ $this->_path = $path;
572
+
573
+ return $oldPath;
574
+ }
575
+
576
+ /**
577
+ * Returns the query portion of the URL (after ?), or FALSE if none.
578
+ *
579
+ * @return string
580
+ */
581
+ public function getQuery()
582
+ {
583
+ return strlen($this->_query) > 0 ? $this->_query : false;
584
+ }
585
+
586
+ /**
587
+ * Returns the query portion of the URL (after ?) as a
588
+ * key-value-array. If the query is empty an empty array
589
+ * is returned
590
+ *
591
+ * @return array
592
+ */
593
+ public function getQueryAsArray()
594
+ {
595
+ $query = $this->getQuery();
596
+ $querryArray = array();
597
+ if ($query !== false) {
598
+ parse_str($query, $querryArray);
599
+ }
600
+ return $querryArray;
601
+ }
602
+
603
+ /**
604
+ * Returns true if and only if the query string passes validation. If no query is passed,
605
+ * then the query string contained in the instance variable is used.
606
+ *
607
+ * @param string $query The query to validate
608
+ * @throws Microsoft_Uri_Exception When query validation fails
609
+ * @return boolean
610
+ * @link http://www.faqs.org/rfcs/rfc2396.html
611
+ */
612
+ public function validateQuery($query = null)
613
+ {
614
+ if ($query === null) {
615
+ $query = $this->_query;
616
+ }
617
+
618
+ // If query is empty, it is considered to be valid
619
+ if (strlen($query) === 0) {
620
+ return true;
621
+ }
622
+
623
+ // Determine whether the query is well-formed
624
+ $pattern = '/^' . $this->_regex['uric'] . '*$/';
625
+ $status = @preg_match($pattern, $query);
626
+ if ($status === false) {
627
+ require_once 'Microsoft/Uri/Exception.php';
628
+ throw new Microsoft_Uri_Exception('Internal error: query validation failed');
629
+ }
630
+
631
+ return $status == 1;
632
+ }
633
+
634
+ /**
635
+ * Add or replace params in the query string for the current URI, and
636
+ * return the old query.
637
+ *
638
+ * @param array $queryParams
639
+ * @return string Old query string
640
+ */
641
+ public function addReplaceQueryParameters(array $queryParams)
642
+ {
643
+ $queryParams = array_merge($this->getQueryAsArray(), $queryParams);
644
+ return $this->setQuery($queryParams);
645
+ }
646
+
647
+ /**
648
+ * Remove params in the query string for the current URI, and
649
+ * return the old query.
650
+ *
651
+ * @param array $queryParamKeys
652
+ * @return string Old query string
653
+ */
654
+ public function removeQueryParameters(array $queryParamKeys)
655
+ {
656
+ $queryParams = array_diff_key($this->getQueryAsArray(), array_fill_keys($queryParamKeys, 0));
657
+ return $this->setQuery($queryParams);
658
+ }
659
+
660
+ /**
661
+ * Set the query string for the current URI, and return the old query
662
+ * string This method accepts both strings and arrays.
663
+ *
664
+ * @param string|array $query The query string or array
665
+ * @throws Microsoft_Uri_Exception When $query is not a valid query string
666
+ * @return string Old query string
667
+ */
668
+ public function setQuery($query)
669
+ {
670
+ $oldQuery = $this->_query;
671
+
672
+ // If query is empty, set an empty string
673
+ if (empty($query) === true) {
674
+ $this->_query = '';
675
+ return $oldQuery;
676
+ }
677
+
678
+ // If query is an array, make a string out of it
679
+ if (is_array($query) === true) {
680
+ $query = http_build_query($query, '', '&');
681
+ } else {
682
+ // If it is a string, make sure it is valid. If not parse and encode it
683
+ $query = (string) $query;
684
+ if ($this->validateQuery($query) === false) {
685
+ parse_str($query, $queryArray);
686
+ $query = http_build_query($queryArray, '', '&');
687
+ }
688
+ }
689
+
690
+ // Make sure the query is valid, and set it
691
+ if ($this->validateQuery($query) === false) {
692
+ require_once 'Microsoft/Uri/Exception.php';
693
+ throw new Microsoft_Uri_Exception("'$query' is not a valid query string");
694
+ }
695
+
696
+ $this->_query = $query;
697
+
698
+ return $oldQuery;
699
+ }
700
+
701
+ /**
702
+ * Returns the fragment portion of the URL (after #), or FALSE if none.
703
+ *
704
+ * @return string|false
705
+ */
706
+ public function getFragment()
707
+ {
708
+ return strlen($this->_fragment) > 0 ? $this->_fragment : false;
709
+ }
710
+
711
+ /**
712
+ * Returns true if and only if the fragment passes validation. If no fragment is passed,
713
+ * then the fragment contained in the instance variable is used.
714
+ *
715
+ * @param string $fragment Fragment of an URI
716
+ * @throws Microsoft_Uri_Exception When fragment validation fails
717
+ * @return boolean
718
+ * @link http://www.faqs.org/rfcs/rfc2396.html
719
+ */
720
+ public function validateFragment($fragment = null)
721
+ {
722
+ if ($fragment === null) {
723
+ $fragment = $this->_fragment;
724
+ }
725
+
726
+ // If fragment is empty, it is considered to be valid
727
+ if (strlen($fragment) === 0) {
728
+ return true;
729
+ }
730
+
731
+ // Determine whether the fragment is well-formed
732
+ $pattern = '/^' . $this->_regex['uric'] . '*$/';
733
+ $status = @preg_match($pattern, $fragment);
734
+ if ($status === false) {
735
+ require_once 'Microsoft/Uri/Exception.php';
736
+ throw new Microsoft_Uri_Exception('Internal error: fragment validation failed');
737
+ }
738
+
739
+ return (boolean) $status;
740
+ }
741
+
742
+ /**
743
+ * Sets the fragment for the current URI, and returns the old fragment
744
+ *
745
+ * @param string $fragment Fragment of the current URI
746
+ * @throws Microsoft_Uri_Exception When $fragment is not a valid HTTP fragment
747
+ * @return string
748
+ */
749
+ public function setFragment($fragment)
750
+ {
751
+ if ($this->validateFragment($fragment) === false) {
752
+ require_once 'Microsoft/Uri/Exception.php';
753
+ throw new Microsoft_Uri_Exception("Fragment \"$fragment\" is not a valid HTTP fragment");
754
+ }
755
+
756
+ $oldFragment = $this->_fragment;
757
+ $this->_fragment = $fragment;
758
+
759
+ return $oldFragment;
760
+ }
761
+ }
app/libs/Microsoft/WindowsAzure/Credentials/CredentialsAbstract.php ADDED
@@ -0,0 +1,257 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
31
+ * @license http://phpazure.codeplex.com/license
32
+ * @version $Id: SharedKeyCredentials.php 14561 2009-05-07 08:05:12Z unknown $
33
+ */
34
+
35
+ /**
36
+ * @see Microsoft_Http_Client
37
+ */
38
+ require_once 'Microsoft/Http/Client.php';
39
+
40
+ /**
41
+ * @see Microsoft_WindowsAzure_Credentials_Exception
42
+ */
43
+ require_once 'Microsoft/WindowsAzure/Credentials/Exception.php';
44
+
45
+ /**
46
+ * @category Microsoft
47
+ * @package Microsoft_WindowsAzure
48
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
49
+ * @license http://phpazure.codeplex.com/license
50
+ */
51
+ abstract class Microsoft_WindowsAzure_Credentials_CredentialsAbstract
52
+ {
53
+ /**
54
+ * Development storage account and key
55
+ */
56
+ const DEVSTORE_ACCOUNT = "devstoreaccount1";
57
+ const DEVSTORE_KEY = "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==";
58
+
59
+ /**
60
+ * HTTP header prefixes
61
+ */
62
+ const PREFIX_PROPERTIES = "x-ms-prop-";
63
+ const PREFIX_METADATA = "x-ms-meta-";
64
+ const PREFIX_STORAGE_HEADER = "x-ms-";
65
+
66
+ /**
67
+ * Permissions
68
+ */
69
+ const PERMISSION_READ = "r";
70
+ const PERMISSION_WRITE = "w";
71
+ const PERMISSION_DELETE = "d";
72
+ const PERMISSION_LIST = "l";
73
+
74
+ /**
75
+ * Account name for Windows Azure
76
+ *
77
+ * @var string
78
+ */
79
+ protected $_accountName = '';
80
+
81
+ /**
82
+ * Account key for Windows Azure
83
+ *
84
+ * @var string
85
+ */
86
+ protected $_accountKey = '';
87
+
88
+ /**
89
+ * Use path-style URI's
90
+ *
91
+ * @var boolean
92
+ */
93
+ protected $_usePathStyleUri = false;
94
+
95
+ /**
96
+ * Creates a new Microsoft_WindowsAzure_Credentials_CredentialsAbstract instance
97
+ *
98
+ * @param string $accountName Account name for Windows Azure
99
+ * @param string $accountKey Account key for Windows Azure
100
+ * @param boolean $usePathStyleUri Use path-style URI's
101
+ */
102
+ public function __construct(
103
+ $accountName = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_ACCOUNT,
104
+ $accountKey = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_KEY,
105
+ $usePathStyleUri = false
106
+ ) {
107
+ $this->_accountName = $accountName;
108
+ $this->_accountKey = base64_decode($accountKey);
109
+ $this->_usePathStyleUri = $usePathStyleUri;
110
+ }
111
+
112
+ /**
113
+ * Set account name for Windows Azure
114
+ *
115
+ * @param string $value
116
+ * @return Microsoft_WindowsAzure_Credentials_CredentialsAbstract
117
+ */
118
+ public function setAccountName($value = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_ACCOUNT)
119
+ {
120
+ $this->_accountName = $value;
121
+ return $this;
122
+ }
123
+
124
+ /**
125
+ * Set account key for Windows Azure
126
+ *
127
+ * @param string $value
128
+ * @return Microsoft_WindowsAzure_Credentials_CredentialsAbstract
129
+ */
130
+ public function setAccountkey($value = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_KEY)
131
+ {
132
+ $this->_accountKey = base64_decode($value);
133
+ return $this;
134
+ }
135
+
136
+ /**
137
+ * Set use path-style URI's
138
+ *
139
+ * @param boolean $value
140
+ * @return Microsoft_WindowsAzure_Credentials_CredentialsAbstract
141
+ */
142
+ public function setUsePathStyleUri($value = false)
143
+ {
144
+ $this->_usePathStyleUri = $value;
145
+ return $this;
146
+ }
147
+
148
+ /**
149
+ * Sign request URL with credentials
150
+ *
151
+ * @param string $requestUrl Request URL
152
+ * @param string $resourceType Resource type
153
+ * @param string $requiredPermission Required permission
154
+ * @return string Signed request URL
155
+ */
156
+ abstract public function signRequestUrl(
157
+ $requestUrl = '',
158
+ $resourceType = Microsoft_WindowsAzure_Storage::RESOURCE_UNKNOWN,
159
+ $requiredPermission = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ
160
+ );
161
+
162
+ /**
163
+ * Sign request headers with credentials
164
+ *
165
+ * @param string $httpVerb HTTP verb the request will use
166
+ * @param string $path Path for the request
167
+ * @param string $queryString Query string for the request
168
+ * @param array $headers x-ms headers to add
169
+ * @param boolean $forTableStorage Is the request for table storage?
170
+ * @param string $resourceType Resource type
171
+ * @param string $requiredPermission Required permission
172
+ * @param mixed $rawData Raw post data
173
+ * @return array Array of headers
174
+ */
175
+ abstract public function signRequestHeaders(
176
+ $httpVerb = Microsoft_Http_Client::GET,
177
+ $path = '/',
178
+ $queryString = '',
179
+ $headers = null,
180
+ $forTableStorage = false,
181
+ $resourceType = Microsoft_WindowsAzure_Storage::RESOURCE_UNKNOWN,
182
+ $requiredPermission = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ,
183
+ $rawData = null
184
+ );
185
+
186
+
187
+ /**
188
+ * Prepare query string for signing
189
+ *
190
+ * @param string $value Original query string
191
+ * @return string Query string for signing
192
+ */
193
+ protected function _prepareQueryStringForSigning($value)
194
+ {
195
+ // Return value
196
+ $returnValue = array();
197
+
198
+ // Prepare query string
199
+ $queryParts = $this->_makeArrayOfQueryString($value);
200
+ foreach ($queryParts as $key => $value) {
201
+ $returnValue[] = $key . '=' . $value;
202
+ }
203
+
204
+ // Return
205
+ if (count($returnValue) > 0) {
206
+ return '?' . implode('&', $returnValue);
207
+ } else {
208
+ return '';
209
+ }
210
+ }
211
+
212
+ /**
213
+ * Make array of query string
214
+ *
215
+ * @param string $value Query string
216
+ * @return array Array of key/value pairs
217
+ */
218
+ protected function _makeArrayOfQueryString($value)
219
+ {
220
+ // Returnvalue
221
+ $returnValue = array();
222
+
223
+ // Remove front ?
224
+ if (strlen($value) > 0 && strpos($value, '?') === 0) {
225
+ $value = substr($value, 1);
226
+ }
227
+
228
+ // Split parts
229
+ $queryParts = explode('&', $value);
230
+ foreach ($queryParts as $queryPart) {
231
+ $queryPart = explode('=', $queryPart, 2);
232
+
233
+ if ($queryPart[0] != '') {
234
+ $returnValue[ $queryPart[0] ] = isset($queryPart[1]) ? $queryPart[1] : '';
235
+ }
236
+ }
237
+
238
+ // Sort
239
+ ksort($returnValue);
240
+
241
+ // Return
242
+ return $returnValue;
243
+ }
244
+
245
+ /**
246
+ * Returns an array value if the key is set, otherwide returns $valueIfNotSet
247
+ *
248
+ * @param array $array
249
+ * @param mixed $key
250
+ * @param mixed $valueIfNotSet
251
+ * @return mixed
252
+ */
253
+ protected function _issetOr($array, $key, $valueIfNotSet)
254
+ {
255
+ return isset($array[$key]) ? $array[$key] : $valueIfNotSet;
256
+ }
257
+ }
app/libs/Microsoft/WindowsAzure/Credentials/Exception.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Exception
31
+ * @version $Id: Exception.php 28585 2009-09-07 12:12:56Z unknown $
32
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
33
+ * @license http://phpazure.codeplex.com/license
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Exception.php';
40
+
41
+ /**
42
+ * @category Microsoft
43
+ * @package Microsoft_WindowsAzure
44
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
45
+ * @license http://phpazure.codeplex.com/license
46
+ */
47
+ class Microsoft_WindowsAzure_Credentials_Exception extends Microsoft_WindowsAzure_Exception
48
+ {}
app/libs/Microsoft/WindowsAzure/Credentials/SharedAccessSignature.php ADDED
@@ -0,0 +1,320 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
31
+ * @license http://phpazure.codeplex.com/license
32
+ * @version $Id: SharedKeyCredentials.php 24305 2009-07-23 06:30:04Z unknown $
33
+ */
34
+
35
+ /**
36
+ * @see Microsoft_WindowsAzure_Credentials_CredentialsAbstract
37
+ */
38
+ require_once 'Microsoft/WindowsAzure/Credentials/CredentialsAbstract.php';
39
+
40
+ /**
41
+ * @see Microsoft_WindowsAzure_Storage
42
+ */
43
+ require_once 'Microsoft/WindowsAzure/Storage.php';
44
+
45
+ /**
46
+ * @see Microsoft_Http_Client
47
+ */
48
+ require_once 'Microsoft/Http/Client.php';
49
+
50
+ /**
51
+ * @category Microsoft
52
+ * @package Microsoft_WindowsAzure
53
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
54
+ * @license http://phpazure.codeplex.com/license
55
+ */
56
+ class Microsoft_WindowsAzure_Credentials_SharedAccessSignature
57
+ extends Microsoft_WindowsAzure_Credentials_CredentialsAbstract
58
+ {
59
+ /**
60
+ * Permission set
61
+ *
62
+ * @var array
63
+ */
64
+ protected $_permissionSet = array();
65
+
66
+ /**
67
+ * Creates a new Microsoft_WindowsAzure_Credentials_SharedAccessSignature instance
68
+ *
69
+ * @param string $accountName Account name for Windows Azure
70
+ * @param string $accountKey Account key for Windows Azure
71
+ * @param boolean $usePathStyleUri Use path-style URI's
72
+ * @param array $permissionSet Permission set
73
+ */
74
+ public function __construct(
75
+ $accountName = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_ACCOUNT,
76
+ $accountKey = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_KEY,
77
+ $usePathStyleUri = false, $permissionSet = array()
78
+ ) {
79
+ parent::__construct($accountName, $accountKey, $usePathStyleUri);
80
+ $this->_permissionSet = $permissionSet;
81
+ }
82
+
83
+ /**
84
+ * Get permission set
85
+ *
86
+ * @return array
87
+ */
88
+ public function getPermissionSet()
89
+ {
90
+ return $this->_permissionSet;
91
+ }
92
+
93
+ /**
94
+ * Set permisison set
95
+ *
96
+ * Warning: fine-grained permissions should be added prior to coarse-grained permissions.
97
+ * For example: first add blob permissions, end with container-wide permissions.
98
+ *
99
+ * Warning: the signed access signature URL must match the account name of the
100
+ * Microsoft_WindowsAzure_Credentials_Microsoft_WindowsAzure_Credentials_SharedAccessSignature instance
101
+ *
102
+ * @param array $value Permission set
103
+ * @return void
104
+ */
105
+ public function setPermissionSet($value = array())
106
+ {
107
+ foreach ($value as $url) {
108
+ if (strpos($url, $this->_accountName) === false) {
109
+ throw new Microsoft_WindowsAzure_Exception('The permission set can only contain URLs for the account name specified in the Microsoft_WindowsAzure_Credentials_SharedAccessSignature instance.');
110
+ }
111
+ }
112
+ $this->_permissionSet = $value;
113
+ }
114
+
115
+ /**
116
+ * Create signature
117
+ *
118
+ * @param string $path Path for the request
119
+ * @param string $resource Signed resource - container (c) - blob (b)
120
+ * @param string $permissions Signed permissions - read (r), write (w), delete (d) and list (l)
121
+ * @param string $start The time at which the Shared Access Signature becomes valid.
122
+ * @param string $expiry The time at which the Shared Access Signature becomes invalid.
123
+ * @param string $identifier Signed identifier
124
+ * @return string
125
+ */
126
+ public function createSignature(
127
+ $path = '/',
128
+ $resource = 'b',
129
+ $permissions = 'r',
130
+ $start = '',
131
+ $expiry = '',
132
+ $identifier = ''
133
+ ) {
134
+ // Determine path
135
+ if ($this->_usePathStyleUri) {
136
+ $path = substr($path, strpos($path, '/'));
137
+ }
138
+
139
+ // Add trailing slash to $path
140
+ if (substr($path, 0, 1) !== '/') {
141
+ $path = '/' . $path;
142
+ }
143
+
144
+ // Build canonicalized resource string
145
+ $canonicalizedResource = '/' . $this->_accountName;
146
+ /*if ($this->_usePathStyleUri) {
147
+ $canonicalizedResource .= '/' . $this->_accountName;
148
+ }*/
149
+ $canonicalizedResource .= $path;
150
+
151
+ // Create string to sign
152
+ $stringToSign = array();
153
+ $stringToSign[] = $permissions;
154
+ $stringToSign[] = $start;
155
+ $stringToSign[] = $expiry;
156
+ $stringToSign[] = $canonicalizedResource;
157
+ $stringToSign[] = $identifier;
158
+
159
+ $stringToSign = implode("\n", $stringToSign);
160
+ $signature = base64_encode(hash_hmac('sha256', $stringToSign, $this->_accountKey, true));
161
+
162
+ return $signature;
163
+ }
164
+
165
+ /**
166
+ * Create signed query string
167
+ *
168
+ * @param string $path Path for the request
169
+ * @param string $queryString Query string for the request
170
+ * @param string $resource Signed resource - container (c) - blob (b)
171
+ * @param string $permissions Signed permissions - read (r), write (w), delete (d) and list (l)
172
+ * @param string $start The time at which the Shared Access Signature becomes valid.
173
+ * @param string $expiry The time at which the Shared Access Signature becomes invalid.
174
+ * @param string $identifier Signed identifier
175
+ * @return string
176
+ */
177
+ public function createSignedQueryString(
178
+ $path = '/',
179
+ $queryString = '',
180
+ $resource = 'b',
181
+ $permissions = 'r',
182
+ $start = '',
183
+ $expiry = '',
184
+ $identifier = ''
185
+ ) {
186
+ // Parts
187
+ $parts = array();
188
+ if ($start !== '') {
189
+ $parts[] = 'st=' . urlencode($start);
190
+ }
191
+ $parts[] = 'se=' . urlencode($expiry);
192
+ $parts[] = 'sr=' . $resource;
193
+ $parts[] = 'sp=' . $permissions;
194
+ if ($identifier !== '') {
195
+ $parts[] = 'si=' . urlencode($identifier);
196
+ }
197
+ $parts[] = 'sig=' . urlencode($this->createSignature($path, $resource, $permissions, $start, $expiry, $identifier));
198
+
199
+ // Assemble parts and query string
200
+ if ($queryString != '') {
201
+ $queryString .= '&';
202
+ }
203
+ $queryString .= implode('&', $parts);
204
+
205
+ return $queryString;
206
+ }
207
+
208
+ /**
209
+ * Permission matches request?
210
+ *
211
+ * @param string $permissionUrl Permission URL
212
+ * @param string $requestUrl Request URL
213
+ * @param string $resourceType Resource type
214
+ * @param string $requiredPermission Required permission
215
+ * @return string Signed request URL
216
+ */
217
+ public function permissionMatchesRequest(
218
+ $permissionUrl = '',
219
+ $requestUrl = '',
220
+ $resourceType = Microsoft_WindowsAzure_Storage::RESOURCE_UNKNOWN,
221
+ $requiredPermission = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ
222
+ ) {
223
+ // Build requirements
224
+ $requiredResourceType = $resourceType;
225
+ if ($requiredResourceType == Microsoft_WindowsAzure_Storage::RESOURCE_BLOB) {
226
+ $requiredResourceType .= Microsoft_WindowsAzure_Storage::RESOURCE_CONTAINER;
227
+ }
228
+
229
+ // Parse permission url
230
+ $parsedPermissionUrl = parse_url($permissionUrl);
231
+
232
+ // Parse permission properties
233
+ $permissionParts = explode('&', $parsedPermissionUrl['query']);
234
+
235
+ // Parse request url
236
+ $parsedRequestUrl = parse_url($requestUrl);
237
+
238
+ // Check if permission matches request
239
+ $matches = true;
240
+ foreach ($permissionParts as $part) {
241
+ list($property, $value) = explode('=', $part, 2);
242
+
243
+ if ($property == 'sr') {
244
+ $matches = $matches && (strpbrk($value, $requiredResourceType) !== false);
245
+ }
246
+
247
+ if ($property == 'sp') {
248
+ $matches = $matches && (strpbrk($value, $requiredPermission) !== false);
249
+ }
250
+ }
251
+
252
+ // Ok, but... does the resource match?
253
+ $matches = $matches && (strpos($parsedRequestUrl['path'], $parsedPermissionUrl['path']) !== false);
254
+
255
+ // Return
256
+ return $matches;
257
+ }
258
+
259
+ /**
260
+ * Sign request URL with credentials
261
+ *
262
+ * @param string $requestUrl Request URL
263
+ * @param string $resourceType Resource type
264
+ * @param string $requiredPermission Required permission
265
+ * @return string Signed request URL
266
+ */
267
+ public function signRequestUrl(
268
+ $requestUrl = '',
269
+ $resourceType = Microsoft_WindowsAzure_Storage::RESOURCE_UNKNOWN,
270
+ $requiredPermission = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ
271
+ ) {
272
+ // Look for a matching permission
273
+ foreach ($this->getPermissionSet() as $permittedUrl) {
274
+ if ($this->permissionMatchesRequest($permittedUrl, $requestUrl, $resourceType, $requiredPermission)) {
275
+ // This matches, append signature data
276
+ $parsedPermittedUrl = parse_url($permittedUrl);
277
+
278
+ if (strpos($requestUrl, '?') === false) {
279
+ $requestUrl .= '?';
280
+ } else {
281
+ $requestUrl .= '&';
282
+ }
283
+
284
+ $requestUrl .= $parsedPermittedUrl['query'];
285
+
286
+ // Return url
287
+ return $requestUrl;
288
+ }
289
+ }
290
+
291
+ // Return url, will be unsigned...
292
+ return $requestUrl;
293
+ }
294
+
295
+ /**
296
+ * Sign request with credentials
297
+ *
298
+ * @param string $httpVerb HTTP verb the request will use
299
+ * @param string $path Path for the request
300
+ * @param string $queryString Query string for the request
301
+ * @param array $headers x-ms headers to add
302
+ * @param boolean $forTableStorage Is the request for table storage?
303
+ * @param string $resourceType Resource type
304
+ * @param string $requiredPermission Required permission
305
+ * @param mixed $rawData Raw post data
306
+ * @return array Array of headers
307
+ */
308
+ public function signRequestHeaders(
309
+ $httpVerb = Microsoft_Http_Client::GET,
310
+ $path = '/',
311
+ $queryString = '',
312
+ $headers = null,
313
+ $forTableStorage = false,
314
+ $resourceType = Microsoft_WindowsAzure_Storage::RESOURCE_UNKNOWN,
315
+ $requiredPermission = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ,
316
+ $rawData = null
317
+ ) {
318
+ return $headers;
319
+ }
320
+ }
app/libs/Microsoft/WindowsAzure/Credentials/SharedKey.php ADDED
@@ -0,0 +1,200 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
31
+ * @license http://phpazure.codeplex.com/license
32
+ * @version $Id$
33
+ */
34
+
35
+ /**
36
+ * @see Microsoft_WindowsAzure_Credentials_CredentialsAbstract
37
+ */
38
+ require_once 'Microsoft/WindowsAzure/Credentials/CredentialsAbstract.php';
39
+
40
+ /**
41
+ * @see Microsoft_WindowsAzure_Storage
42
+ */
43
+ require_once 'Microsoft/WindowsAzure/Storage.php';
44
+
45
+ /**
46
+ * @see Microsoft_Http_Client
47
+ */
48
+ require_once 'Microsoft/Http/Client.php';
49
+
50
+ /**
51
+ * @see Microsoft_WindowsAzure_Credentials_Exception
52
+ */
53
+ require_once 'Microsoft/WindowsAzure/Credentials/Exception.php';
54
+
55
+ /**
56
+ * @category Microsoft
57
+ * @package Microsoft_WindowsAzure
58
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
59
+ * @license http://phpazure.codeplex.com/license
60
+ */
61
+ class Microsoft_WindowsAzure_Credentials_SharedKey
62
+ extends Microsoft_WindowsAzure_Credentials_CredentialsAbstract
63
+ {
64
+ /**
65
+ * Sign request URL with credentials
66
+ *
67
+ * @param string $requestUrl Request URL
68
+ * @param string $resourceType Resource type
69
+ * @param string $requiredPermission Required permission
70
+ * @return string Signed request URL
71
+ */
72
+ public function signRequestUrl(
73
+ $requestUrl = '',
74
+ $resourceType = Microsoft_WindowsAzure_Storage::RESOURCE_UNKNOWN,
75
+ $requiredPermission = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ
76
+ ) {
77
+ return $requestUrl;
78
+ }
79
+
80
+ /**
81
+ * Sign request headers with credentials
82
+ *
83
+ * @param string $httpVerb HTTP verb the request will use
84
+ * @param string $path Path for the request
85
+ * @param string $queryString Query string for the request
86
+ * @param array $headers x-ms headers to add
87
+ * @param boolean $forTableStorage Is the request for table storage?
88
+ * @param string $resourceType Resource type
89
+ * @param string $requiredPermission Required permission
90
+ * @param mixed $rawData Raw post data
91
+ * @return array Array of headers
92
+ */
93
+ public function signRequestHeaders(
94
+ $httpVerb = Microsoft_Http_Client::GET,
95
+ $path = '/',
96
+ $queryString = '',
97
+ $headers = null,
98
+ $forTableStorage = false,
99
+ $resourceType = Microsoft_WindowsAzure_Storage::RESOURCE_UNKNOWN,
100
+ $requiredPermission = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ,
101
+ $rawData = null
102
+ ) {
103
+ // http://github.com/sriramk/winazurestorage/blob/214010a2f8931bac9c96dfeb337d56fe084ca63b/winazurestorage.py
104
+
105
+ // Table storage?
106
+ if ($forTableStorage) {
107
+ throw new Microsoft_WindowsAzure_Credentials_Exception('The Windows Azure SDK for PHP does not support SharedKey authentication on table storage. Use SharedKeyLite authentication instead.');
108
+ }
109
+
110
+ // Determine path
111
+ if ($this->_usePathStyleUri) {
112
+ $path = substr($path, strpos($path, '/'));
113
+ }
114
+
115
+ // Determine query
116
+ $queryString = $this->_prepareQueryStringForSigning($queryString);
117
+
118
+ // Canonicalized headers
119
+ $canonicalizedHeaders = array();
120
+
121
+ // Request date
122
+ $requestDate = '';
123
+ if (isset($headers[Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER . 'date'])) {
124
+ $requestDate = $headers[Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER . 'date'];
125
+ } else {
126
+ $requestDate = gmdate('D, d M Y H:i:s', time()) . ' GMT'; // RFC 1123
127
+ $canonicalizedHeaders[] = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER . 'date:' . $requestDate;
128
+ }
129
+
130
+ // Build canonicalized headers
131
+ if (!is_null($headers)) {
132
+ foreach ($headers as $header => $value) {
133
+ if (is_bool($value)) {
134
+ $value = $value === true ? 'True' : 'False';
135
+ }
136
+
137
+ $headers[$header] = $value;
138
+ if (substr($header, 0, strlen(Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER)) == Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER) {
139
+ $canonicalizedHeaders[] = strtolower($header) . ':' . $value;
140
+ }
141
+ }
142
+ }
143
+ sort($canonicalizedHeaders);
144
+
145
+ // Build canonicalized resource string
146
+ $canonicalizedResource = '/' . $this->_accountName;
147
+ if ($this->_usePathStyleUri) {
148
+ $canonicalizedResource .= '/' . $this->_accountName;
149
+ }
150
+ $canonicalizedResource .= $path;
151
+ if ($queryString !== '') {
152
+ $queryStringItems = $this->_makeArrayOfQueryString($queryString);
153
+ foreach ($queryStringItems as $key => $value) {
154
+ $canonicalizedResource .= "\n" . strtolower($key) . ':' . $value;
155
+ }
156
+ }
157
+
158
+ // Content-Length header
159
+ $contentLength = '';
160
+ if (strtoupper($httpVerb) != Microsoft_Http_Client::GET
161
+ && strtoupper($httpVerb) != Microsoft_Http_Client::DELETE
162
+ && strtoupper($httpVerb) != Microsoft_Http_Client::HEAD) {
163
+ $contentLength = 0;
164
+
165
+ if (!is_null($rawData)) {
166
+ $contentLength = strlen($rawData);
167
+ }
168
+ }
169
+
170
+ // Create string to sign
171
+ $stringToSign = array();
172
+ $stringToSign[] = strtoupper($httpVerb); // VERB
173
+ $stringToSign[] = $this->_issetOr($headers, 'Content-Encoding', ''); // Content-Encoding
174
+ $stringToSign[] = $this->_issetOr($headers, 'Content-Language', ''); // Content-Language
175
+ $stringToSign[] = $contentLength; // Content-Length
176
+ $stringToSign[] = $this->_issetOr($headers, 'Content-MD5', ''); // Content-MD5
177
+ $stringToSign[] = $this->_issetOr($headers, 'Content-Type', ''); // Content-Type
178
+ $stringToSign[] = ""; // Date
179
+ $stringToSign[] = $this->_issetOr($headers, 'If-Modified-Since', ''); // If-Modified-Since
180
+ $stringToSign[] = $this->_issetOr($headers, 'If-Match', ''); // If-Match
181
+ $stringToSign[] = $this->_issetOr($headers, 'If-None-Match', ''); // If-None-Match
182
+ $stringToSign[] = $this->_issetOr($headers, 'If-Unmodified-Since', ''); // If-Unmodified-Since
183
+ $stringToSign[] = $this->_issetOr($headers, 'Range', ''); // Range
184
+
185
+ if (!$forTableStorage && count($canonicalizedHeaders) > 0) {
186
+ $stringToSign[] = implode("\n", $canonicalizedHeaders); // Canonicalized headers
187
+ }
188
+
189
+ $stringToSign[] = $canonicalizedResource; // Canonicalized resource
190
+ $stringToSign = implode("\n", $stringToSign);
191
+ $signString = base64_encode(hash_hmac('sha256', $stringToSign, $this->_accountKey, true));
192
+
193
+ // Sign request
194
+ $headers[Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER . 'date'] = $requestDate;
195
+ $headers['Authorization'] = 'SharedKey ' . $this->_accountName . ':' . $signString;
196
+
197
+ // Return headers
198
+ return $headers;
199
+ }
200
+ }
app/libs/Microsoft/WindowsAzure/Credentials/SharedKeyLite.php ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
31
+ * @license http://phpazure.codeplex.com/license
32
+ * @version $Id: SharedKeyCredentials.php 14561 2009-05-07 08:05:12Z unknown $
33
+ */
34
+
35
+ /**
36
+ * @see Microsoft_WindowsAzure_Credentials_CredentialsAbstract
37
+ */
38
+ require_once 'Microsoft/WindowsAzure/Credentials/CredentialsAbstract.php';
39
+
40
+ /**
41
+ * @see Microsoft_WindowsAzure_Storage
42
+ */
43
+ require_once 'Microsoft/WindowsAzure/Storage.php';
44
+
45
+ /**
46
+ * @see Microsoft_WindowsAzure_Credentials_SharedKey
47
+ */
48
+ require_once 'Microsoft/WindowsAzure/Credentials/SharedKey.php';
49
+
50
+ /**
51
+ * @see Microsoft_WindowsAzure_Credentials_Exception
52
+ */
53
+ require_once 'Microsoft/WindowsAzure/Credentials/Exception.php';
54
+
55
+ /**
56
+ * @category Microsoft
57
+ * @package Microsoft_WindowsAzure
58
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
59
+ * @license http://phpazure.codeplex.com/license
60
+ */
61
+ class Microsoft_WindowsAzure_Credentials_SharedKeyLite
62
+ extends Microsoft_WindowsAzure_Credentials_CredentialsAbstract
63
+ {
64
+ /**
65
+ * Sign request URL with credentials
66
+ *
67
+ * @param string $requestUrl Request URL
68
+ * @param string $resourceType Resource type
69
+ * @param string $requiredPermission Required permission
70
+ * @return string Signed request URL
71
+ */
72
+ public function signRequestUrl(
73
+ $requestUrl = '',
74
+ $resourceType = Microsoft_WindowsAzure_Storage::RESOURCE_UNKNOWN,
75
+ $requiredPermission = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ
76
+ ) {
77
+ return $requestUrl;
78
+ }
79
+
80
+ /**
81
+ * Sign request headers with credentials
82
+ *
83
+ * @param string $httpVerb HTTP verb the request will use
84
+ * @param string $path Path for the request
85
+ * @param string $queryString Query string for the request
86
+ * @param array $headers x-ms headers to add
87
+ * @param boolean $forTableStorage Is the request for table storage?
88
+ * @param string $resourceType Resource type
89
+ * @param string $requiredPermission Required permission
90
+ * @param mixed $rawData Raw post data
91
+ * @return array Array of headers
92
+ */
93
+ public function signRequestHeaders(
94
+ $httpVerb = Microsoft_Http_Client::GET,
95
+ $path = '/',
96
+ $queryString = '',
97
+ $headers = null,
98
+ $forTableStorage = false,
99
+ $resourceType = Microsoft_WindowsAzure_Storage::RESOURCE_UNKNOWN,
100
+ $requiredPermission = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ,
101
+ $rawData = null
102
+ ) {
103
+ // Table storage?
104
+ if (!$forTableStorage) {
105
+ throw new Microsoft_WindowsAzure_Credentials_Exception('The Windows Azure SDK for PHP does not support SharedKeyLite authentication on blob or queue storage. Use SharedKey authentication instead.');
106
+ }
107
+
108
+ // Determine path
109
+ if ($this->_usePathStyleUri) {
110
+ $path = substr($path, strpos($path, '/'));
111
+ }
112
+
113
+ // Determine query
114
+ $queryString = $this->_prepareQueryStringForSigning($queryString);
115
+
116
+ // Build canonicalized resource string
117
+ $canonicalizedResource = '/' . $this->_accountName;
118
+ if ($this->_usePathStyleUri) {
119
+ $canonicalizedResource .= '/' . $this->_accountName;
120
+ }
121
+ $canonicalizedResource .= $path;
122
+ if ($queryString !== '') {
123
+ $canonicalizedResource .= $queryString;
124
+ }
125
+
126
+ // Request date
127
+ $requestDate = '';
128
+ if (isset($headers[Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER . 'date'])) {
129
+ $requestDate = $headers[Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER . 'date'];
130
+ } else {
131
+ $requestDate = gmdate('D, d M Y H:i:s', time()) . ' GMT'; // RFC 1123
132
+ }
133
+
134
+ // Create string to sign
135
+ $stringToSign = array();
136
+ $stringToSign[] = $requestDate; // Date
137
+ $stringToSign[] = $canonicalizedResource; // Canonicalized resource
138
+ $stringToSign = implode("\n", $stringToSign);
139
+ $signString = base64_encode(hash_hmac('sha256', $stringToSign, $this->_accountKey, true));
140
+
141
+ // Sign request
142
+ $headers[Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PREFIX_STORAGE_HEADER . 'date'] = $requestDate;
143
+ $headers['Authorization'] = 'SharedKeyLite ' . $this->_accountName . ':' . $signString;
144
+
145
+ // Return headers
146
+ return $headers;
147
+ }
148
+
149
+ /**
150
+ * Prepare query string for signing
151
+ *
152
+ * @param string $value Original query string
153
+ * @return string Query string for signing
154
+ */
155
+ protected function _prepareQueryStringForSigning($value)
156
+ {
157
+ // Check for 'comp='
158
+ if (strpos($value, 'comp=') === false) {
159
+ // If not found, no query string needed
160
+ return '';
161
+ } else {
162
+ // If found, make sure it is the only parameter being used
163
+ if (strlen($value) > 0 && strpos($value, '?') === 0) {
164
+ $value = substr($value, 1);
165
+ }
166
+
167
+ // Split parts
168
+ $queryParts = explode('&', $value);
169
+ foreach ($queryParts as $queryPart) {
170
+ if (strpos($queryPart, 'comp=') !== false) {
171
+ return '?' . $queryPart;
172
+ }
173
+ }
174
+
175
+ // Should never happen...
176
+ return '';
177
+ }
178
+ }
179
+ }
app/libs/Microsoft/WindowsAzure/Diagnostics/ConfigurationDataSources.php ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Diagnostics
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 45989 2010-05-03 12:19:10Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Diagnostics_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Diagnostics/Exception.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationObjectBaseAbstract.php';
45
+
46
+ /**
47
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationLogs
48
+ */
49
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationLogs.php';
50
+
51
+ /**
52
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationDiagnosticInfrastructureLogs
53
+ */
54
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationDiagnosticInfrastructureLogs.php';
55
+
56
+ /**
57
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationPerformanceCounters
58
+ */
59
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationPerformanceCounters.php';
60
+
61
+ /**
62
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationWindowsEventLog
63
+ */
64
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationWindowsEventLog.php';
65
+
66
+ /**
67
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationDirectories
68
+ */
69
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationDirectories.php';
70
+
71
+ /**
72
+ * @category Microsoft
73
+ * @package Microsoft_WindowsAzure
74
+ * @subpackage Diagnostics
75
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
76
+ * @license http://phpazure.codeplex.com/license
77
+ *
78
+ * @property int OverallQuotaInMB Overall quota in MB
79
+ * @property Microsoft_WindowsAzure_Diagnostics_ConfigurationLogs Logs Logs
80
+ * @property Microsoft_WindowsAzure_Diagnostics_ConfigurationDiagnosticInfrastructureLogs DiagnosticInfrastructureLogs Diagnostic infrastructure logs
81
+ * @property Microsoft_WindowsAzure_Diagnostics_ConfigurationPerformanceCounters PerformanceCounters Performance counters
82
+ * @property Microsoft_WindowsAzure_Diagnostics_ConfigurationWindowsEventLog WindowsEventLog Windows Event Log
83
+ * @property Microsoft_WindowsAzure_Diagnostics_ConfigurationDirectories Directories Directories
84
+ */
85
+ class Microsoft_WindowsAzure_Diagnostics_ConfigurationDataSources
86
+ extends Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
87
+ {
88
+ /**
89
+ * Constructor
90
+ *
91
+ * @param int $overallQuotaInMB Overall quota in MB
92
+ */
93
+ public function __construct($overallQuotaInMB = 0)
94
+ {
95
+ $this->_data = array(
96
+ 'overallquotainmb' => $overallQuotaInMB,
97
+ 'logs' => new Microsoft_WindowsAzure_Diagnostics_ConfigurationLogs(),
98
+ 'diagnosticinfrastructurelogs' => new Microsoft_WindowsAzure_Diagnostics_ConfigurationDiagnosticInfrastructureLogs(),
99
+ 'performancecounters' => new Microsoft_WindowsAzure_Diagnostics_ConfigurationPerformanceCounters(),
100
+ 'windowseventlog' => new Microsoft_WindowsAzure_Diagnostics_ConfigurationWindowsEventLog(),
101
+ 'directories' => new Microsoft_WindowsAzure_Diagnostics_ConfigurationDirectories()
102
+ );
103
+ }
104
+ }
app/libs/Microsoft/WindowsAzure/Diagnostics/ConfigurationDiagnosticInfrastructureLogs.php ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Diagnostics
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 45989 2010-05-03 12:19:10Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Diagnostics_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Diagnostics/Exception.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationObjectBaseAbstract.php';
45
+
46
+ /**
47
+ * @see Microsoft_WindowsAzure_Diagnostics_LogLevel
48
+ */
49
+ require_once 'Microsoft/WindowsAzure/Diagnostics/LogLevel.php';
50
+
51
+ /**
52
+ * @category Microsoft
53
+ * @package Microsoft_WindowsAzure
54
+ * @subpackage Diagnostics
55
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
56
+ * @license http://phpazure.codeplex.com/license
57
+ *
58
+ * @property int BufferQuotaInMB Buffer quota in MB
59
+ * @property int ScheduledTransferPeriodInMinutes Scheduled transfer period in minutes
60
+ * @property string ScheduledTransferLogLevelFilter Scheduled transfer log level filter
61
+ */
62
+ class Microsoft_WindowsAzure_Diagnostics_ConfigurationDiagnosticInfrastructureLogs
63
+ extends Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
64
+ {
65
+ /**
66
+ * Constructor
67
+ *
68
+ * @param int $bufferQuotaInMB Buffer quota in MB
69
+ * @param int $scheduledTransferPeriodInMinutes Scheduled transfer period in minutes
70
+ * @param string $scheduledTransferLogLevelFilter Scheduled transfer log level filter
71
+ */
72
+ public function __construct($bufferQuotaInMB = 0, $scheduledTransferPeriodInMinutes = 0, $scheduledTransferLogLevelFilter = Microsoft_WindowsAzure_Diagnostics_LogLevel::UNDEFINED)
73
+ {
74
+ $this->_data = array(
75
+ 'bufferquotainmb' => $bufferQuotaInMB,
76
+ 'scheduledtransferperiodinminutes' => $scheduledTransferPeriodInMinutes,
77
+ 'scheduledtransferloglevelfilter' => $scheduledTransferLogLevelFilter
78
+ );
79
+ }
80
+ }
app/libs/Microsoft/WindowsAzure/Diagnostics/ConfigurationDirectories.php ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Diagnostics
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 45989 2010-05-03 12:19:10Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Diagnostics_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Diagnostics/Exception.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationObjectBaseAbstract.php';
45
+
46
+ /**
47
+ * @see Microsoft_WindowsAzure_Diagnostics_DirectoryConfigurationSubscription
48
+ */
49
+ require_once 'Microsoft/WindowsAzure/Diagnostics/DirectoryConfigurationSubscription.php';
50
+
51
+ /**
52
+ * @category Microsoft
53
+ * @package Microsoft_WindowsAzure
54
+ * @subpackage Diagnostics
55
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
56
+ * @license http://phpazure.codeplex.com/license
57
+ *
58
+ * @property int BufferQuotaInMB Buffer quota in MB
59
+ * @property int ScheduledTransferPeriodInMinutes Scheduled transfer period in minutes
60
+ * @property array Subscriptions Subscriptions
61
+ */
62
+ class Microsoft_WindowsAzure_Diagnostics_ConfigurationDirectories
63
+ extends Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
64
+ {
65
+ /**
66
+ * Constructor
67
+ *
68
+ * @param int $bufferQuotaInMB Buffer quota in MB
69
+ * @param int $scheduledTransferPeriodInMinutes Scheduled transfer period in minutes
70
+ */
71
+ public function __construct($bufferQuotaInMB = 0, $scheduledTransferPeriodInMinutes = 0)
72
+ {
73
+ $this->_data = array(
74
+ 'bufferquotainmb' => $bufferQuotaInMB,
75
+ 'scheduledtransferperiodinminutes' => $scheduledTransferPeriodInMinutes,
76
+ 'subscriptions' => array()
77
+ );
78
+ }
79
+
80
+ /**
81
+ * Add subscription
82
+ *
83
+ * @param string $path Path
84
+ * @param string $container Container
85
+ * @param int $directoryQuotaInMB Directory quota in MB
86
+ */
87
+ public function addSubscription($path, $container, $directoryQuotaInMB = 1024)
88
+ {
89
+ $this->_data['subscriptions'][$path] = new Microsoft_WindowsAzure_Diagnostics_DirectoryConfigurationSubscription($path, $container, $directoryQuotaInMB);
90
+ }
91
+
92
+ /**
93
+ * Remove subscription
94
+ *
95
+ * @param string $path Path
96
+ */
97
+ public function removeSubscription($path)
98
+ {
99
+ if (isset($this->_data['subscriptions'][$path])) {
100
+ unset($this->_data['subscriptions'][$path]);
101
+ }
102
+ }
103
+ }
app/libs/Microsoft/WindowsAzure/Diagnostics/ConfigurationInstance.php ADDED
@@ -0,0 +1,234 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Diagnostics
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 45989 2010-05-03 12:19:10Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Diagnostics_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Diagnostics/Exception.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationObjectBaseAbstract.php';
45
+
46
+ /**
47
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationDataSources
48
+ */
49
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationDataSources.php';
50
+
51
+ /**
52
+ * @category Microsoft
53
+ * @package Microsoft_WindowsAzure
54
+ * @subpackage Diagnostics
55
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
56
+ * @license http://phpazure.codeplex.com/license
57
+ *
58
+ * @property Microsoft_WindowsAzure_Diagnostics_ConfigurationDataSources DataSources Data sources
59
+ */
60
+ class Microsoft_WindowsAzure_Diagnostics_ConfigurationInstance
61
+ extends Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
62
+ {
63
+ /**
64
+ * Constructor
65
+ */
66
+ public function __construct()
67
+ {
68
+ $this->_data = array(
69
+ 'datasources' => new Microsoft_WindowsAzure_Diagnostics_ConfigurationDataSources()
70
+ );
71
+ }
72
+
73
+ /**
74
+ * Load configuration XML
75
+ *
76
+ * @param string $configurationXml Configuration XML
77
+ */
78
+ public function loadXml($configurationXml)
79
+ {
80
+ // Convert to SimpleXMLElement
81
+ $configurationXml = simplexml_load_string($configurationXml);
82
+
83
+ // Assign general settings
84
+ $this->DataSources->OverallQuotaInMB = (int)$configurationXml->DataSources->OverallQuotaInMB;
85
+
86
+ // Assign Logs settings
87
+ $this->DataSources->Logs->BufferQuotaInMB = (int)$configurationXml->DataSources->Logs->BufferQuotaInMB;
88
+ $this->DataSources->Logs->ScheduledTransferPeriodInMinutes = (int)$configurationXml->DataSources->Logs->ScheduledTransferPeriodInMinutes;
89
+ $this->DataSources->Logs->ScheduledTransferLogLevelFilter = (string)$configurationXml->DataSources->Logs->ScheduledTransferLogLevelFilter;
90
+
91
+ // Assign DiagnosticInfrastructureLogs settings
92
+ $this->DataSources->DiagnosticInfrastructureLogs->BufferQuotaInMB = (int)$configurationXml->DataSources->DiagnosticInfrastructureLogs->BufferQuotaInMB;
93
+ $this->DataSources->DiagnosticInfrastructureLogs->ScheduledTransferPeriodInMinutes = (int)$configurationXml->DataSources->DiagnosticInfrastructureLogs->ScheduledTransferPeriodInMinutes;
94
+ $this->DataSources->DiagnosticInfrastructureLogs->ScheduledTransferLogLevelFilter = (string)$configurationXml->DataSources->DiagnosticInfrastructureLogs->ScheduledTransferLogLevelFilter;
95
+
96
+ // Assign PerformanceCounters settings
97
+ $this->DataSources->PerformanceCounters->BufferQuotaInMB = (int)$configurationXml->DataSources->PerformanceCounters->BufferQuotaInMB;
98
+ $this->DataSources->PerformanceCounters->ScheduledTransferPeriodInMinutes = (int)$configurationXml->DataSources->PerformanceCounters->ScheduledTransferPeriodInMinutes;
99
+ if ($configurationXml->DataSources->PerformanceCounters->Subscriptions
100
+ && $configurationXml->DataSources->PerformanceCounters->Subscriptions->PerformanceCounterConfiguration) {
101
+ $subscriptions = $configurationXml->DataSources->PerformanceCounters->Subscriptions;
102
+ if (count($subscriptions->PerformanceCounterConfiguration) > 1) {
103
+ $subscriptions = $subscriptions->PerformanceCounterConfiguration;
104
+ } else {
105
+ $subscriptions = array($subscriptions->PerformanceCounterConfiguration);
106
+ }
107
+ foreach ($subscriptions as $subscription) {
108
+ $this->DataSources->PerformanceCounters->addSubscription((string)$subscription->CounterSpecifier, (int)$subscription->SampleRateInSeconds);
109
+ }
110
+ }
111
+
112
+ // Assign WindowsEventLog settings
113
+ $this->DataSources->WindowsEventLog->BufferQuotaInMB = (int)$configurationXml->DataSources->WindowsEventLog->BufferQuotaInMB;
114
+ $this->DataSources->WindowsEventLog->ScheduledTransferPeriodInMinutes = (int)$configurationXml->DataSources->WindowsEventLog->ScheduledTransferPeriodInMinutes;
115
+ $this->DataSources->WindowsEventLog->ScheduledTransferLogLevelFilter = (string)$configurationXml->DataSources->WindowsEventLog->ScheduledTransferLogLevelFilter;
116
+ if ($configurationXml->DataSources->WindowsEventLog->Subscriptions
117
+ && $configurationXml->DataSources->WindowsEventLog->Subscriptions->string) {
118
+ $subscriptions = $configurationXml->DataSources->WindowsEventLog->Subscriptions;
119
+ if (count($subscriptions->string) > 1) {
120
+ $subscriptions = $subscriptions->string;
121
+ } else {
122
+ $subscriptions = array($subscriptions->string);
123
+ }
124
+ foreach ($subscriptions as $subscription) {
125
+ $this->DataSources->WindowsEventLog->addSubscription((string)$subscription);
126
+ }
127
+ }
128
+
129
+ // Assign Directories settings
130
+ $this->DataSources->Directories->BufferQuotaInMB = (int)$configurationXml->DataSources->Directories->BufferQuotaInMB;
131
+ $this->DataSources->Directories->ScheduledTransferPeriodInMinutes = (int)$configurationXml->DataSources->Directories->ScheduledTransferPeriodInMinutes;
132
+
133
+ if ($configurationXml->DataSources->Directories->Subscriptions
134
+ && $configurationXml->DataSources->Directories->Subscriptions->DirectoryConfiguration) {
135
+ $subscriptions = $configurationXml->DataSources->Directories->Subscriptions;
136
+ if (count($subscriptions->DirectoryConfiguration) > 1) {
137
+ $subscriptions = $subscriptions->DirectoryConfiguration;
138
+ } else {
139
+ $subscriptions = array($subscriptions->DirectoryConfiguration);
140
+ }
141
+ foreach ($subscriptions as $subscription) {
142
+ $this->DataSources->Directories->addSubscription((string)$subscription->Path, (string)$subscription->Container, (int)$subscription->DirectoryQuotaInMB);
143
+ }
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Create configuration XML
149
+ *
150
+ * @return string
151
+ */
152
+ public function toXml()
153
+ {
154
+ // Return value
155
+ $returnValue = array();
156
+
157
+ // Build XML
158
+ $returnValue[] = '<?xml version="1.0"?>';
159
+ $returnValue[] = '<ConfigRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">';
160
+
161
+ // Add data sources
162
+ $returnValue[] = ' <DataSources>';
163
+
164
+ $returnValue[] = ' <OverallQuotaInMB>' . $this->DataSources->OverallQuotaInMB . '</OverallQuotaInMB>';
165
+
166
+ $returnValue[] = ' <Logs>';
167
+ $returnValue[] = ' <BufferQuotaInMB>' . $this->DataSources->Logs->BufferQuotaInMB . '</BufferQuotaInMB>';
168
+ $returnValue[] = ' <ScheduledTransferPeriodInMinutes>' . $this->DataSources->Logs->ScheduledTransferPeriodInMinutes . '</ScheduledTransferPeriodInMinutes>';
169
+ $returnValue[] = ' <ScheduledTransferLogLevelFilter>' . $this->DataSources->Logs->ScheduledTransferLogLevelFilter . '</ScheduledTransferLogLevelFilter>';
170
+ $returnValue[] = ' </Logs>';
171
+
172
+ $returnValue[] = ' <DiagnosticInfrastructureLogs>';
173
+ $returnValue[] = ' <BufferQuotaInMB>' . $this->DataSources->DiagnosticInfrastructureLogs->BufferQuotaInMB . '</BufferQuotaInMB>';
174
+ $returnValue[] = ' <ScheduledTransferPeriodInMinutes>' . $this->DataSources->DiagnosticInfrastructureLogs->ScheduledTransferPeriodInMinutes . '</ScheduledTransferPeriodInMinutes>';
175
+ $returnValue[] = ' <ScheduledTransferLogLevelFilter>' . $this->DataSources->DiagnosticInfrastructureLogs->ScheduledTransferLogLevelFilter . '</ScheduledTransferLogLevelFilter>';
176
+ $returnValue[] = ' </DiagnosticInfrastructureLogs>';
177
+
178
+ $returnValue[] = ' <PerformanceCounters>';
179
+ $returnValue[] = ' <BufferQuotaInMB>' . $this->DataSources->PerformanceCounters->BufferQuotaInMB . '</BufferQuotaInMB>';
180
+ $returnValue[] = ' <ScheduledTransferPeriodInMinutes>' . $this->DataSources->PerformanceCounters->ScheduledTransferPeriodInMinutes . '</ScheduledTransferPeriodInMinutes>';
181
+ if (count($this->DataSources->PerformanceCounters->Subscriptions) == 0) {
182
+ $returnValue[] = ' <Subscriptions />';
183
+ } else {
184
+ $returnValue[] = ' <Subscriptions>';
185
+ foreach ($this->DataSources->PerformanceCounters->Subscriptions as $subscription) {
186
+ $returnValue[] = ' <PerformanceCounterConfiguration>';
187
+ $returnValue[] = ' <CounterSpecifier>' . $subscription->CounterSpecifier . '</CounterSpecifier>';
188
+ $returnValue[] = ' <SampleRateInSeconds>' . $subscription->SampleRateInSeconds . '</SampleRateInSeconds>';
189
+ $returnValue[] = ' </PerformanceCounterConfiguration>';
190
+ }
191
+ $returnValue[] = ' </Subscriptions>';
192
+ }
193
+ $returnValue[] = ' </PerformanceCounters>';
194
+
195
+ $returnValue[] = ' <WindowsEventLog>';
196
+ $returnValue[] = ' <BufferQuotaInMB>' . $this->DataSources->WindowsEventLog->BufferQuotaInMB . '</BufferQuotaInMB>';
197
+ $returnValue[] = ' <ScheduledTransferPeriodInMinutes>' . $this->DataSources->WindowsEventLog->ScheduledTransferPeriodInMinutes . '</ScheduledTransferPeriodInMinutes>';
198
+ if (count($this->DataSources->WindowsEventLog->Subscriptions) == 0) {
199
+ $returnValue[] = ' <Subscriptions />';
200
+ } else {
201
+ $returnValue[] = ' <Subscriptions>';
202
+ foreach ($this->DataSources->WindowsEventLog->Subscriptions as $subscription) {
203
+ $returnValue[] = ' <string>' . $subscription . '</string>';
204
+ }
205
+ $returnValue[] = ' </Subscriptions>';
206
+ }
207
+ $returnValue[] = ' <ScheduledTransferLogLevelFilter>' . $this->DataSources->WindowsEventLog->ScheduledTransferLogLevelFilter . '</ScheduledTransferLogLevelFilter>';
208
+ $returnValue[] = ' </WindowsEventLog>';
209
+
210
+ $returnValue[] = ' <Directories>';
211
+ $returnValue[] = ' <BufferQuotaInMB>' . $this->DataSources->Directories->BufferQuotaInMB . '</BufferQuotaInMB>';
212
+ $returnValue[] = ' <ScheduledTransferPeriodInMinutes>' . $this->DataSources->Directories->ScheduledTransferPeriodInMinutes . '</ScheduledTransferPeriodInMinutes>';
213
+ if (count($this->DataSources->Directories->Subscriptions) == 0) {
214
+ $returnValue[] = ' <Subscriptions />';
215
+ } else {
216
+ $returnValue[] = ' <Subscriptions>';
217
+ foreach ($this->DataSources->Directories->Subscriptions as $subscription) {
218
+ $returnValue[] = ' <DirectoryConfiguration>';
219
+ $returnValue[] = ' <Path>' . $subscription->Path . '</Path>';
220
+ $returnValue[] = ' <Container>' . $subscription->Container . '</Container>';
221
+ $returnValue[] = ' <DirectoryQuotaInMB>' . $subscription->DirectoryQuotaInMB . '</DirectoryQuotaInMB>';
222
+ $returnValue[] = ' </DirectoryConfiguration>';
223
+ }
224
+ $returnValue[] = ' </Subscriptions>';
225
+ }
226
+ $returnValue[] = ' </Directories>';
227
+
228
+ $returnValue[] = ' </DataSources>';
229
+ $returnValue[] = '</ConfigRequest>';
230
+
231
+ // Return
232
+ return implode("\r\n", $returnValue);
233
+ }
234
+ }
app/libs/Microsoft/WindowsAzure/Diagnostics/ConfigurationLogs.php ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Diagnostics
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 45989 2010-05-03 12:19:10Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Diagnostics_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Diagnostics/Exception.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationObjectBaseAbstract.php';
45
+
46
+ /**
47
+ * @see Microsoft_WindowsAzure_Diagnostics_LogLevel
48
+ */
49
+ require_once 'Microsoft/WindowsAzure/Diagnostics/LogLevel.php';
50
+
51
+ /**
52
+ * @category Microsoft
53
+ * @package Microsoft_WindowsAzure
54
+ * @subpackage Diagnostics
55
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
56
+ * @license http://phpazure.codeplex.com/license
57
+ *
58
+ * @property int BufferQuotaInMB Buffer quota in MB
59
+ * @property int ScheduledTransferPeriodInMinutes Scheduled transfer period in minutes
60
+ * @property string ScheduledTransferLogLevelFilter Scheduled transfer log level filter
61
+ */
62
+ class Microsoft_WindowsAzure_Diagnostics_ConfigurationLogs
63
+ extends Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
64
+ {
65
+ /**
66
+ * Constructor
67
+ *
68
+ * @param int $bufferQuotaInMB Buffer quota in MB
69
+ * @param int $scheduledTransferPeriodInMinutes Scheduled transfer period in minutes
70
+ * @param string $scheduledTransferLogLevelFilter Scheduled transfer log level filter
71
+ */
72
+ public function __construct($bufferQuotaInMB = 0, $scheduledTransferPeriodInMinutes = 0, $scheduledTransferLogLevelFilter = Microsoft_WindowsAzure_Diagnostics_LogLevel::UNDEFINED)
73
+ {
74
+ $this->_data = array(
75
+ 'bufferquotainmb' => $bufferQuotaInMB,
76
+ 'scheduledtransferperiodinminutes' => $scheduledTransferPeriodInMinutes,
77
+ 'scheduledtransferloglevelfilter' => $scheduledTransferLogLevelFilter
78
+ );
79
+ }
80
+ }
app/libs/Microsoft/WindowsAzure/Diagnostics/ConfigurationObjectBaseAbstract.php ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Diagnostics
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 45989 2010-05-03 12:19:10Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Diagnostics_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Diagnostics/Exception.php';
40
+
41
+ /**
42
+ * @category Microsoft
43
+ * @package Microsoft_WindowsAzure
44
+ * @subpackage Diagnostics
45
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
46
+ * @license http://phpazure.codeplex.com/license
47
+ */
48
+ abstract class Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
49
+ {
50
+ /**
51
+ * Data
52
+ *
53
+ * @var array
54
+ */
55
+ protected $_data = null;
56
+
57
+ /**
58
+ * Magic overload for setting properties
59
+ *
60
+ * @param string $name Name of the property
61
+ * @param string $value Value to set
62
+ */
63
+ public function __set($name, $value) {
64
+ if (array_key_exists(strtolower($name), $this->_data)) {
65
+ $this->_data[strtolower($name)] = $value;
66
+ return;
67
+ }
68
+
69
+ throw new Microsoft_WindowsAzure_Diagnostics_Exception("Unknown property: " . $name);
70
+ }
71
+
72
+ /**
73
+ * Magic overload for getting properties
74
+ *
75
+ * @param string $name Name of the property
76
+ */
77
+ public function __get($name) {
78
+ if (array_key_exists(strtolower($name), $this->_data)) {
79
+ return $this->_data[strtolower($name)];
80
+ }
81
+
82
+ throw new Microsoft_WindowsAzure_Diagnostics_Exception("Unknown property: " . $name);
83
+ }
84
+ }
app/libs/Microsoft/WindowsAzure/Diagnostics/ConfigurationPerformanceCounters.php ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Diagnostics
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 45989 2010-05-03 12:19:10Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Diagnostics_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Diagnostics/Exception.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationObjectBaseAbstract.php';
45
+
46
+ /**
47
+ * @see Microsoft_WindowsAzure_Diagnostics_PerformanceCounterSubscription
48
+ */
49
+ require_once 'Microsoft/WindowsAzure/Diagnostics/PerformanceCounterSubscription.php';
50
+
51
+ /**
52
+ * @category Microsoft
53
+ * @package Microsoft_WindowsAzure
54
+ * @subpackage Diagnostics
55
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
56
+ * @license http://phpazure.codeplex.com/license
57
+ *
58
+ * @property int BufferQuotaInMB Buffer quota in MB
59
+ * @property int ScheduledTransferPeriodInMinutes Scheduled transfer period in minutes
60
+ * @property array Subscriptions Subscriptions
61
+ */
62
+ class Microsoft_WindowsAzure_Diagnostics_ConfigurationPerformanceCounters
63
+ extends Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
64
+ {
65
+ /**
66
+ * Constructor
67
+ *
68
+ * @param int $bufferQuotaInMB Buffer quota in MB
69
+ * @param int $scheduledTransferPeriodInMinutes Scheduled transfer period in minutes
70
+ */
71
+ public function __construct($bufferQuotaInMB = 0, $scheduledTransferPeriodInMinutes = 0)
72
+ {
73
+ $this->_data = array(
74
+ 'bufferquotainmb' => $bufferQuotaInMB,
75
+ 'scheduledtransferperiodinminutes' => $scheduledTransferPeriodInMinutes,
76
+ 'subscriptions' => array()
77
+ );
78
+ }
79
+
80
+ /**
81
+ * Add subscription
82
+ *
83
+ * @param string $counterSpecifier Counter specifier
84
+ * @param int $sampleRateInSeconds Sample rate in seconds
85
+ */
86
+ public function addSubscription($counterSpecifier, $sampleRateInSeconds = 1)
87
+ {
88
+ $this->_data['subscriptions'][$counterSpecifier] = new Microsoft_WindowsAzure_Diagnostics_PerformanceCounterSubscription($counterSpecifier, $sampleRateInSeconds);
89
+ }
90
+
91
+ /**
92
+ * Remove subscription
93
+ *
94
+ * @param string $counterSpecifier Counter specifier
95
+ */
96
+ public function removeSubscription($counterSpecifier)
97
+ {
98
+ if (isset($this->_data['subscriptions'][$counterSpecifier])) {
99
+ unset($this->_data['subscriptions'][$counterSpecifier]);
100
+ }
101
+ }
102
+ }
app/libs/Microsoft/WindowsAzure/Diagnostics/ConfigurationWindowsEventLog.php ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Diagnostics
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 45989 2010-05-03 12:19:10Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Diagnostics_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Diagnostics/Exception.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationObjectBaseAbstract.php';
45
+
46
+ /**
47
+ * @see Microsoft_WindowsAzure_Diagnostics_LogLevel
48
+ */
49
+ require_once 'Microsoft/WindowsAzure/Diagnostics/LogLevel.php';
50
+
51
+ /**
52
+ * @category Microsoft
53
+ * @package Microsoft_WindowsAzure
54
+ * @subpackage Diagnostics
55
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
56
+ * @license http://phpazure.codeplex.com/license
57
+ *
58
+ * @property int BufferQuotaInMB Buffer quota in MB
59
+ * @property int ScheduledTransferPeriodInMinutes Scheduled transfer period in minutes
60
+ * @property string ScheduledTransferLogLevelFilter Scheduled transfer log level filter
61
+ * @property array Subscriptions Subscriptions
62
+ */
63
+ class Microsoft_WindowsAzure_Diagnostics_ConfigurationWindowsEventLog
64
+ extends Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
65
+ {
66
+ /**
67
+ * Constructor
68
+ *
69
+ * @param int $bufferQuotaInMB Buffer quota in MB
70
+ * @param int $scheduledTransferPeriodInMinutes Scheduled transfer period in minutes
71
+ * @param string $scheduledTransferLogLevelFilter Scheduled transfer log level filter
72
+ */
73
+ public function __construct($bufferQuotaInMB = 0, $scheduledTransferPeriodInMinutes = 0, $scheduledTransferLogLevelFilter = Microsoft_WindowsAzure_Diagnostics_LogLevel::UNDEFINED)
74
+ {
75
+ $this->_data = array(
76
+ 'bufferquotainmb' => $bufferQuotaInMB,
77
+ 'scheduledtransferperiodinminutes' => $scheduledTransferPeriodInMinutes,
78
+ 'scheduledtransferloglevelfilter' => $scheduledTransferLogLevelFilter,
79
+ 'subscriptions' => array()
80
+ );
81
+ }
82
+
83
+ /**
84
+ * Add subscription
85
+ *
86
+ * @param string $filter Event log filter
87
+ */
88
+ public function addSubscription($filter)
89
+ {
90
+ $this->_data['subscriptions'][$filter] = $filter;
91
+ }
92
+
93
+ /**
94
+ * Remove subscription
95
+ *
96
+ * @param string $filter Event log filter
97
+ */
98
+ public function removeSubscription($filter)
99
+ {
100
+ if (isset($this->_data['subscriptions'][$filter])) {
101
+ unset($this->_data['subscriptions'][$filter]);
102
+ }
103
+ }
104
+ }
app/libs/Microsoft/WindowsAzure/Diagnostics/DirectoryConfigurationSubscription.php ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Diagnostics
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 45989 2010-05-03 12:19:10Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Diagnostics_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Diagnostics/Exception.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationObjectBaseAbstract.php';
45
+
46
+ /**
47
+ * @category Microsoft
48
+ * @package Microsoft_WindowsAzure
49
+ * @subpackage Diagnostics
50
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
51
+ * @license http://phpazure.codeplex.com/license
52
+ *
53
+ * @property string Path Path
54
+ * @property string Container Container
55
+ * @property int DirectoryQuotaInMB Directory quota in MB
56
+ */
57
+ class Microsoft_WindowsAzure_Diagnostics_DirectoryConfigurationSubscription
58
+ extends Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
59
+ {
60
+ /**
61
+ * Constructor
62
+ *
63
+ * @param string $path Path
64
+ * @param string $container Container
65
+ * @param int $directoryQuotaInMB Directory quota in MB
66
+ */
67
+ public function __construct($path, $container, $directoryQuotaInMB = 1024)
68
+ {
69
+ $this->_data = array(
70
+ 'path' => $path,
71
+ 'container' => $container,
72
+ 'directoryquotainmb' => $directoryQuotaInMB
73
+ );
74
+ }
75
+ }
app/libs/Microsoft/WindowsAzure/Diagnostics/Exception.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Diagnostics
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 45989 2010-05-03 12:19:10Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Exception.php';
40
+
41
+ /**
42
+ * @category Microsoft
43
+ * @package Microsoft_WindowsAzure
44
+ * @subpackage Diagnostics
45
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
46
+ * @license http://phpazure.codeplex.com/license
47
+ */
48
+ class Microsoft_WindowsAzure_Diagnostics_Exception
49
+ extends Microsoft_WindowsAzure_Exception
50
+ {
51
+ }
app/libs/Microsoft/WindowsAzure/Diagnostics/LogLevel.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Diagnostics
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 45989 2010-05-03 12:19:10Z unknown $
34
+ */
35
+
36
+
37
+ /**
38
+ * @category Microsoft
39
+ * @package Microsoft_WindowsAzure
40
+ * @subpackage Diagnostics
41
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
42
+ * @license http://phpazure.codeplex.com/license
43
+ */
44
+ class Microsoft_WindowsAzure_Diagnostics_LogLevel
45
+ {
46
+ const UNDEFINED = 'Undefined';
47
+ const CRITICAL = 'Critical';
48
+ const ERROR = 'Error';
49
+ const WARNING = 'Warning';
50
+ const INFORMATION = 'Information';
51
+ const VERBOSE = 'Verbose';
52
+ }
app/libs/Microsoft/WindowsAzure/Diagnostics/Manager.php ADDED
@@ -0,0 +1,225 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Diagnostics
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 45989 2010-05-03 12:19:10Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Storage_Blob
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Storage/Blob.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Diagnostics_Exception
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Diagnostics/Exception.php';
45
+
46
+ /**
47
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationInstance
48
+ */
49
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationInstance.php';
50
+
51
+ /**
52
+ * @category Microsoft
53
+ * @package Microsoft_WindowsAzure
54
+ * @subpackage Diagnostics
55
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
56
+ * @license http://phpazure.codeplex.com/license
57
+ */
58
+ class Microsoft_WindowsAzure_Diagnostics_Manager
59
+ {
60
+ /**
61
+ * Blob storage client
62
+ *
63
+ * @var Microsoft_WindowsAzure_Storage_Blob
64
+ */
65
+ protected $_blobStorageClient = null;
66
+
67
+ /**
68
+ * Control container name
69
+ *
70
+ * @var string
71
+ */
72
+ protected $_controlContainer = '';
73
+
74
+ /**
75
+ * Create a new instance of Microsoft_WindowsAzure_Diagnostics_Manager
76
+ *
77
+ * @param Microsoft_WindowsAzure_Storage_Blob $blobStorageClient Blob storage client
78
+ * @param string $controlContainer Control container name
79
+ */
80
+ public function __construct(Microsoft_WindowsAzure_Storage_Blob $blobStorageClient = null, $controlContainer = 'wad-control-container')
81
+ {
82
+ $this->_blobStorageClient = $blobStorageClient;
83
+ $this->_controlContainer = $controlContainer;
84
+
85
+ $this->_ensureStorageInitialized();
86
+ }
87
+
88
+ /**
89
+ * Ensure storage has been initialized
90
+ */
91
+ protected function _ensureStorageInitialized()
92
+ {
93
+ if (!$this->_blobStorageClient->containerExists($this->_controlContainer)) {
94
+ $this->_blobStorageClient->createContainer($this->_controlContainer);
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Get default configuration values
100
+ *
101
+ * @return Microsoft_WindowsAzure_Diagnostics_ConfigurationInstance
102
+ */
103
+ public function getDefaultConfiguration()
104
+ {
105
+ return new Microsoft_WindowsAzure_Diagnostics_ConfigurationInstance();
106
+ }
107
+
108
+ /**
109
+ * Checks if a configuration for a specific role instance exists.
110
+ *
111
+ * @param string $roleInstance Role instance name, can be found in $_SERVER['RdRoleId'] when hosted on Windows Azure.
112
+ * @return boolean
113
+ * @throws Microsoft_WindowsAzure_Diagnostics_Exception
114
+ */
115
+ public function configurationForRoleInstanceExists($roleInstance = null)
116
+ {
117
+ if (is_null($roleInstance)) {
118
+ throw new Microsoft_WindowsAzure_Diagnostics_Exception('Role instance should be specified. Try reading $_SERVER[\'RdRoleId\'] for this information if the application is hosted on Windows Azure Fabric or Development Fabric.');
119
+ }
120
+
121
+ return $this->_blobStorageClient->blobExists($this->_controlContainer, $roleInstance);
122
+ }
123
+
124
+ /**
125
+ * Checks if a configuration for current role instance exists. Only works on Development Fabric or Windows Azure Fabric.
126
+ *
127
+ * @return boolean
128
+ * @throws Microsoft_WindowsAzure_Diagnostics_Exception
129
+ */
130
+ public function configurationForCurrentRoleInstanceExists()
131
+ {
132
+ if (!isset($_SERVER['RdRoleId'])) {
133
+ throw new Microsoft_WindowsAzure_Diagnostics_Exception('Server variable \'RdRoleId\' is unknown. Please verify the application is running in Development Fabric or Windows Azure Fabric.');
134
+ }
135
+
136
+ return $this->_blobStorageClient->blobExists($this->_controlContainer, $this->_getCurrentRoleInstanceId());
137
+ }
138
+
139
+ /**
140
+ * Get configuration for current role instance. Only works on Development Fabric or Windows Azure Fabric.
141
+ *
142
+ * @return Microsoft_WindowsAzure_Diagnostics_ConfigurationInstance
143
+ * @throws Microsoft_WindowsAzure_Diagnostics_Exception
144
+ */
145
+ public function getConfigurationForCurrentRoleInstance()
146
+ {
147
+ if (!isset($_SERVER['RdRoleId'])) {
148
+ throw new Microsoft_WindowsAzure_Diagnostics_Exception('Server variable \'RdRoleId\' is unknown. Please verify the application is running in Development Fabric or Windows Azure Fabric.');
149
+ }
150
+ return $this->getConfigurationForRoleInstance($this->_getCurrentRoleInstanceId());
151
+ }
152
+
153
+ /**
154
+ * Get the current role instance ID. Only works on Development Fabric or Windows Azure Fabric.
155
+ *
156
+ * @return string
157
+ * @throws Microsoft_WindowsAzure_Diagnostics_Exception
158
+ */
159
+ protected function _getCurrentRoleInstanceId()
160
+ {
161
+ if (!isset($_SERVER['RdRoleId'])) {
162
+ throw new Microsoft_WindowsAzure_Diagnostics_Exception('Server variable \'RdRoleId\' is unknown. Please verify the application is running in Development Fabric or Windows Azure Fabric.');
163
+ }
164
+
165
+ if (strpos($_SERVER['RdRoleId'], 'deployment(') === false) {
166
+ return $_SERVER['RdRoleId'];
167
+ } else {
168
+ $roleIdParts = explode('.', $_SERVER['RdRoleId']);
169
+ return $roleIdParts[0] . '/' . $roleIdParts[2] . '/' . $_SERVER['RdRoleId'];
170
+ }
171
+ }
172
+
173
+ /**
174
+ * Set configuration for current role instance. Only works on Development Fabric or Windows Azure Fabric.
175
+ *
176
+ * @param Microsoft_WindowsAzure_Diagnostics_ConfigurationInstance $configuration Configuration to apply
177
+ * @throws Microsoft_WindowsAzure_Diagnostics_Exception
178
+ */
179
+ public function setConfigurationForCurrentRoleInstance(Microsoft_WindowsAzure_Diagnostics_ConfigurationInstance $configuration)
180
+ {
181
+ if (!isset($_SERVER['RdRoleId'])) {
182
+ throw new Microsoft_WindowsAzure_Diagnostics_Exception('Server variable \'RdRoleId\' is unknown. Please verify the application is running in Development Fabric or Windows Azure Fabric.');
183
+ }
184
+
185
+ $this->setConfigurationForRoleInstance($this->_getCurrentRoleInstanceId(), $configuration);
186
+ }
187
+
188
+ /**
189
+ * Get configuration for a specific role instance
190
+ *
191
+ * @param string $roleInstance Role instance name, can be found in $_SERVER['RdRoleId'] when hosted on Windows Azure.
192
+ * @return Microsoft_WindowsAzure_Diagnostics_ConfigurationInstance
193
+ * @throws Microsoft_WindowsAzure_Diagnostics_Exception
194
+ */
195
+ public function getConfigurationForRoleInstance($roleInstance = null)
196
+ {
197
+ if (is_null($roleInstance)) {
198
+ throw new Microsoft_WindowsAzure_Diagnostics_Exception('Role instance should be specified. Try reading $_SERVER[\'RdRoleId\'] for this information if the application is hosted on Windows Azure Fabric or Development Fabric.');
199
+ }
200
+
201
+ if ($this->_blobStorageClient->blobExists($this->_controlContainer, $roleInstance)) {
202
+ $configurationInstance = new Microsoft_WindowsAzure_Diagnostics_ConfigurationInstance();
203
+ $configurationInstance->loadXml( $this->_blobStorageClient->getBlobData($this->_controlContainer, $roleInstance) );
204
+ return $configurationInstance;
205
+ }
206
+
207
+ return new Microsoft_WindowsAzure_Diagnostics_ConfigurationInstance();
208
+ }
209
+
210
+ /**
211
+ * Set configuration for a specific role instance
212
+ *
213
+ * @param string $roleInstance Role instance name, can be found in $_SERVER['RdRoleId'] when hosted on Windows Azure.
214
+ * @param Microsoft_WindowsAzure_Diagnostics_ConfigurationInstance $configuration Configuration to apply
215
+ * @throws Microsoft_WindowsAzure_Diagnostics_Exception
216
+ */
217
+ public function setConfigurationForRoleInstance($roleInstance = null, Microsoft_WindowsAzure_Diagnostics_ConfigurationInstance $configuration)
218
+ {
219
+ if (is_null($roleInstance)) {
220
+ throw new Microsoft_WindowsAzure_Diagnostics_Exception('Role instance should be specified. Try reading $_SERVER[\'RdRoleId\'] for this information if the application is hosted on Windows Azure Fabric or Development Fabric.');
221
+ }
222
+
223
+ $this->_blobStorageClient->putBlobData($this->_controlContainer, $roleInstance, $configuration->toXml(), array(), null, array('Content-Type' => 'text/xml'));
224
+ }
225
+ }
app/libs/Microsoft/WindowsAzure/Diagnostics/PerformanceCounterSubscription.php ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Diagnostics
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 45989 2010-05-03 12:19:10Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Diagnostics_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Diagnostics/Exception.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Diagnostics/ConfigurationObjectBaseAbstract.php';
45
+
46
+ /**
47
+ * @category Microsoft
48
+ * @package Microsoft_WindowsAzure
49
+ * @subpackage Diagnostics
50
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
51
+ * @license http://phpazure.codeplex.com/license
52
+ *
53
+ * @property string CounterSpecifier Counter specifier
54
+ * @property int SampleRateInSeconds Sample rate in seconds
55
+ */
56
+ class Microsoft_WindowsAzure_Diagnostics_PerformanceCounterSubscription
57
+ extends Microsoft_WindowsAzure_Diagnostics_ConfigurationObjectBaseAbstract
58
+ {
59
+ /**
60
+ * Constructor
61
+ *
62
+ * @param string $counterSpecifier Counter specifier
63
+ * @param int $sampleRateInSeconds Sample rate in seconds
64
+ */
65
+ public function __construct($counterSpecifier, $sampleRateInSeconds = 1)
66
+ {
67
+ $this->_data = array(
68
+ 'counterspecifier' => $counterSpecifier,
69
+ 'samplerateinseconds' => $sampleRateInSeconds
70
+ );
71
+ }
72
+ }
app/libs/Microsoft/WindowsAzure/Exception.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Exception
31
+ * @version $Id: Exception.php 45259 2010-04-16 12:13:55Z unknown $
32
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
33
+ * @license http://phpazure.codeplex.com/license
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_Exception
38
+ */
39
+ require_once 'Microsoft/Exception.php';
40
+
41
+ /**
42
+ * @category Microsoft
43
+ * @package Microsoft_WindowsAzure
44
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
45
+ * @license http://phpazure.codeplex.com/license
46
+ */
47
+ class Microsoft_WindowsAzure_Exception extends Microsoft_Exception
48
+ {}
app/libs/Microsoft/WindowsAzure/RetryPolicy/Exception.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Exception
31
+ * @version $Id: Exception.php 45259 2010-04-16 12:13:55Z unknown $
32
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
33
+ * @license http://phpazure.codeplex.com/license
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Exception.php';
40
+
41
+ /**
42
+ * @category Microsoft
43
+ * @package Microsoft_WindowsAzure
44
+ * @subpackage RetryPolicy
45
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
46
+ * @license http://phpazure.codeplex.com/license
47
+ */
48
+ class Microsoft_WindowsAzure_RetryPolicy_Exception extends Microsoft_WindowsAzure_Exception
49
+ {}
app/libs/Microsoft/WindowsAzure/RetryPolicy/NoRetry.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage RetryPolicy
31
+ * @version $Id: NoRetry.php 45259 2010-04-16 12:13:55Z unknown $
32
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
33
+ * @license http://phpazure.codeplex.com/license
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/RetryPolicy/RetryPolicyAbstract.php';
40
+
41
+ /**
42
+ * @category Microsoft
43
+ * @package Microsoft_WindowsAzure
44
+ * @subpackage RetryPolicy
45
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
46
+ * @license http://phpazure.codeplex.com/license
47
+ */
48
+ class Microsoft_WindowsAzure_RetryPolicy_NoRetry extends Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract
49
+ {
50
+ /**
51
+ * Execute function under retry policy
52
+ *
53
+ * @param string|array $function Function to execute
54
+ * @param array $parameters Parameters for function call
55
+ * @return mixed
56
+ */
57
+ public function execute($function, $parameters = array())
58
+ {
59
+ $returnValue = null;
60
+
61
+ try
62
+ {
63
+ $returnValue = call_user_func_array($function, $parameters);
64
+ return $returnValue;
65
+ }
66
+ catch (Exception $ex)
67
+ {
68
+ throw $ex;
69
+ }
70
+ }
71
+ }
app/libs/Microsoft/WindowsAzure/RetryPolicy/RetryN.php ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage RetryPolicy
31
+ * @version $Id: RetryN.php 45259 2010-04-16 12:13:55Z unknown $
32
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
33
+ * @license http://phpazure.codeplex.com/license
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/RetryPolicy/RetryPolicyAbstract.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_RetryPolicy_Exception
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/RetryPolicy/Exception.php';
45
+
46
+ /**
47
+ * @category Microsoft
48
+ * @package Microsoft_WindowsAzure
49
+ * @subpackage RetryPolicy
50
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
51
+ * @license http://phpazure.codeplex.com/license
52
+ */
53
+ class Microsoft_WindowsAzure_RetryPolicy_RetryN extends Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract
54
+ {
55
+ /**
56
+ * Number of retries
57
+ *
58
+ * @var int
59
+ */
60
+ protected $_retryCount = 1;
61
+
62
+ /**
63
+ * Interval between retries (in milliseconds)
64
+ *
65
+ * @var int
66
+ */
67
+ protected $_retryInterval = 0;
68
+
69
+ /**
70
+ * Constructor
71
+ *
72
+ * @param int $count Number of retries
73
+ * @param int $intervalBetweenRetries Interval between retries (in milliseconds)
74
+ */
75
+ public function __construct($count = 1, $intervalBetweenRetries = 0)
76
+ {
77
+ $this->_retryCount = $count;
78
+ $this->_retryInterval = $intervalBetweenRetries;
79
+ }
80
+
81
+ /**
82
+ * Execute function under retry policy
83
+ *
84
+ * @param string|array $function Function to execute
85
+ * @param array $parameters Parameters for function call
86
+ * @return mixed
87
+ */
88
+ public function execute($function, $parameters = array())
89
+ {
90
+ $returnValue = null;
91
+
92
+ for ($retriesLeft = $this->_retryCount; $retriesLeft >= 0; --$retriesLeft) {
93
+ try {
94
+ $returnValue = call_user_func_array($function, $parameters);
95
+ return $returnValue;
96
+ } catch (Exception $ex) {
97
+ if ($retriesLeft == 1) {
98
+ throw new Microsoft_WindowsAzure_RetryPolicy_Exception("Exceeded retry count of " . $this->_retryCount . ". " . $ex->getMessage());
99
+ }
100
+
101
+ usleep($this->_retryInterval * 1000);
102
+ }
103
+ }
104
+ }
105
+ }
app/libs/Microsoft/WindowsAzure/RetryPolicy/RetryPolicyAbstract.php ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage RetryPolicy
31
+ * @version $Id: RetryPolicy.php 28585 2009-09-07 12:12:56Z unknown $
32
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
33
+ * @license http://phpazure.codeplex.com/license
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Exception.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_RetryPolicy_NoRetry
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/RetryPolicy/NoRetry.php';
45
+
46
+ /**
47
+ * @see Microsoft_WindowsAzure_RetryPolicy_RetryN
48
+ */
49
+ require_once 'Microsoft/WindowsAzure/RetryPolicy/RetryN.php';
50
+
51
+ /**
52
+ * @category Microsoft
53
+ * @package Microsoft_WindowsAzure
54
+ * @subpackage RetryPolicy
55
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
56
+ * @license http://phpazure.codeplex.com/license
57
+ */
58
+ abstract class Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract
59
+ {
60
+ /**
61
+ * Execute function under retry policy
62
+ *
63
+ * @param string|array $function Function to execute
64
+ * @param array $parameters Parameters for function call
65
+ * @return mixed
66
+ */
67
+ public abstract function execute($function, $parameters = array());
68
+
69
+ /**
70
+ * Create a Microsoft_WindowsAzure_RetryPolicy_NoRetry instance
71
+ *
72
+ * @return Microsoft_WindowsAzure_RetryPolicy_NoRetry
73
+ */
74
+ public static function noRetry()
75
+ {
76
+ return new Microsoft_WindowsAzure_RetryPolicy_NoRetry();
77
+ }
78
+
79
+ /**
80
+ * Create a Microsoft_WindowsAzure_RetryPolicy_RetryN instance
81
+ *
82
+ * @param int $count Number of retries
83
+ * @param int $intervalBetweenRetries Interval between retries (in milliseconds)
84
+ * @return Microsoft_WindowsAzure_RetryPolicy_RetryN
85
+ */
86
+ public static function retryN($count = 1, $intervalBetweenRetries = 0)
87
+ {
88
+ return new Microsoft_WindowsAzure_RetryPolicy_RetryN($count, $intervalBetweenRetries);
89
+ }
90
+ }
app/libs/Microsoft/WindowsAzure/SessionHandler.php ADDED
@@ -0,0 +1,230 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Session
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 21617 2009-06-12 10:46:31Z unknown $
34
+ */
35
+
36
+ /** Microsoft_WindowsAzure_Storage_Table */
37
+ require_once 'Microsoft/WindowsAzure/Storage/Table.php';
38
+
39
+ /**
40
+ * @see Microsoft_WindowsAzure_Exception
41
+ */
42
+ require_once 'Microsoft/WindowsAzure/Exception.php';
43
+
44
+ /**
45
+ * @category Microsoft
46
+ * @package Microsoft_WindowsAzure
47
+ * @subpackage Session
48
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
49
+ * @license http://phpazure.codeplex.com/license
50
+ */
51
+ class Microsoft_WindowsAzure_SessionHandler
52
+ {
53
+ /**
54
+ * Table storage
55
+ *
56
+ * @var Microsoft_WindowsAzure_Storage_Table
57
+ */
58
+ protected $_tableStorage;
59
+
60
+ /**
61
+ * Session table name
62
+ *
63
+ * @var string
64
+ */
65
+ protected $_sessionTable;
66
+
67
+ /**
68
+ * Session table partition
69
+ *
70
+ * @var string
71
+ */
72
+ protected $_sessionTablePartition;
73
+
74
+ /**
75
+ * Creates a new Microsoft_WindowsAzure_SessionHandler instance
76
+ *
77
+ * @param Microsoft_WindowsAzure_Storage_Table $tableStorage Table storage
78
+ * @param string $sessionTable Session table name
79
+ * @param string $sessionTablePartition Session table partition
80
+ */
81
+ public function __construct(Microsoft_WindowsAzure_Storage_Table $tableStorage, $sessionTable = 'phpsessions', $sessionTablePartition = 'sessions')
82
+ {
83
+ // Set properties
84
+ $this->_tableStorage = $tableStorage;
85
+ $this->_sessionTable = $sessionTable;
86
+ $this->_sessionTablePartition = $sessionTablePartition;
87
+ }
88
+
89
+ /**
90
+ * Registers the current session handler as PHP's session handler
91
+ *
92
+ * @return boolean
93
+ */
94
+ public function register()
95
+ {
96
+ return session_set_save_handler(array($this, 'open'),
97
+ array($this, 'close'),
98
+ array($this, 'read'),
99
+ array($this, 'write'),
100
+ array($this, 'destroy'),
101
+ array($this, 'gc')
102
+ );
103
+ }
104
+
105
+ /**
106
+ * Open the session store
107
+ *
108
+ * @return bool
109
+ */
110
+ public function open()
111
+ {
112
+ // Make sure table exists
113
+ $tableExists = $this->_tableStorage->tableExists($this->_sessionTable);
114
+ if (!$tableExists) {
115
+ $this->_tableStorage->createTable($this->_sessionTable);
116
+ }
117
+
118
+ // Ok!
119
+ return true;
120
+ }
121
+
122
+ /**
123
+ * Close the session store
124
+ *
125
+ * @return bool
126
+ */
127
+ public function close()
128
+ {
129
+ return true;
130
+ }
131
+
132
+ /**
133
+ * Read a specific session
134
+ *
135
+ * @param int $id Session Id
136
+ * @return string
137
+ */
138
+ public function read($id)
139
+ {
140
+ try
141
+ {
142
+ $sessionRecord = $this->_tableStorage->retrieveEntityById(
143
+ $this->_sessionTable,
144
+ $this->_sessionTablePartition,
145
+ $id
146
+ );
147
+ return base64_decode($sessionRecord->serializedData);
148
+ }
149
+ catch (Microsoft_WindowsAzure_Exception $ex)
150
+ {
151
+ return '';
152
+ }
153
+ }
154
+
155
+ /**
156
+ * Write a specific session
157
+ *
158
+ * @param int $id Session Id
159
+ * @param string $serializedData Serialized PHP object
160
+ */
161
+ public function write($id, $serializedData)
162
+ {
163
+ $sessionRecord = new Microsoft_WindowsAzure_Storage_DynamicTableEntity($this->_sessionTablePartition, $id);
164
+ $sessionRecord->sessionExpires = time();
165
+ $sessionRecord->serializedData = base64_encode($serializedData);
166
+
167
+ $sessionRecord->setAzurePropertyType('sessionExpires', 'Edm.Int32');
168
+
169
+ try
170
+ {
171
+ $this->_tableStorage->updateEntity($this->_sessionTable, $sessionRecord);
172
+ }
173
+ catch (Microsoft_WindowsAzure_Exception $unknownRecord)
174
+ {
175
+ $this->_tableStorage->insertEntity($this->_sessionTable, $sessionRecord);
176
+ }
177
+ }
178
+
179
+ /**
180
+ * Destroy a specific session
181
+ *
182
+ * @param int $id Session Id
183
+ * @return boolean
184
+ */
185
+ public function destroy($id)
186
+ {
187
+ try
188
+ {
189
+ $sessionRecord = $this->_tableStorage->retrieveEntityById(
190
+ $this->_sessionTable,
191
+ $this->_sessionTablePartition,
192
+ $id
193
+ );
194
+ $this->_tableStorage->deleteEntity($this->_sessionTable, $sessionRecord);
195
+
196
+ return true;
197
+ }
198
+ catch (Microsoft_WindowsAzure_Exception $ex)
199
+ {
200
+ return false;
201
+ }
202
+ }
203
+
204
+ /**
205
+ * Garbage collector
206
+ *
207
+ * @param int $lifeTime Session maximal lifetime
208
+ * @see session.gc_divisor 100
209
+ * @see session.gc_maxlifetime 1440
210
+ * @see session.gc_probability 1
211
+ * @usage Execution rate 1/100 (session.gc_probability/session.gc_divisor)
212
+ * @return boolean
213
+ */
214
+ public function gc($lifeTime)
215
+ {
216
+ try
217
+ {
218
+ $result = $this->_tableStorage->retrieveEntities($this->_sessionTable, 'PartitionKey eq \'' . $this->_sessionTablePartition . '\' and sessionExpires lt ' . (time() - $lifeTime));
219
+ foreach ($result as $sessionRecord)
220
+ {
221
+ $this->_tableStorage->deleteEntity($this->_sessionTable, $sessionRecord);
222
+ }
223
+ return true;
224
+ }
225
+ catch (Microsoft_WindowsAzure_exception $ex)
226
+ {
227
+ return false;
228
+ }
229
+ }
230
+ }
app/libs/Microsoft/WindowsAzure/Storage.php ADDED
@@ -0,0 +1,586 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Storage
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 51671 2010-09-30 08:33:45Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Credentials_CredentialsAbstract
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Credentials/CredentialsAbstract.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Credentials_SharedKey
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Credentials/SharedKey.php';
45
+
46
+ /**
47
+ * @see Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract
48
+ */
49
+ require_once 'Microsoft/WindowsAzure/RetryPolicy/RetryPolicyAbstract.php';
50
+
51
+ /**
52
+ * @see Microsoft_WindowsAzure_Exception
53
+ */
54
+ require_once 'Microsoft/WindowsAzure/Exception.php';
55
+
56
+ /**
57
+ * @see Microsoft_Http_Client
58
+ */
59
+ require_once 'Microsoft/Http/Client.php';
60
+
61
+ /**
62
+ * @see Microsoft_Http_Response
63
+ */
64
+ require_once 'Microsoft/Http/Response.php';
65
+
66
+ /**
67
+ * @category Microsoft
68
+ * @package Microsoft_WindowsAzure
69
+ * @subpackage Storage
70
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
71
+ * @license http://phpazure.codeplex.com/license
72
+ */
73
+ class Microsoft_WindowsAzure_Storage
74
+ {
75
+ /**
76
+ * Development storage URLS
77
+ */
78
+ const URL_DEV_BLOB = "127.0.0.1:10000";
79
+ const URL_DEV_QUEUE = "127.0.0.1:10001";
80
+ const URL_DEV_TABLE = "127.0.0.1:10002";
81
+
82
+ /**
83
+ * Live storage URLS
84
+ */
85
+ const URL_CLOUD_BLOB = "blob.core.windows.net";
86
+ const URL_CLOUD_QUEUE = "queue.core.windows.net";
87
+ const URL_CLOUD_TABLE = "table.core.windows.net";
88
+
89
+ /**
90
+ * Resource types
91
+ */
92
+ const RESOURCE_UNKNOWN = "unknown";
93
+ const RESOURCE_CONTAINER = "c";
94
+ const RESOURCE_BLOB = "b";
95
+ const RESOURCE_TABLE = "t";
96
+ const RESOURCE_ENTITY = "e";
97
+ const RESOURCE_QUEUE = "q";
98
+
99
+ /**
100
+ * HTTP header prefixes
101
+ */
102
+ const PREFIX_PROPERTIES = "x-ms-prop-";
103
+ const PREFIX_METADATA = "x-ms-meta-";
104
+ const PREFIX_STORAGE_HEADER = "x-ms-";
105
+
106
+ /**
107
+ * Current API version
108
+ *
109
+ * @var string
110
+ */
111
+ protected $_apiVersion = '2009-09-19';
112
+
113
+ /**
114
+ * Storage host name
115
+ *
116
+ * @var string
117
+ */
118
+ protected $_host = '';
119
+
120
+ /**
121
+ * Account name for Windows Azure
122
+ *
123
+ * @var string
124
+ */
125
+ protected $_accountName = '';
126
+
127
+ /**
128
+ * Account key for Windows Azure
129
+ *
130
+ * @var string
131
+ */
132
+ protected $_accountKey = '';
133
+
134
+ /**
135
+ * Use path-style URI's
136
+ *
137
+ * @var boolean
138
+ */
139
+ protected $_usePathStyleUri = false;
140
+
141
+ /**
142
+ * Microsoft_WindowsAzure_Credentials_CredentialsAbstract instance
143
+ *
144
+ * @var Microsoft_WindowsAzure_Credentials_CredentialsAbstract
145
+ */
146
+ protected $_credentials = null;
147
+
148
+ /**
149
+ * Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract instance
150
+ *
151
+ * @var Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract
152
+ */
153
+ protected $_retryPolicy = null;
154
+
155
+ /**
156
+ * Microsoft_Http_Client channel used for communication with REST services
157
+ *
158
+ * @var Microsoft_Http_Client
159
+ */
160
+ protected $_httpClientChannel = null;
161
+
162
+ /**
163
+ * Use proxy?
164
+ *
165
+ * @var boolean
166
+ */
167
+ protected $_useProxy = false;
168
+
169
+ /**
170
+ * Proxy url
171
+ *
172
+ * @var string
173
+ */
174
+ protected $_proxyUrl = '';
175
+
176
+ /**
177
+ * Proxy port
178
+ *
179
+ * @var int
180
+ */
181
+ protected $_proxyPort = 80;
182
+
183
+ /**
184
+ * Proxy credentials
185
+ *
186
+ * @var string
187
+ */
188
+ protected $_proxyCredentials = '';
189
+
190
+ /**
191
+ * Creates a new Microsoft_WindowsAzure_Storage instance
192
+ *
193
+ * @param string $host Storage host name
194
+ * @param string $accountName Account name for Windows Azure
195
+ * @param string $accountKey Account key for Windows Azure
196
+ * @param boolean $usePathStyleUri Use path-style URI's
197
+ * @param Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy Retry policy to use when making requests
198
+ */
199
+ public function __construct(
200
+ $host = self::URL_DEV_BLOB,
201
+ $accountName = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_ACCOUNT,
202
+ $accountKey = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_KEY,
203
+ $usePathStyleUri = false,
204
+ Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy = null
205
+ ) {
206
+ $this->_host = $host;
207
+ $this->_accountName = $accountName;
208
+ $this->_accountKey = $accountKey;
209
+ $this->_usePathStyleUri = $usePathStyleUri;
210
+
211
+ // Using local storage?
212
+ if (!$this->_usePathStyleUri
213
+ && ($this->_host == self::URL_DEV_BLOB
214
+ || $this->_host == self::URL_DEV_QUEUE
215
+ || $this->_host == self::URL_DEV_TABLE)
216
+ ) {
217
+ // Local storage
218
+ $this->_usePathStyleUri = true;
219
+ }
220
+
221
+ if (is_null($this->_credentials)) {
222
+ $this->_credentials = new Microsoft_WindowsAzure_Credentials_SharedKey(
223
+ $this->_accountName, $this->_accountKey, $this->_usePathStyleUri);
224
+ }
225
+
226
+ $this->_retryPolicy = $retryPolicy;
227
+ if (is_null($this->_retryPolicy)) {
228
+ $this->_retryPolicy = Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract::noRetry();
229
+ }
230
+
231
+ // Setup default Microsoft_Http_Client channel
232
+ $options = array(
233
+ 'adapter' => 'Microsoft_Http_Client_Adapter_Proxy'
234
+ );
235
+ if (function_exists('curl_init')) {
236
+ // Set cURL options if cURL is used afterwards
237
+ $options['curloptions'] = array(
238
+ CURLOPT_FOLLOWLOCATION => true,
239
+ CURLOPT_TIMEOUT => 120,
240
+ );
241
+ }
242
+ $this->_httpClientChannel = new Microsoft_Http_Client(null, $options);
243
+ }
244
+
245
+ /**
246
+ * Set the HTTP client channel to use
247
+ *
248
+ * @param Microsoft_Http_Client_Adapter_Interface|string $adapterInstance Adapter instance or adapter class name.
249
+ */
250
+ public function setHttpClientChannel($adapterInstance = 'Microsoft_Http_Client_Adapter_Proxy')
251
+ {
252
+ $this->_httpClientChannel->setAdapter($adapterInstance);
253
+ }
254
+
255
+ /**
256
+ * Retrieve HTTP client channel
257
+ *
258
+ * @return Microsoft_Http_Client_Adapter_Interface
259
+ */
260
+ public function getHttpClientChannel()
261
+ {
262
+ return $this->_httpClientChannel;
263
+ }
264
+
265
+ /**
266
+ * Set retry policy to use when making requests
267
+ *
268
+ * @param Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy Retry policy to use when making requests
269
+ */
270
+ public function setRetryPolicy(Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy = null)
271
+ {
272
+ $this->_retryPolicy = $retryPolicy;
273
+ if (is_null($this->_retryPolicy)) {
274
+ $this->_retryPolicy = Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract::noRetry();
275
+ }
276
+ }
277
+
278
+ /**
279
+ * Set proxy
280
+ *
281
+ * @param boolean $useProxy Use proxy?
282
+ * @param string $proxyUrl Proxy URL
283
+ * @param int $proxyPort Proxy port
284
+ * @param string $proxyCredentials Proxy credentials
285
+ */
286
+ public function setProxy($useProxy = false, $proxyUrl = '', $proxyPort = 80, $proxyCredentials = '')
287
+ {
288
+ $this->_useProxy = $useProxy;
289
+ $this->_proxyUrl = $proxyUrl;
290
+ $this->_proxyPort = $proxyPort;
291
+ $this->_proxyCredentials = $proxyCredentials;
292
+
293
+ if ($this->_useProxy) {
294
+ $credentials = explode(':', $this->_proxyCredentials);
295
+
296
+ $this->_httpClientChannel->setConfig(array(
297
+ 'proxy_host' => $this->_proxyUrl,
298
+ 'proxy_port' => $this->_proxyPort,
299
+ 'proxy_user' => $credentials[0],
300
+ 'proxy_pass' => $credentials[1],
301
+ ));
302
+ } else {
303
+ $this->_httpClientChannel->setConfig(array(
304
+ 'proxy_host' => '',
305
+ 'proxy_port' => 8080,
306
+ 'proxy_user' => '',
307
+ 'proxy_pass' => '',
308
+ ));
309
+ }
310
+ }
311
+
312
+ /**
313
+ * Returns the Windows Azure account name
314
+ *
315
+ * @return string
316
+ */
317
+ public function getAccountName()
318
+ {
319
+ return $this->_accountName;
320
+ }
321
+
322
+ /**
323
+ * Get base URL for creating requests
324
+ *
325
+ * @return string
326
+ */
327
+ public function getBaseUrl()
328
+ {
329
+ if ($this->_usePathStyleUri) {
330
+ return 'http://' . $this->_host . '/' . $this->_accountName;
331
+ } else {
332
+ return 'http://' . $this->_accountName . '.' . $this->_host;
333
+ }
334
+ }
335
+
336
+ /**
337
+ * Set Microsoft_WindowsAzure_Credentials_CredentialsAbstract instance
338
+ *
339
+ * @param Microsoft_WindowsAzure_Credentials_CredentialsAbstract $credentials Microsoft_WindowsAzure_Credentials_CredentialsAbstract instance to use for request signing.
340
+ */
341
+ public function setCredentials(Microsoft_WindowsAzure_Credentials_CredentialsAbstract $credentials)
342
+ {
343
+ $this->_credentials = $credentials;
344
+ $this->_credentials->setAccountName($this->_accountName);
345
+ $this->_credentials->setAccountkey($this->_accountKey);
346
+ $this->_credentials->setUsePathStyleUri($this->_usePathStyleUri);
347
+ }
348
+
349
+ /**
350
+ * Get Microsoft_WindowsAzure_Credentials_CredentialsAbstract instance
351
+ *
352
+ * @return Microsoft_WindowsAzure_Credentials_CredentialsAbstract
353
+ */
354
+ public function getCredentials()
355
+ {
356
+ return $this->_credentials;
357
+ }
358
+
359
+ /**
360
+ * Perform request using Microsoft_Http_Client channel
361
+ *
362
+ * @param string $path Path
363
+ * @param string $queryString Query string
364
+ * @param string $httpVerb HTTP verb the request will use
365
+ * @param array $headers x-ms headers to add
366
+ * @param boolean $forTableStorage Is the request for table storage?
367
+ * @param mixed $rawData Optional RAW HTTP data to be sent over the wire
368
+ * @param string $resourceType Resource type
369
+ * @param string $requiredPermission Required permission
370
+ * @return Microsoft_Http_Response
371
+ */
372
+ protected function _performRequest(
373
+ $path = '/',
374
+ $queryString = '',
375
+ $httpVerb = Microsoft_Http_Client::GET,
376
+ $headers = array(),
377
+ $forTableStorage = false,
378
+ $rawData = null,
379
+ $resourceType = Microsoft_WindowsAzure_Storage::RESOURCE_UNKNOWN,
380
+ $requiredPermission = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ
381
+ ) {
382
+ // Clean path
383
+ if (strpos($path, '/') !== 0) {
384
+ $path = '/' . $path;
385
+ }
386
+
387
+ // Clean headers
388
+ if (is_null($headers)) {
389
+ $headers = array();
390
+ }
391
+
392
+ // Ensure cUrl will also work correctly:
393
+ // - disable Content-Type if required
394
+ // - disable Expect: 100 Continue
395
+ if (!isset($headers["Content-Type"])) {
396
+ $headers["Content-Type"] = '';
397
+ }
398
+ $headers["Expect"]= '';
399
+
400
+ // Add version header
401
+ $headers['x-ms-version'] = $this->_apiVersion;
402
+
403
+ // URL encoding
404
+ $path = self::urlencode($path);
405
+ $queryString = self::urlencode($queryString);
406
+
407
+ // Generate URL and sign request
408
+ $requestUrl = $this->_credentials
409
+ ->signRequestUrl($this->getBaseUrl() . $path . $queryString, $resourceType, $requiredPermission);
410
+ $requestHeaders = $this->_credentials
411
+ ->signRequestHeaders($httpVerb, $path, $queryString, $headers, $forTableStorage, $resourceType, $requiredPermission, $rawData);
412
+
413
+ // Prepare request
414
+ $this->_httpClientChannel->resetParameters(true);
415
+ $this->_httpClientChannel->setUri($requestUrl);
416
+ $this->_httpClientChannel->setHeaders($requestHeaders);
417
+ $this->_httpClientChannel->setRawData($rawData);
418
+
419
+ // Execute request
420
+ $response = $this->_retryPolicy->execute(
421
+ array($this->_httpClientChannel, 'request'),
422
+ array($httpVerb)
423
+ );
424
+
425
+ return $response;
426
+ }
427
+
428
+ /**
429
+ * Parse result from Microsoft_Http_Response
430
+ *
431
+ * @param Microsoft_Http_Response $response Response from HTTP call
432
+ * @return object
433
+ * @throws Microsoft_WindowsAzure_Exception
434
+ */
435
+ protected function _parseResponse(Microsoft_Http_Response $response = null)
436
+ {
437
+ if (is_null($response)) {
438
+ throw new Microsoft_WindowsAzure_Exception('Response should not be null.');
439
+ }
440
+
441
+ $xml = @simplexml_load_string($response->getBody());
442
+
443
+ if ($xml !== false) {
444
+ // Fetch all namespaces
445
+ $namespaces = array_merge($xml->getNamespaces(true), $xml->getDocNamespaces(true));
446
+
447
+ // Register all namespace prefixes
448
+ foreach ($namespaces as $prefix => $ns) {
449
+ if ($prefix != '') {
450
+ $xml->registerXPathNamespace($prefix, $ns);
451
+ }
452
+ }
453
+ }
454
+
455
+ return $xml;
456
+ }
457
+
458
+ /**
459
+ * Generate metadata headers
460
+ *
461
+ * @param array $metadata
462
+ * @return HTTP headers containing metadata
463
+ */
464
+ protected function _generateMetadataHeaders($metadata = array())
465
+ {
466
+ // Validate
467
+ if (!is_array($metadata)) {
468
+ return array();
469
+ }
470
+
471
+ // Return headers
472
+ $headers = array();
473
+ foreach ($metadata as $key => $value) {
474
+ if (strpos($value, "\r") !== false || strpos($value, "\n") !== false) {
475
+ throw new Microsoft_WindowsAzure_Exception('Metadata cannot contain newline characters.');
476
+ }
477
+
478
+ if (!self::isValidMetadataName($key)) {
479
+ throw new Microsoft_WindowsAzure_Exception('Metadata name does not adhere to metadata naming conventions. See http://msdn.microsoft.com/en-us/library/aa664670(VS.71).aspx for more information.');
480
+ }
481
+
482
+ $headers["x-ms-meta-" . strtolower($key)] = $value;
483
+ }
484
+ return $headers;
485
+ }
486
+
487
+ /**
488
+ * Parse metadata headers
489
+ *
490
+ * @param array $headers HTTP headers containing metadata
491
+ * @return array
492
+ */
493
+ protected function _parseMetadataHeaders($headers = array())
494
+ {
495
+ // Validate
496
+ if (!is_array($headers)) {
497
+ return array();
498
+ }
499
+
500
+ // Return metadata
501
+ $metadata = array();
502
+ foreach ($headers as $key => $value) {
503
+ if (substr(strtolower($key), 0, 10) == "x-ms-meta-") {
504
+ $metadata[str_replace("x-ms-meta-", '', strtolower($key))] = $value;
505
+ }
506
+ }
507
+ return $metadata;
508
+ }
509
+
510
+ /**
511
+ * Parse metadata XML
512
+ *
513
+ * @param SimpleXMLElement $parentElement Element containing the Metadata element.
514
+ * @return array
515
+ */
516
+ protected function _parseMetadataElement($element = null)
517
+ {
518
+ // Metadata present?
519
+ if (!is_null($element) && isset($element->Metadata) && !is_null($element->Metadata)) {
520
+ return get_object_vars($element->Metadata);
521
+ }
522
+
523
+ return array();
524
+ }
525
+
526
+ /**
527
+ * Generate ISO 8601 compliant date string in UTC time zone
528
+ *
529
+ * @param int $timestamp
530
+ * @return string
531
+ */
532
+ public function isoDate($timestamp = null)
533
+ {
534
+ $tz = @date_default_timezone_get();
535
+ @date_default_timezone_set('UTC');
536
+
537
+ if (is_null($timestamp)) {
538
+ $timestamp = time();
539
+ }
540
+
541
+ $returnValue = str_replace('+00:00', '.0000000Z', @date('c', $timestamp));
542
+ @date_default_timezone_set($tz);
543
+ return $returnValue;
544
+ }
545
+
546
+ /**
547
+ * URL encode function
548
+ *
549
+ * @param string $value Value to encode
550
+ * @return string Encoded value
551
+ */
552
+ public static function urlencode($value)
553
+ {
554
+ return str_replace(' ', '%20', $value);
555
+ }
556
+
557
+ /**
558
+ * Is valid metadata name?
559
+ *
560
+ * @param string $metadataName Metadata name
561
+ * @return boolean
562
+ */
563
+ public static function isValidMetadataName($metadataName = '')
564
+ {
565
+ if (preg_match("/^[a-zA-Z0-9_@][a-zA-Z0-9_]*$/", $metadataName) === 0) {
566
+ return false;
567
+ }
568
+
569
+ if ($metadataName == '') {
570
+ return false;
571
+ }
572
+
573
+ return true;
574
+ }
575
+
576
+ /**
577
+ * Builds a query string from an array of elements
578
+ *
579
+ * @param array Array of elements
580
+ * @return string Assembled query string
581
+ */
582
+ public static function createQueryStringFromArray($queryString)
583
+ {
584
+ return count($queryString) > 0 ? '?' . implode('&', $queryString) : '';
585
+ }
586
+ }
app/libs/Microsoft/WindowsAzure/Storage/Batch.php ADDED
@@ -0,0 +1,261 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Storage
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 21617 2009-06-12 10:46:31Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Exception.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Storage_BatchStorageAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Storage/BatchStorageAbstract.php';
45
+
46
+ /**
47
+ * @category Microsoft
48
+ * @package Microsoft_WindowsAzure
49
+ * @subpackage Storage
50
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
51
+ * @license http://phpazure.codeplex.com/license
52
+ */
53
+ class Microsoft_WindowsAzure_Storage_Batch
54
+ {
55
+ /**
56
+ * Storage client the batch is defined on
57
+ *
58
+ * @var Microsoft_WindowsAzure_Storage_BatchStorageAbstract
59
+ */
60
+ protected $_storageClient = null;
61
+
62
+ /**
63
+ * For table storage?
64
+ *
65
+ * @var boolean
66
+ */
67
+ protected $_forTableStorage = false;
68
+
69
+ /**
70
+ * Base URL
71
+ *
72
+ * @var string
73
+ */
74
+ protected $_baseUrl;
75
+
76
+ /**
77
+ * Pending operations
78
+ *
79
+ * @var unknown_type
80
+ */
81
+ protected $_operations = array();
82
+
83
+ /**
84
+ * Does the batch contain a single select?
85
+ *
86
+ * @var boolean
87
+ */
88
+ protected $_isSingleSelect = false;
89
+
90
+ /**
91
+ * Creates a new Microsoft_WindowsAzure_Storage_Batch
92
+ *
93
+ * @param Microsoft_WindowsAzure_Storage_BatchStorageAbstract $storageClient Storage client the batch is defined on
94
+ */
95
+ public function __construct(Microsoft_WindowsAzure_Storage_BatchStorageAbstract $storageClient = null, $baseUrl = '')
96
+ {
97
+ $this->_storageClient = $storageClient;
98
+ $this->_baseUrl = $baseUrl;
99
+ $this->_beginBatch();
100
+ }
101
+
102
+ /**
103
+ * Get base URL for creating requests
104
+ *
105
+ * @return string
106
+ */
107
+ public function getBaseUrl()
108
+ {
109
+ return $this->_baseUrl;
110
+ }
111
+
112
+ /**
113
+ * Starts a new batch operation set
114
+ *
115
+ * @throws Microsoft_WindowsAzure_Exception
116
+ */
117
+ protected function _beginBatch()
118
+ {
119
+ $this->_storageClient->setCurrentBatch($this);
120
+ }
121
+
122
+ /**
123
+ * Cleanup current batch
124
+ */
125
+ protected function _clean()
126
+ {
127
+ unset($this->_operations);
128
+ $this->_storageClient->setCurrentBatch(null);
129
+ $this->_storageClient = null;
130
+ unset($this);
131
+ }
132
+
133
+ /**
134
+ * Enlist operation in current batch
135
+ *
136
+ * @param string $path Path
137
+ * @param string $queryString Query string
138
+ * @param string $httpVerb HTTP verb the request will use
139
+ * @param array $headers x-ms headers to add
140
+ * @param boolean $forTableStorage Is the request for table storage?
141
+ * @param mixed $rawData Optional RAW HTTP data to be sent over the wire
142
+ * @throws Microsoft_WindowsAzure_Exception
143
+ */
144
+ public function enlistOperation($path = '/', $queryString = '', $httpVerb = Microsoft_Http_Client::GET, $headers = array(), $forTableStorage = false, $rawData = null)
145
+ {
146
+ // Set _forTableStorage
147
+ if ($forTableStorage) {
148
+ $this->_forTableStorage = true;
149
+ }
150
+
151
+ // Set _isSingleSelect
152
+ if ($httpVerb == Microsoft_Http_Client::GET) {
153
+ if (count($this->_operations) > 0) {
154
+ throw new Microsoft_WindowsAzure_Exception("Select operations can only be performed in an empty batch transaction.");
155
+ }
156
+ $this->_isSingleSelect = true;
157
+ }
158
+
159
+ // Clean path
160
+ if (strpos($path, '/') !== 0) {
161
+ $path = '/' . $path;
162
+ }
163
+
164
+ // Clean headers
165
+ if (is_null($headers)) {
166
+ $headers = array();
167
+ }
168
+
169
+ // URL encoding
170
+ $path = Microsoft_WindowsAzure_Storage::urlencode($path);
171
+ $queryString = Microsoft_WindowsAzure_Storage::urlencode($queryString);
172
+
173
+ // Generate URL
174
+ $requestUrl = $this->getBaseUrl() . $path . $queryString;
175
+
176
+ // Generate $rawData
177
+ if (is_null($rawData)) {
178
+ $rawData = '';
179
+ }
180
+
181
+ // Add headers
182
+ if ($httpVerb != Microsoft_Http_Client::GET) {
183
+ $headers['Content-ID'] = count($this->_operations) + 1;
184
+ if ($httpVerb != Microsoft_Http_Client::DELETE) {
185
+ $headers['Content-Type'] = 'application/atom+xml;type=entry';
186
+ }
187
+ $headers['Content-Length'] = strlen($rawData);
188
+ }
189
+
190
+ // Generate $operation
191
+ $operation = '';
192
+ $operation .= $httpVerb . ' ' . $requestUrl . ' HTTP/1.1' . "\n";
193
+ foreach ($headers as $key => $value)
194
+ {
195
+ $operation .= $key . ': ' . $value . "\n";
196
+ }
197
+ $operation .= "\n";
198
+
199
+ // Add data
200
+ $operation .= $rawData;
201
+
202
+ // Store operation
203
+ $this->_operations[] = $operation;
204
+ }
205
+
206
+ /**
207
+ * Commit current batch
208
+ *
209
+ * @return Microsoft_Http_Response
210
+ * @throws Microsoft_WindowsAzure_Exception
211
+ */
212
+ public function commit()
213
+ {
214
+ // Perform batch
215
+ $response = $this->_storageClient->performBatch($this->_operations, $this->_forTableStorage, $this->_isSingleSelect);
216
+
217
+ // Dispose
218
+ $this->_clean();
219
+
220
+ // Parse response
221
+ $errors = null;
222
+ preg_match_all('/<message (.*)>(.*)<\/message>/', $response->getBody(), $errors);
223
+
224
+ // Error?
225
+ if (count($errors[2]) > 0) {
226
+ throw new Microsoft_WindowsAzure_Exception('An error has occured while committing a batch: ' . $errors[2][0]);
227
+ }
228
+
229
+ // Return
230
+ return $response;
231
+ }
232
+
233
+ /**
234
+ * Rollback current batch
235
+ */
236
+ public function rollback()
237
+ {
238
+ // Dispose
239
+ $this->_clean();
240
+ }
241
+
242
+ /**
243
+ * Get operation count
244
+ *
245
+ * @return integer
246
+ */
247
+ public function getOperationCount()
248
+ {
249
+ return count($this->_operations);
250
+ }
251
+
252
+ /**
253
+ * Is single select?
254
+ *
255
+ * @return boolean
256
+ */
257
+ public function isSingleSelect()
258
+ {
259
+ return $this->_isSingleSelect;
260
+ }
261
+ }
app/libs/Microsoft/WindowsAzure/Storage/BatchStorageAbstract.php ADDED
@@ -0,0 +1,210 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Storage
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Storage.php 21617 2009-06-12 10:46:31Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Storage
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Storage.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Credentials_CredentialsAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Credentials/CredentialsAbstract.php';
45
+
46
+ /**
47
+ * @see Microsoft_WindowsAzure_Exception
48
+ */
49
+ require_once 'Microsoft/WindowsAzure/Exception.php';
50
+
51
+ /**
52
+ * @see Microsoft_WindowsAzure_Storage_Batch
53
+ */
54
+ require_once 'Microsoft/WindowsAzure/Storage/Batch.php';
55
+
56
+ /**
57
+ * @see Microsoft_Http_Client
58
+ */
59
+ require_once 'Microsoft/Http/Client.php';
60
+
61
+ /**
62
+ * @see Microsoft_Http_Response
63
+ */
64
+ require_once 'Microsoft/Http/Response.php';
65
+
66
+ /**
67
+ * @category Microsoft
68
+ * @package Microsoft_WindowsAzure
69
+ * @subpackage Storage
70
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
71
+ * @license http://phpazure.codeplex.com/license
72
+ */
73
+ abstract class Microsoft_WindowsAzure_Storage_BatchStorageAbstract
74
+ extends Microsoft_WindowsAzure_Storage
75
+ {
76
+ /**
77
+ * Current batch
78
+ *
79
+ * @var Microsoft_WindowsAzure_Storage_Batch
80
+ */
81
+ protected $_currentBatch = null;
82
+
83
+ /**
84
+ * Set current batch
85
+ *
86
+ * @param Microsoft_WindowsAzure_Storage_Batch $batch Current batch
87
+ * @throws Microsoft_WindowsAzure_Exception
88
+ */
89
+ public function setCurrentBatch(Microsoft_WindowsAzure_Storage_Batch $batch = null)
90
+ {
91
+ if (!is_null($batch) && $this->isInBatch()) {
92
+ throw new Microsoft_WindowsAzure_Exception('Only one batch can be active at a time.');
93
+ }
94
+ $this->_currentBatch = $batch;
95
+ }
96
+
97
+ /**
98
+ * Get current batch
99
+ *
100
+ * @return Microsoft_WindowsAzure_Storage_Batch
101
+ */
102
+ public function getCurrentBatch()
103
+ {
104
+ return $this->_currentBatch;
105
+ }
106
+
107
+ /**
108
+ * Is there a current batch?
109
+ *
110
+ * @return boolean
111
+ */
112
+ public function isInBatch()
113
+ {
114
+ return !is_null($this->_currentBatch);
115
+ }
116
+
117
+ /**
118
+ * Starts a new batch operation set
119
+ *
120
+ * @return Microsoft_WindowsAzure_Storage_Batch
121
+ * @throws Microsoft_WindowsAzure_Exception
122
+ */
123
+ public function startBatch()
124
+ {
125
+ return new Microsoft_WindowsAzure_Storage_Batch($this, $this->getBaseUrl());
126
+ }
127
+
128
+ /**
129
+ * Perform batch using Microsoft_Http_Client channel, combining all batch operations into one request
130
+ *
131
+ * @param array $operations Operations in batch
132
+ * @param boolean $forTableStorage Is the request for table storage?
133
+ * @param boolean $isSingleSelect Is the request a single select statement?
134
+ * @param string $resourceType Resource type
135
+ * @param string $requiredPermission Required permission
136
+ * @return Microsoft_Http_Response
137
+ */
138
+ public function performBatch($operations = array(), $forTableStorage = false, $isSingleSelect = false, $resourceType = Microsoft_WindowsAzure_Storage::RESOURCE_UNKNOWN, $requiredPermission = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ)
139
+ {
140
+ // Generate boundaries
141
+ $batchBoundary = 'batch_' . md5(time() . microtime());
142
+ $changesetBoundary = 'changeset_' . md5(time() . microtime());
143
+
144
+ // Set headers
145
+ $headers = array();
146
+
147
+ // Add version header
148
+ $headers['x-ms-version'] = $this->_apiVersion;
149
+
150
+ // Add dataservice headers
151
+ $headers['DataServiceVersion'] = '1.0;NetFx';
152
+ $headers['MaxDataServiceVersion'] = '1.0;NetFx';
153
+
154
+ // Add content-type header
155
+ $headers['Content-Type'] = 'multipart/mixed; boundary=' . $batchBoundary;
156
+
157
+ // Set path and query string
158
+ $path = '/$batch';
159
+ $queryString = '';
160
+
161
+ // Set verb
162
+ $httpVerb = Microsoft_Http_Client::POST;
163
+
164
+ // Generate raw data
165
+ $rawData = '';
166
+
167
+ // Single select?
168
+ if ($isSingleSelect) {
169
+ $operation = $operations[0];
170
+ $rawData .= '--' . $batchBoundary . "\n";
171
+ $rawData .= 'Content-Type: application/http' . "\n";
172
+ $rawData .= 'Content-Transfer-Encoding: binary' . "\n\n";
173
+ $rawData .= $operation;
174
+ $rawData .= '--' . $batchBoundary . '--';
175
+ } else {
176
+ $rawData .= '--' . $batchBoundary . "\n";
177
+ $rawData .= 'Content-Type: multipart/mixed; boundary=' . $changesetBoundary . "\n\n";
178
+
179
+ // Add operations
180
+ foreach ($operations as $operation)
181
+ {
182
+ $rawData .= '--' . $changesetBoundary . "\n";
183
+ $rawData .= 'Content-Type: application/http' . "\n";
184
+ $rawData .= 'Content-Transfer-Encoding: binary' . "\n\n";
185
+ $rawData .= $operation;
186
+ }
187
+ $rawData .= '--' . $changesetBoundary . '--' . "\n";
188
+
189
+ $rawData .= '--' . $batchBoundary . '--';
190
+ }
191
+
192
+ // Generate URL and sign request
193
+ $requestUrl = $this->_credentials->signRequestUrl($this->getBaseUrl() . $path . $queryString, $resourceType, $requiredPermission);
194
+ $requestHeaders = $this->_credentials->signRequestHeaders($httpVerb, $path, $queryString, $headers, $forTableStorage, $resourceType, $requiredPermission);
195
+
196
+ // Prepare request
197
+ $this->_httpClientChannel->resetParameters(true);
198
+ $this->_httpClientChannel->setUri($requestUrl);
199
+ $this->_httpClientChannel->setHeaders($requestHeaders);
200
+ $this->_httpClientChannel->setRawData($rawData);
201
+
202
+ // Execute request
203
+ $response = $this->_retryPolicy->execute(
204
+ array($this->_httpClientChannel, 'request'),
205
+ array($httpVerb)
206
+ );
207
+
208
+ return $response;
209
+ }
210
+ }
app/libs/Microsoft/WindowsAzure/Storage/Blob.php ADDED
@@ -0,0 +1,2029 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Storage
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://todo name_todo
33
+ * @version $Id: Blob.php 53747 2010-11-18 19:34:25Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Credentials_CredentialsAbstract_SharedKey
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Credentials/SharedKey.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Credentials_SharedAccessSignature
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Credentials/SharedAccessSignature.php';
45
+
46
+ /**
47
+ * @see Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract
48
+ */
49
+ require_once 'Microsoft/WindowsAzure/RetryPolicy/RetryPolicyAbstract.php';
50
+
51
+ /**
52
+ * @see Microsoft_Http_Client
53
+ */
54
+ require_once 'Microsoft/Http/Client.php';
55
+
56
+ /**
57
+ * @see Microsoft_Http_Response
58
+ */
59
+ require_once 'Microsoft/Http/Response.php';
60
+
61
+ /**
62
+ * @see Microsoft_WindowsAzure_Storage
63
+ */
64
+ require_once 'Microsoft/WindowsAzure/Storage.php';
65
+
66
+ /**
67
+ * @see Microsoft_WindowsAzure_Storage_BlobContainer
68
+ */
69
+ require_once 'Microsoft/WindowsAzure/Storage/BlobContainer.php';
70
+
71
+ /**
72
+ * @see Microsoft_WindowsAzure_Storage_BlobInstance
73
+ */
74
+ require_once 'Microsoft/WindowsAzure/Storage/BlobInstance.php';
75
+
76
+ /**
77
+ * @see Microsoft_WindowsAzure_Storage_PageRegionInstance
78
+ */
79
+ require_once 'Microsoft/WindowsAzure/Storage/PageRegionInstance.php';
80
+
81
+ /**
82
+ * @see Microsoft_WindowsAzure_Storage_LeaseInstance
83
+ */
84
+ require_once 'Microsoft/WindowsAzure/Storage/LeaseInstance.php';
85
+
86
+ /**
87
+ * @see Microsoft_WindowsAzure_Storage_SignedIdentifier
88
+ */
89
+ require_once 'Microsoft/WindowsAzure/Storage/SignedIdentifier.php';
90
+
91
+ /**
92
+ * @see Microsoft_WindowsAzure_Exception
93
+ */
94
+ require_once 'Microsoft/WindowsAzure/Exception.php';
95
+
96
+
97
+ /**
98
+ * @category Microsoft
99
+ * @package Microsoft_WindowsAzure
100
+ * @subpackage Storage
101
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
102
+ * @license http://phpazure.codeplex.com/license
103
+ */
104
+ class Microsoft_WindowsAzure_Storage_Blob extends Microsoft_WindowsAzure_Storage
105
+ {
106
+ /**
107
+ * ACL - Private access
108
+ */
109
+ const ACL_PRIVATE = null;
110
+
111
+ /**
112
+ * ACL - Public access (read all blobs)
113
+ *
114
+ * @deprecated Use ACL_PUBLIC_CONTAINER or ACL_PUBLIC_BLOB instead.
115
+ */
116
+ const ACL_PUBLIC = 'container';
117
+
118
+ /**
119
+ * ACL - Blob Public access (read all blobs)
120
+ */
121
+ const ACL_PUBLIC_BLOB = 'blob';
122
+
123
+ /**
124
+ * ACL - Container Public access (enumerate and read all blobs)
125
+ */
126
+ const ACL_PUBLIC_CONTAINER = 'container';
127
+
128
+ /**
129
+ * Blob lease constants
130
+ */
131
+ const LEASE_ACQUIRE = 'acquire';
132
+ const LEASE_RENEW = 'renew';
133
+ const LEASE_RELEASE = 'release';
134
+ const LEASE_BREAK = 'break';
135
+
136
+ /**
137
+ * Maximal blob size (in bytes)
138
+ */
139
+ const MAX_BLOB_SIZE = 67108864;
140
+
141
+ /**
142
+ * Maximal blob transfer size (in bytes)
143
+ */
144
+ const MAX_BLOB_TRANSFER_SIZE = 4194304;
145
+
146
+ /**
147
+ * Blob types
148
+ */
149
+ const BLOBTYPE_BLOCK = 'BlockBlob';
150
+ const BLOBTYPE_PAGE = 'PageBlob';
151
+
152
+ /**
153
+ * Put page write options
154
+ */
155
+ const PAGE_WRITE_UPDATE = 'update';
156
+ const PAGE_WRITE_CLEAR = 'clear';
157
+
158
+ /**
159
+ * Stream wrapper clients
160
+ *
161
+ * @var array
162
+ */
163
+ protected static $_wrapperClients = array();
164
+
165
+ /**
166
+ * SharedAccessSignature credentials
167
+ *
168
+ * @var Microsoft_WindowsAzure_Credentials_SharedAccessSignature
169
+ */
170
+ private $_sharedAccessSignatureCredentials = null;
171
+
172
+ /**
173
+ * Creates a new Microsoft_WindowsAzure_Storage_Blob instance
174
+ *
175
+ * @param string $host Storage host name
176
+ * @param string $accountName Account name for Windows Azure
177
+ * @param string $accountKey Account key for Windows Azure
178
+ * @param boolean $usePathStyleUri Use path-style URI's
179
+ * @param Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy Retry policy to use when making requests
180
+ */
181
+ public function __construct($host = Microsoft_WindowsAzure_Storage::URL_DEV_BLOB, $accountName = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_ACCOUNT, $accountKey = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_KEY, $usePathStyleUri = false, Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy = null)
182
+ {
183
+ parent::__construct($host, $accountName, $accountKey, $usePathStyleUri, $retryPolicy);
184
+
185
+ // API version
186
+ $this->_apiVersion = '2009-09-19';
187
+
188
+ // SharedAccessSignature credentials
189
+ $this->_sharedAccessSignatureCredentials = new Microsoft_WindowsAzure_Credentials_SharedAccessSignature($accountName, $accountKey, $usePathStyleUri);
190
+ }
191
+
192
+ /**
193
+ * Check if a blob exists
194
+ *
195
+ * @param string $containerName Container name
196
+ * @param string $blobName Blob name
197
+ * @param string $snapshotId Snapshot identifier
198
+ * @return boolean
199
+ */
200
+ public function blobExists($containerName = '', $blobName = '', $snapshotId = null)
201
+ {
202
+ if ($containerName === '') {
203
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
204
+ }
205
+ if (!self::isValidContainerName($containerName)) {
206
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
207
+ }
208
+ if ($blobName === '') {
209
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
210
+ }
211
+
212
+ // Get blob instance
213
+ try {
214
+ $this->getBlobInstance($containerName, $blobName, $snapshotId);
215
+ } catch (Microsoft_WindowsAzure_Exception $e) {
216
+ return false;
217
+ }
218
+
219
+ return true;
220
+ }
221
+
222
+ /**
223
+ * Check if a container exists
224
+ *
225
+ * @param string $containerName Container name
226
+ * @return boolean
227
+ */
228
+ public function containerExists($containerName = '')
229
+ {
230
+ if ($containerName === '') {
231
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
232
+ }
233
+ if (!self::isValidContainerName($containerName)) {
234
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
235
+ }
236
+
237
+ // List containers
238
+ $containers = $this->listContainers($containerName, 1);
239
+ foreach ($containers as $container) {
240
+ if ($container->Name == $containerName) {
241
+ return true;
242
+ }
243
+ }
244
+
245
+ return false;
246
+ }
247
+
248
+ /**
249
+ * Create container
250
+ *
251
+ * @param string $containerName Container name
252
+ * @param array $metadata Key/value pairs of meta data
253
+ * @return object Container properties
254
+ * @throws Microsoft_WindowsAzure_Exception
255
+ */
256
+ public function createContainer($containerName = '', $metadata = array())
257
+ {
258
+ if ($containerName === '') {
259
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
260
+ }
261
+ if (!self::isValidContainerName($containerName)) {
262
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
263
+ }
264
+ if (!is_array($metadata)) {
265
+ throw new Microsoft_WindowsAzure_Exception('Meta data should be an array of key and value pairs.');
266
+ }
267
+
268
+ // Create metadata headers
269
+ $headers = array();
270
+ $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata));
271
+
272
+ // Perform request
273
+ $response = $this->_performRequest($containerName, '?restype=container', Microsoft_Http_Client::PUT, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_CONTAINER, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
274
+ if ($response->isSuccessful()) {
275
+ return new Microsoft_WindowsAzure_Storage_BlobContainer(
276
+ $containerName,
277
+ $response->getHeader('Etag'),
278
+ $response->getHeader('Last-modified'),
279
+ $metadata
280
+ );
281
+ } else {
282
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
283
+ }
284
+ }
285
+
286
+ /**
287
+ * Create container if it does not exist
288
+ *
289
+ * @param string $containerName Container name
290
+ * @param array $metadata Key/value pairs of meta data
291
+ * @throws Microsoft_WindowsAzure_Exception
292
+ */
293
+ public function createContainerIfNotExists($containerName = '', $metadata = array())
294
+ {
295
+ if (!$this->containerExists($containerName)) {
296
+ $this->createContainer($containerName, $metadata);
297
+ }
298
+ }
299
+
300
+ /**
301
+ * Get container ACL
302
+ *
303
+ * @param string $containerName Container name
304
+ * @param bool $signedIdentifiers Display only private/blob/container or display signed identifiers?
305
+ * @return string Acl, to be compared with Microsoft_WindowsAzure_Storage_Blob::ACL_*
306
+ * @throws Microsoft_WindowsAzure_Exception
307
+ */
308
+ public function getContainerAcl($containerName = '', $signedIdentifiers = false)
309
+ {
310
+ if ($containerName === '') {
311
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
312
+ }
313
+ if (!self::isValidContainerName($containerName)) {
314
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
315
+ }
316
+
317
+ // Perform request
318
+ $response = $this->_performRequest($containerName, '?restype=container&comp=acl', Microsoft_Http_Client::GET, array(), false, null, Microsoft_WindowsAzure_Storage::RESOURCE_CONTAINER, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ);
319
+ if ($response->isSuccessful()) {
320
+ if ($signedIdentifiers == false) {
321
+ // Only private/blob/container
322
+ $accessType = $response->getHeader(Microsoft_WindowsAzure_Storage::PREFIX_STORAGE_HEADER . 'blob-public-access');
323
+ if (strtolower($accessType) == 'true') {
324
+ $accessType = self::ACL_PUBLIC_CONTAINER;
325
+ }
326
+ return $accessType;
327
+ } else {
328
+ // Parse result
329
+ $result = $this->_parseResponse($response);
330
+ if (!$result) {
331
+ return array();
332
+ }
333
+
334
+ $entries = null;
335
+ if ($result->SignedIdentifier) {
336
+ if (count($result->SignedIdentifier) > 1) {
337
+ $entries = $result->SignedIdentifier;
338
+ } else {
339
+ $entries = array($result->SignedIdentifier);
340
+ }
341
+ }
342
+
343
+ // Return value
344
+ $returnValue = array();
345
+ foreach ($entries as $entry) {
346
+ $returnValue[] = new Microsoft_WindowsAzure_Storage_SignedIdentifier(
347
+ $entry->Id,
348
+ $entry->AccessPolicy ? $entry->AccessPolicy->Start ? $entry->AccessPolicy->Start : '' : '',
349
+ $entry->AccessPolicy ? $entry->AccessPolicy->Expiry ? $entry->AccessPolicy->Expiry : '' : '',
350
+ $entry->AccessPolicy ? $entry->AccessPolicy->Permission ? $entry->AccessPolicy->Permission : '' : ''
351
+ );
352
+ }
353
+
354
+ // Return
355
+ return $returnValue;
356
+ }
357
+ } else {
358
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
359
+ }
360
+ }
361
+
362
+ /**
363
+ * Set container ACL
364
+ *
365
+ * @param string $containerName Container name
366
+ * @param bool $acl Microsoft_WindowsAzure_Storage_Blob::ACL_*
367
+ * @param array $signedIdentifiers Signed identifiers
368
+ * @throws Microsoft_WindowsAzure_Exception
369
+ */
370
+ public function setContainerAcl($containerName = '', $acl = self::ACL_PRIVATE, $signedIdentifiers = array())
371
+ {
372
+ if ($containerName === '') {
373
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
374
+ }
375
+ if (!self::isValidContainerName($containerName)) {
376
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
377
+ }
378
+
379
+ // Headers
380
+ $headers = array();
381
+
382
+ // Acl specified?
383
+ if ($acl != self::ACL_PRIVATE && !is_null($acl) && $acl != '') {
384
+ $headers[Microsoft_WindowsAzure_Storage::PREFIX_STORAGE_HEADER . 'blob-public-access'] = $acl;
385
+ }
386
+
387
+ // Policies
388
+ $policies = null;
389
+ if (is_array($signedIdentifiers) && count($signedIdentifiers) > 0) {
390
+ $policies = '';
391
+ $policies .= '<?xml version="1.0" encoding="utf-8"?>' . "\r\n";
392
+ $policies .= '<SignedIdentifiers>' . "\r\n";
393
+ foreach ($signedIdentifiers as $signedIdentifier) {
394
+ $policies .= ' <SignedIdentifier>' . "\r\n";
395
+ $policies .= ' <Id>' . $signedIdentifier->Id . '</Id>' . "\r\n";
396
+ $policies .= ' <AccessPolicy>' . "\r\n";
397
+ if ($signedIdentifier->Start != '')
398
+ $policies .= ' <Start>' . $signedIdentifier->Start . '</Start>' . "\r\n";
399
+ if ($signedIdentifier->Expiry != '')
400
+ $policies .= ' <Expiry>' . $signedIdentifier->Expiry . '</Expiry>' . "\r\n";
401
+ if ($signedIdentifier->Permissions != '')
402
+ $policies .= ' <Permission>' . $signedIdentifier->Permissions . '</Permission>' . "\r\n";
403
+ $policies .= ' </AccessPolicy>' . "\r\n";
404
+ $policies .= ' </SignedIdentifier>' . "\r\n";
405
+ }
406
+ $policies .= '</SignedIdentifiers>' . "\r\n";
407
+ }
408
+
409
+ // Perform request
410
+ $response = $this->_performRequest($containerName, '?restype=container&comp=acl', Microsoft_Http_Client::PUT, $headers, false, $policies, Microsoft_WindowsAzure_Storage::RESOURCE_CONTAINER, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
411
+ if (!$response->isSuccessful()) {
412
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
413
+ }
414
+ }
415
+
416
+ /**
417
+ * Get container
418
+ *
419
+ * @param string $containerName Container name
420
+ * @return Microsoft_WindowsAzure_Storage_BlobContainer
421
+ * @throws Microsoft_WindowsAzure_Exception
422
+ */
423
+ public function getContainer($containerName = '')
424
+ {
425
+ if ($containerName === '') {
426
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
427
+ }
428
+ if (!self::isValidContainerName($containerName)) {
429
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
430
+ }
431
+
432
+ // Perform request
433
+ $response = $this->_performRequest($containerName, '?restype=container', Microsoft_Http_Client::GET, array(), false, null, Microsoft_WindowsAzure_Storage::RESOURCE_CONTAINER, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ);
434
+ if ($response->isSuccessful()) {
435
+ // Parse metadata
436
+ $metadata = $this->_parseMetadataHeaders($response->getHeaders());
437
+
438
+ // Return container
439
+ return new Microsoft_WindowsAzure_Storage_BlobContainer(
440
+ $containerName,
441
+ $response->getHeader('Etag'),
442
+ $response->getHeader('Last-modified'),
443
+ $metadata
444
+ );
445
+ } else {
446
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
447
+ }
448
+ }
449
+
450
+ /**
451
+ * Get container metadata
452
+ *
453
+ * @param string $containerName Container name
454
+ * @return array Key/value pairs of meta data
455
+ * @throws Microsoft_WindowsAzure_Exception
456
+ */
457
+ public function getContainerMetadata($containerName = '')
458
+ {
459
+ if ($containerName === '') {
460
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
461
+ }
462
+ if (!self::isValidContainerName($containerName)) {
463
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
464
+ }
465
+
466
+ return $this->getContainer($containerName)->Metadata;
467
+ }
468
+
469
+ /**
470
+ * Set container metadata
471
+ *
472
+ * Calling the Set Container Metadata operation overwrites all existing metadata that is associated with the container. It's not possible to modify an individual name/value pair.
473
+ *
474
+ * @param string $containerName Container name
475
+ * @param array $metadata Key/value pairs of meta data
476
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
477
+ * @throws Microsoft_WindowsAzure_Exception
478
+ */
479
+ public function setContainerMetadata($containerName = '', $metadata = array(), $additionalHeaders = array())
480
+ {
481
+ if ($containerName === '') {
482
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
483
+ }
484
+ if (!self::isValidContainerName($containerName)) {
485
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
486
+ }
487
+ if (!is_array($metadata)) {
488
+ throw new Microsoft_WindowsAzure_Exception('Meta data should be an array of key and value pairs.');
489
+ }
490
+ if (count($metadata) == 0) {
491
+ return;
492
+ }
493
+
494
+ // Create metadata headers
495
+ $headers = array();
496
+ $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata));
497
+
498
+ // Additional headers?
499
+ foreach ($additionalHeaders as $key => $value) {
500
+ $headers[$key] = $value;
501
+ }
502
+
503
+ // Perform request
504
+ $response = $this->_performRequest($containerName, '?restype=container&comp=metadata', Microsoft_Http_Client::PUT, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_CONTAINER, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
505
+ if (!$response->isSuccessful()) {
506
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
507
+ }
508
+ }
509
+
510
+ /**
511
+ * Delete container
512
+ *
513
+ * @param string $containerName Container name
514
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
515
+ * @throws Microsoft_WindowsAzure_Exception
516
+ */
517
+ public function deleteContainer($containerName = '', $additionalHeaders = array())
518
+ {
519
+ if ($containerName === '') {
520
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
521
+ }
522
+ if (!self::isValidContainerName($containerName)) {
523
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
524
+ }
525
+
526
+ // Additional headers?
527
+ $headers = array();
528
+ foreach ($additionalHeaders as $key => $value) {
529
+ $headers[$key] = $value;
530
+ }
531
+
532
+ // Perform request
533
+ $response = $this->_performRequest($containerName, '?restype=container', Microsoft_Http_Client::DELETE, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_CONTAINER, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
534
+ if (!$response->isSuccessful()) {
535
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
536
+ }
537
+ }
538
+
539
+ /**
540
+ * List containers
541
+ *
542
+ * @param string $prefix Optional. Filters the results to return only containers whose name begins with the specified prefix.
543
+ * @param int $maxResults Optional. Specifies the maximum number of containers to return per call to Azure storage. This does NOT affect list size returned by this function. (maximum: 5000)
544
+ * @param string $marker Optional string value that identifies the portion of the list to be returned with the next list operation.
545
+ * @param string $include Optional. Include this parameter to specify that the container's metadata be returned as part of the response body. (allowed values: '', 'metadata')
546
+ * @param int $currentResultCount Current result count (internal use)
547
+ * @return array
548
+ * @throws Microsoft_WindowsAzure_Exception
549
+ */
550
+ public function listContainers($prefix = null, $maxResults = null, $marker = null, $include = null, $currentResultCount = 0)
551
+ {
552
+ // Build query string
553
+ $queryString = array('comp=list');
554
+ if (!is_null($prefix)) {
555
+ $queryString[] = 'prefix=' . $prefix;
556
+ }
557
+ if (!is_null($maxResults)) {
558
+ $queryString[] = 'maxresults=' . $maxResults;
559
+ }
560
+ if (!is_null($marker)) {
561
+ $queryString[] = 'marker=' . $marker;
562
+ }
563
+ if (!is_null($include)) {
564
+ $queryString[] = 'include=' . $include;
565
+ }
566
+ $queryString = self::createQueryStringFromArray($queryString);
567
+
568
+ // Perform request
569
+ $response = $this->_performRequest('', $queryString, Microsoft_Http_Client::GET, array(), false, null, Microsoft_WindowsAzure_Storage::RESOURCE_CONTAINER, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_LIST);
570
+ if ($response->isSuccessful()) {
571
+ $xmlContainers = $this->_parseResponse($response)->Containers->Container;
572
+ $xmlMarker = (string)$this->_parseResponse($response)->NextMarker;
573
+
574
+ $containers = array();
575
+ if (!is_null($xmlContainers)) {
576
+ for ($i = 0; $i < count($xmlContainers); $i++) {
577
+ $containers[] = new Microsoft_WindowsAzure_Storage_BlobContainer(
578
+ (string)$xmlContainers[$i]->Name,
579
+ (string)$xmlContainers[$i]->Etag,
580
+ (string)$xmlContainers[$i]->LastModified,
581
+ $this->_parseMetadataElement($xmlContainers[$i])
582
+ );
583
+ }
584
+ }
585
+ $currentResultCount = $currentResultCount + count($containers);
586
+ if (!is_null($maxResults) && $currentResultCount < $maxResults) {
587
+ if (!is_null($xmlMarker) && $xmlMarker != '') {
588
+ $containers = array_merge($containers, $this->listContainers($prefix, $maxResults, $xmlMarker, $include, $currentResultCount));
589
+ }
590
+ }
591
+ if (!is_null($maxResults) && count($containers) > $maxResults) {
592
+ $containers = array_slice($containers, 0, $maxResults);
593
+ }
594
+
595
+ return $containers;
596
+ } else {
597
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
598
+ }
599
+ }
600
+
601
+ /**
602
+ * Put blob
603
+ *
604
+ * @param string $containerName Container name
605
+ * @param string $blobName Blob name
606
+ * @param string $localFileName Local file name to be uploaded
607
+ * @param array $metadata Key/value pairs of meta data
608
+ * @param string $leaseId Lease identifier
609
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
610
+ * @return object Partial blob properties
611
+ * @throws Microsoft_WindowsAzure_Exception
612
+ */
613
+ public function putBlob($containerName = '', $blobName = '', $localFileName = '', $metadata = array(), $leaseId = null, $additionalHeaders = array())
614
+ {
615
+ if ($containerName === '') {
616
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
617
+ }
618
+ if (!self::isValidContainerName($containerName)) {
619
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
620
+ }
621
+ if ($blobName === '') {
622
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
623
+ }
624
+ if ($localFileName === '') {
625
+ throw new Microsoft_WindowsAzure_Exception('Local file name is not specified.');
626
+ }
627
+ if (!file_exists($localFileName)) {
628
+ throw new Microsoft_WindowsAzure_Exception('Local file not found.');
629
+ }
630
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
631
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
632
+ }
633
+
634
+ // Check file size
635
+ if (filesize($localFileName) >= self::MAX_BLOB_SIZE) {
636
+ return $this->putLargeBlob($containerName, $blobName, $localFileName, $metadata, $leaseId, $additionalHeaders);
637
+ }
638
+
639
+ // Put the data to Windows Azure Storage
640
+ return $this->putBlobData($containerName, $blobName, file_get_contents($localFileName), $metadata, $leaseId, $additionalHeaders);
641
+ }
642
+
643
+ /**
644
+ * Put blob data
645
+ *
646
+ * @param string $containerName Container name
647
+ * @param string $blobName Blob name
648
+ * @param mixed $data Data to store
649
+ * @param array $metadata Key/value pairs of meta data
650
+ * @param string $leaseId Lease identifier
651
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
652
+ * @return object Partial blob properties
653
+ * @throws Microsoft_WindowsAzure_Exception
654
+ */
655
+ public function putBlobData($containerName = '', $blobName = '', $data = '', $metadata = array(), $leaseId = null, $additionalHeaders = array())
656
+ {
657
+ if ($containerName === '') {
658
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
659
+ }
660
+ if (!self::isValidContainerName($containerName)) {
661
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
662
+ }
663
+ if ($blobName === '') {
664
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
665
+ }
666
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
667
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
668
+ }
669
+
670
+ // Create metadata headers
671
+ $headers = array();
672
+ if (!is_null($leaseId)) {
673
+ $headers['x-ms-lease-id'] = $leaseId;
674
+ }
675
+ $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata));
676
+
677
+ // Additional headers?
678
+ foreach ($additionalHeaders as $key => $value) {
679
+ $headers[$key] = $value;
680
+ }
681
+
682
+ // Specify blob type
683
+ $headers[Microsoft_WindowsAzure_Storage::PREFIX_STORAGE_HEADER . 'blob-type'] = self::BLOBTYPE_BLOCK;
684
+
685
+ // Resource name
686
+ $resourceName = self::createResourceName($containerName , $blobName);
687
+
688
+ // Perform request
689
+ $response = $this->_performRequest($resourceName, '', Microsoft_Http_Client::PUT, $headers, false, $data, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
690
+ if ($response->isSuccessful()) {
691
+ return new Microsoft_WindowsAzure_Storage_BlobInstance(
692
+ $containerName,
693
+ $blobName,
694
+ null,
695
+ $response->getHeader('Etag'),
696
+ $response->getHeader('Last-modified'),
697
+ $this->getBaseUrl() . '/' . $containerName . '/' . $blobName,
698
+ strlen($data),
699
+ '',
700
+ '',
701
+ '',
702
+ false,
703
+ $metadata
704
+ );
705
+ } else {
706
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
707
+ }
708
+ }
709
+
710
+ /**
711
+ * Put large blob (> 64 MB)
712
+ *
713
+ * @param string $containerName Container name
714
+ * @param string $blobName Blob name
715
+ * @param string $localFileName Local file name to be uploaded
716
+ * @param array $metadata Key/value pairs of meta data
717
+ * @param string $leaseId Lease identifier
718
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
719
+ * @return object Partial blob properties
720
+ * @throws Microsoft_WindowsAzure_Exception
721
+ */
722
+ public function putLargeBlob($containerName = '', $blobName = '', $localFileName = '', $metadata = array(), $leaseId = null, $additionalHeaders = array())
723
+ {
724
+ if ($containerName === '') {
725
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
726
+ }
727
+ if (!self::isValidContainerName($containerName)) {
728
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
729
+ }
730
+ if ($blobName === '') {
731
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
732
+ }
733
+ if ($localFileName === '') {
734
+ throw new Microsoft_WindowsAzure_Exception('Local file name is not specified.');
735
+ }
736
+ if (!file_exists($localFileName)) {
737
+ throw new Microsoft_WindowsAzure_Exception('Local file not found.');
738
+ }
739
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
740
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
741
+ }
742
+
743
+ // Check file size
744
+ if (filesize($localFileName) < self::MAX_BLOB_SIZE) {
745
+ return $this->putBlob($containerName, $blobName, $localFileName, $metadata, $leaseId, $additionalHeaders);
746
+ }
747
+
748
+ // Determine number of parts
749
+ $numberOfParts = ceil( filesize($localFileName) / self::MAX_BLOB_TRANSFER_SIZE );
750
+
751
+ // Generate block id's
752
+ $blockIdentifiers = array();
753
+ for ($i = 0; $i < $numberOfParts; $i++) {
754
+ $blockIdentifiers[] = $this->_generateBlockId($i);
755
+ }
756
+
757
+ // Open file
758
+ $fp = fopen($localFileName, 'r');
759
+ if ($fp === false) {
760
+ throw new Microsoft_WindowsAzure_Exception('Could not open local file.');
761
+ }
762
+
763
+ // Upload parts
764
+ for ($i = 0; $i < $numberOfParts; $i++) {
765
+ // Seek position in file
766
+ fseek($fp, $i * self::MAX_BLOB_TRANSFER_SIZE);
767
+
768
+ // Read contents
769
+ $fileContents = fread($fp, self::MAX_BLOB_TRANSFER_SIZE);
770
+
771
+ // Put block
772
+ $this->putBlock($containerName, $blobName, $blockIdentifiers[$i], $fileContents, $leaseId);
773
+
774
+ // Dispose file contents
775
+ $fileContents = null;
776
+ unset($fileContents);
777
+ }
778
+
779
+ // Close file
780
+ fclose($fp);
781
+
782
+ // Put block list
783
+ $this->putBlockList($containerName, $blobName, $blockIdentifiers, $metadata, $leaseId, $additionalHeaders);
784
+
785
+ // Return information of the blob
786
+ return $this->getBlobInstance($containerName, $blobName, null, $leaseId);
787
+ }
788
+
789
+ /**
790
+ * Put large blob block
791
+ *
792
+ * @param string $containerName Container name
793
+ * @param string $blobName Blob name
794
+ * @param string $identifier Block ID
795
+ * @param array $contents Contents of the block
796
+ * @param string $leaseId Lease identifier
797
+ * @throws Microsoft_WindowsAzure_Exception
798
+ */
799
+ public function putBlock($containerName = '', $blobName = '', $identifier = '', $contents = '', $leaseId = null)
800
+ {
801
+ if ($containerName === '') {
802
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
803
+ }
804
+ if (!self::isValidContainerName($containerName)) {
805
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
806
+ }
807
+ if ($identifier === '') {
808
+ throw new Microsoft_WindowsAzure_Exception('Block identifier is not specified.');
809
+ }
810
+ if (strlen($contents) > self::MAX_BLOB_TRANSFER_SIZE) {
811
+ throw new Microsoft_WindowsAzure_Exception('Block size is too big.');
812
+ }
813
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
814
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
815
+ }
816
+
817
+ // Headers
818
+ $headers = array();
819
+ if (!is_null($leaseId)) {
820
+ $headers['x-ms-lease-id'] = $leaseId;
821
+ }
822
+
823
+ // Resource name
824
+ $resourceName = self::createResourceName($containerName , $blobName);
825
+
826
+ // Upload
827
+ $response = $this->_performRequest($resourceName, '?comp=block&blockid=' . base64_encode($identifier), Microsoft_Http_Client::PUT, $headers, false, $contents, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
828
+ if (!$response->isSuccessful()) {
829
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
830
+ }
831
+ }
832
+
833
+ /**
834
+ * Put block list
835
+ *
836
+ * @param string $containerName Container name
837
+ * @param string $blobName Blob name
838
+ * @param array $blockList Array of block identifiers
839
+ * @param array $metadata Key/value pairs of meta data
840
+ * @param string $leaseId Lease identifier
841
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
842
+ * @throws Microsoft_WindowsAzure_Exception
843
+ */
844
+ public function putBlockList($containerName = '', $blobName = '', $blockList = array(), $metadata = array(), $leaseId = null, $additionalHeaders = array())
845
+ {
846
+ if ($containerName === '') {
847
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
848
+ }
849
+ if (!self::isValidContainerName($containerName)) {
850
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
851
+ }
852
+ if ($blobName === '') {
853
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
854
+ }
855
+ if (count($blockList) == 0) {
856
+ throw new Microsoft_WindowsAzure_Exception('Block list does not contain any elements.');
857
+ }
858
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
859
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
860
+ }
861
+
862
+ // Generate block list
863
+ $blocks = '';
864
+ foreach ($blockList as $block) {
865
+ $blocks .= ' <Latest>' . base64_encode($block) . '</Latest>' . "\n";
866
+ }
867
+
868
+ // Generate block list request
869
+ $fileContents = utf8_encode(implode("\n", array(
870
+ '<?xml version="1.0" encoding="utf-8"?>',
871
+ '<BlockList>',
872
+ $blocks,
873
+ '</BlockList>'
874
+ )));
875
+
876
+ // Create metadata headers
877
+ $headers = array();
878
+ if (!is_null($leaseId)) {
879
+ $headers['x-ms-lease-id'] = $leaseId;
880
+ }
881
+ $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata));
882
+
883
+ // Additional headers?
884
+ foreach ($additionalHeaders as $key => $value) {
885
+ $headers[$key] = $value;
886
+ }
887
+
888
+ // Resource name
889
+ $resourceName = self::createResourceName($containerName , $blobName);
890
+
891
+ // Perform request
892
+ $response = $this->_performRequest($resourceName, '?comp=blocklist', Microsoft_Http_Client::PUT, $headers, false, $fileContents, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
893
+ if (!$response->isSuccessful()) {
894
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
895
+ }
896
+ }
897
+
898
+ /**
899
+ * Get block list
900
+ *
901
+ * @param string $containerName Container name
902
+ * @param string $blobName Blob name
903
+ * @param string $snapshotId Snapshot identifier
904
+ * @param string $leaseId Lease identifier
905
+ * @param integer $type Type of block list to retrieve. 0 = all, 1 = committed, 2 = uncommitted
906
+ * @return array
907
+ * @throws Microsoft_WindowsAzure_Exception
908
+ */
909
+ public function getBlockList($containerName = '', $blobName = '', $snapshotId = null, $leaseId = null, $type = 0)
910
+ {
911
+ if ($containerName === '') {
912
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
913
+ }
914
+ if (!self::isValidContainerName($containerName)) {
915
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
916
+ }
917
+ if ($blobName === '') {
918
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
919
+ }
920
+ if ($type < 0 || $type > 2) {
921
+ throw new Microsoft_WindowsAzure_Exception('Invalid type of block list to retrieve.');
922
+ }
923
+
924
+ // Set $blockListType
925
+ $blockListType = 'all';
926
+ if ($type == 1) {
927
+ $blockListType = 'committed';
928
+ }
929
+ if ($type == 2) {
930
+ $blockListType = 'uncommitted';
931
+ }
932
+
933
+ // Headers
934
+ $headers = array();
935
+ if (!is_null($leaseId)) {
936
+ $headers['x-ms-lease-id'] = $leaseId;
937
+ }
938
+
939
+ // Build query string
940
+ $queryString = array('comp=blocklist', 'blocklisttype=' . $blockListType);
941
+ if (!is_null($snapshotId)) {
942
+ $queryString[] = 'snapshot=' . $snapshotId;
943
+ }
944
+ $queryString = self::createQueryStringFromArray($queryString);
945
+
946
+ // Resource name
947
+ $resourceName = self::createResourceName($containerName , $blobName);
948
+
949
+ // Perform request
950
+ $response = $this->_performRequest($resourceName, $queryString, Microsoft_Http_Client::GET, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ);
951
+ if ($response->isSuccessful()) {
952
+ // Parse response
953
+ $blockList = $this->_parseResponse($response);
954
+
955
+ // Create return value
956
+ $returnValue = array();
957
+ if ($blockList->CommittedBlocks) {
958
+ foreach ($blockList->CommittedBlocks->Block as $block) {
959
+ $returnValue['CommittedBlocks'][] = (object)array(
960
+ 'Name' => (string)$block->Name,
961
+ 'Size' => (string)$block->Size
962
+ );
963
+ }
964
+ }
965
+ if ($blockList->UncommittedBlocks) {
966
+ foreach ($blockList->UncommittedBlocks->Block as $block) {
967
+ $returnValue['UncommittedBlocks'][] = (object)array(
968
+ 'Name' => (string)$block->Name,
969
+ 'Size' => (string)$block->Size
970
+ );
971
+ }
972
+ }
973
+
974
+ return $returnValue;
975
+ } else {
976
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
977
+ }
978
+ }
979
+
980
+ /**
981
+ * Create page blob
982
+ *
983
+ * @param string $containerName Container name
984
+ * @param string $blobName Blob name
985
+ * @param int $size Size of the page blob in bytes
986
+ * @param array $metadata Key/value pairs of meta data
987
+ * @param string $leaseId Lease identifier
988
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
989
+ * @return object Partial blob properties
990
+ * @throws Microsoft_WindowsAzure_Exception
991
+ */
992
+ public function createPageBlob($containerName = '', $blobName = '', $size = 0, $metadata = array(), $leaseId = null, $additionalHeaders = array())
993
+ {
994
+ if ($containerName === '') {
995
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
996
+ }
997
+ if (!self::isValidContainerName($containerName)) {
998
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
999
+ }
1000
+ if ($blobName === '') {
1001
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
1002
+ }
1003
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
1004
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
1005
+ }
1006
+ if ($size <= 0) {
1007
+ throw new Microsoft_WindowsAzure_Exception('Page blob size must be specified.');
1008
+ }
1009
+
1010
+ // Create metadata headers
1011
+ $headers = array();
1012
+ if (!is_null($leaseId)) {
1013
+ $headers['x-ms-lease-id'] = $leaseId;
1014
+ }
1015
+ $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata));
1016
+
1017
+ // Additional headers?
1018
+ foreach ($additionalHeaders as $key => $value) {
1019
+ $headers[$key] = $value;
1020
+ }
1021
+
1022
+ // Specify blob type & blob length
1023
+ $headers[Microsoft_WindowsAzure_Storage::PREFIX_STORAGE_HEADER . 'blob-type'] = self::BLOBTYPE_PAGE;
1024
+ $headers[Microsoft_WindowsAzure_Storage::PREFIX_STORAGE_HEADER . 'blob-content-length'] = $size;
1025
+ $headers['Content-Length'] = 0;
1026
+
1027
+ // Resource name
1028
+ $resourceName = self::createResourceName($containerName , $blobName);
1029
+
1030
+ // Perform request
1031
+ $response = $this->_performRequest($resourceName, '', Microsoft_Http_Client::PUT, $headers, false, '', Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
1032
+ if ($response->isSuccessful()) {
1033
+ return new Microsoft_WindowsAzure_Storage_BlobInstance(
1034
+ $containerName,
1035
+ $blobName,
1036
+ null,
1037
+ $response->getHeader('Etag'),
1038
+ $response->getHeader('Last-modified'),
1039
+ $this->getBaseUrl() . '/' . $containerName . '/' . $blobName,
1040
+ $size,
1041
+ '',
1042
+ '',
1043
+ '',
1044
+ false,
1045
+ $metadata
1046
+ );
1047
+ } else {
1048
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
1049
+ }
1050
+ }
1051
+
1052
+ /**
1053
+ * Put page in page blob
1054
+ *
1055
+ * @param string $containerName Container name
1056
+ * @param string $blobName Blob name
1057
+ * @param int $startByteOffset Start byte offset
1058
+ * @param int $endByteOffset End byte offset
1059
+ * @param mixed $contents Page contents
1060
+ * @param string $writeMethod Write method (Microsoft_WindowsAzure_Storage_Blob::PAGE_WRITE_*)
1061
+ * @param string $leaseId Lease identifier
1062
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
1063
+ * @throws Microsoft_WindowsAzure_Exception
1064
+ */
1065
+ public function putPage($containerName = '', $blobName = '', $startByteOffset = 0, $endByteOffset = 0, $contents = '', $writeMethod = self::PAGE_WRITE_UPDATE, $leaseId = null, $additionalHeaders = array())
1066
+ {
1067
+ if ($containerName === '') {
1068
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
1069
+ }
1070
+ if (!self::isValidContainerName($containerName)) {
1071
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1072
+ }
1073
+ if ($blobName === '') {
1074
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
1075
+ }
1076
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
1077
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
1078
+ }
1079
+ if ($startByteOffset % 512 != 0) {
1080
+ throw new Microsoft_WindowsAzure_Exception('Start byte offset must be a modulus of 512.');
1081
+ }
1082
+ if (($endByteOffset + 1) % 512 != 0) {
1083
+ throw new Microsoft_WindowsAzure_Exception('End byte offset must be a modulus of 512 minus 1.');
1084
+ }
1085
+
1086
+ // Determine size
1087
+ $size = strlen($contents);
1088
+ if ($size >= self::MAX_BLOB_TRANSFER_SIZE) {
1089
+ throw new Microsoft_WindowsAzure_Exception('Page blob size must not be larger than ' + self::MAX_BLOB_TRANSFER_SIZE . ' bytes.');
1090
+ }
1091
+
1092
+ // Create metadata headers
1093
+ $headers = array();
1094
+ if (!is_null($leaseId)) {
1095
+ $headers['x-ms-lease-id'] = $leaseId;
1096
+ }
1097
+
1098
+ // Additional headers?
1099
+ foreach ($additionalHeaders as $key => $value) {
1100
+ $headers[$key] = $value;
1101
+ }
1102
+
1103
+ // Specify range
1104
+ $headers['Range'] = 'bytes=' . $startByteOffset . '-' . $endByteOffset;
1105
+
1106
+ // Write method
1107
+ $headers[Microsoft_WindowsAzure_Storage::PREFIX_STORAGE_HEADER . 'page-write'] = $writeMethod;
1108
+
1109
+ // Resource name
1110
+ $resourceName = self::createResourceName($containerName , $blobName);
1111
+
1112
+ // Perform request
1113
+ $response = $this->_performRequest($resourceName, '?comp=page', Microsoft_Http_Client::PUT, $headers, false, $contents, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
1114
+ if (!$response->isSuccessful()) {
1115
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
1116
+ }
1117
+ }
1118
+
1119
+ /**
1120
+ * Put page in page blob
1121
+ *
1122
+ * @param string $containerName Container name
1123
+ * @param string $blobName Blob name
1124
+ * @param int $startByteOffset Start byte offset
1125
+ * @param int $endByteOffset End byte offset
1126
+ * @param string $leaseId Lease identifier
1127
+ * @return array Array of page ranges
1128
+ * @throws Microsoft_WindowsAzure_Exception
1129
+ */
1130
+ public function getPageRegions($containerName = '', $blobName = '', $startByteOffset = 0, $endByteOffset = 0, $leaseId = null)
1131
+ {
1132
+ if ($containerName === '') {
1133
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
1134
+ }
1135
+ if (!self::isValidContainerName($containerName)) {
1136
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1137
+ }
1138
+ if ($blobName === '') {
1139
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
1140
+ }
1141
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
1142
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
1143
+ }
1144
+ if ($startByteOffset % 512 != 0) {
1145
+ throw new Microsoft_WindowsAzure_Exception('Start byte offset must be a modulus of 512.');
1146
+ }
1147
+ if ($endByteOffset > 0 && ($endByteOffset + 1) % 512 != 0) {
1148
+ throw new Microsoft_WindowsAzure_Exception('End byte offset must be a modulus of 512 minus 1.');
1149
+ }
1150
+
1151
+ // Create metadata headers
1152
+ $headers = array();
1153
+ if (!is_null($leaseId)) {
1154
+ $headers['x-ms-lease-id'] = $leaseId;
1155
+ }
1156
+
1157
+ // Specify range?
1158
+ if ($endByteOffset > 0) {
1159
+ $headers['Range'] = 'bytes=' . $startByteOffset . '-' . $endByteOffset;
1160
+ }
1161
+
1162
+ // Resource name
1163
+ $resourceName = self::createResourceName($containerName , $blobName);
1164
+
1165
+ // Perform request
1166
+ $response = $this->_performRequest($resourceName, '?comp=pagelist', Microsoft_Http_Client::GET, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
1167
+ if ($response->isSuccessful()) {
1168
+ $result = $this->_parseResponse($response);
1169
+ $xmlRanges = null;
1170
+ if (count($result->PageRange) > 1) {
1171
+ $xmlRanges = $result->PageRange;
1172
+ } else {
1173
+ $xmlRanges = array($result->PageRange);
1174
+ }
1175
+
1176
+ $ranges = array();
1177
+ for ($i = 0; $i < count($xmlRanges); $i++) {
1178
+ $ranges[] = new Microsoft_WindowsAzure_Storage_PageRegionInstance(
1179
+ (int)$xmlRanges[$i]->Start,
1180
+ (int)$xmlRanges[$i]->End
1181
+ );
1182
+ }
1183
+
1184
+ return $ranges;
1185
+ } else {
1186
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
1187
+ }
1188
+ }
1189
+
1190
+ /**
1191
+ * Copy blob
1192
+ *
1193
+ * @param string $sourceContainerName Source container name
1194
+ * @param string $sourceBlobName Source blob name
1195
+ * @param string $destinationContainerName Destination container name
1196
+ * @param string $destinationBlobName Destination blob name
1197
+ * @param array $metadata Key/value pairs of meta data
1198
+ * @param string $sourceSnapshotId Source snapshot identifier
1199
+ * @param string $destinationLeaseId Destination lease identifier
1200
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd894037.aspx for more information.
1201
+ * @return object Partial blob properties
1202
+ * @throws Microsoft_WindowsAzure_Exception
1203
+ */
1204
+ public function copyBlob($sourceContainerName = '', $sourceBlobName = '', $destinationContainerName = '', $destinationBlobName = '', $metadata = array(), $sourceSnapshotId = null, $destinationLeaseId = null, $additionalHeaders = array())
1205
+ {
1206
+ if ($sourceContainerName === '') {
1207
+ throw new Microsoft_WindowsAzure_Exception('Source container name is not specified.');
1208
+ }
1209
+ if (!self::isValidContainerName($sourceContainerName)) {
1210
+ throw new Microsoft_WindowsAzure_Exception('Source container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1211
+ }
1212
+ if ($sourceBlobName === '') {
1213
+ throw new Microsoft_WindowsAzure_Exception('Source blob name is not specified.');
1214
+ }
1215
+ if ($destinationContainerName === '') {
1216
+ throw new Microsoft_WindowsAzure_Exception('Destination container name is not specified.');
1217
+ }
1218
+ if (!self::isValidContainerName($destinationContainerName)) {
1219
+ throw new Microsoft_WindowsAzure_Exception('Destination container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1220
+ }
1221
+ if ($destinationBlobName === '') {
1222
+ throw new Microsoft_WindowsAzure_Exception('Destination blob name is not specified.');
1223
+ }
1224
+ if ($sourceContainerName === '$root' && strpos($sourceBlobName, '/') !== false) {
1225
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
1226
+ }
1227
+ if ($destinationContainerName === '$root' && strpos($destinationBlobName, '/') !== false) {
1228
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
1229
+ }
1230
+
1231
+ // Create metadata headers
1232
+ $headers = array();
1233
+ if (!is_null($destinationLeaseId)) {
1234
+ $headers['x-ms-lease-id'] = $destinationLeaseId;
1235
+ }
1236
+ $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata));
1237
+
1238
+ // Additional headers?
1239
+ foreach ($additionalHeaders as $key => $value) {
1240
+ $headers[$key] = $value;
1241
+ }
1242
+
1243
+ // Resource names
1244
+ $sourceResourceName = self::createResourceName($sourceContainerName, $sourceBlobName);
1245
+ if (!is_null($sourceSnapshotId)) {
1246
+ $sourceResourceName .= '?snapshot=' . $sourceSnapshotId;
1247
+ }
1248
+ $destinationResourceName = self::createResourceName($destinationContainerName, $destinationBlobName);
1249
+
1250
+ // Set source blob
1251
+ $headers["x-ms-copy-source"] = '/' . $this->_accountName . '/' . $sourceResourceName;
1252
+
1253
+ // Perform request
1254
+ $response = $this->_performRequest($destinationResourceName, '', Microsoft_Http_Client::PUT, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
1255
+ if ($response->isSuccessful()) {
1256
+ return new Microsoft_WindowsAzure_Storage_BlobInstance(
1257
+ $destinationContainerName,
1258
+ $destinationBlobName,
1259
+ null,
1260
+ $response->getHeader('Etag'),
1261
+ $response->getHeader('Last-modified'),
1262
+ $this->getBaseUrl() . '/' . $destinationContainerName . '/' . $destinationBlobName,
1263
+ 0,
1264
+ '',
1265
+ '',
1266
+ '',
1267
+ false,
1268
+ $metadata
1269
+ );
1270
+ } else {
1271
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
1272
+ }
1273
+ }
1274
+
1275
+ /**
1276
+ * Get blob
1277
+ *
1278
+ * @param string $containerName Container name
1279
+ * @param string $blobName Blob name
1280
+ * @param string $localFileName Local file name to store downloaded blob
1281
+ * @param string $snapshotId Snapshot identifier
1282
+ * @param string $leaseId Lease identifier
1283
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
1284
+ * @throws Microsoft_WindowsAzure_Exception
1285
+ */
1286
+ public function getBlob($containerName = '', $blobName = '', $localFileName = '', $snapshotId = null, $leaseId = null, $additionalHeaders = array())
1287
+ {
1288
+ if ($containerName === '') {
1289
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
1290
+ }
1291
+ if (!self::isValidContainerName($containerName)) {
1292
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1293
+ }
1294
+ if ($blobName === '') {
1295
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
1296
+ }
1297
+ if ($localFileName === '') {
1298
+ throw new Microsoft_WindowsAzure_Exception('Local file name is not specified.');
1299
+ }
1300
+
1301
+ // Fetch data
1302
+ file_put_contents($localFileName, $this->getBlobData($containerName, $blobName, $snapshotId, $leaseId, $additionalHeaders));
1303
+ }
1304
+
1305
+ /**
1306
+ * Get blob data
1307
+ *
1308
+ * @param string $containerName Container name
1309
+ * @param string $blobName Blob name
1310
+ * @param string $snapshotId Snapshot identifier
1311
+ * @param string $leaseId Lease identifier
1312
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
1313
+ * @return mixed Blob contents
1314
+ * @throws Microsoft_WindowsAzure_Exception
1315
+ */
1316
+ public function getBlobData($containerName = '', $blobName = '', $snapshotId = null, $leaseId = null, $additionalHeaders = array())
1317
+ {
1318
+ if ($containerName === '') {
1319
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
1320
+ }
1321
+ if (!self::isValidContainerName($containerName)) {
1322
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1323
+ }
1324
+ if ($blobName === '') {
1325
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
1326
+ }
1327
+
1328
+ // Build query string
1329
+ $queryString = array();
1330
+ if (!is_null($snapshotId)) {
1331
+ $queryString[] = 'snapshot=' . $snapshotId;
1332
+ }
1333
+ $queryString = self::createQueryStringFromArray($queryString);
1334
+
1335
+ // Additional headers?
1336
+ $headers = array();
1337
+ if (!is_null($leaseId)) {
1338
+ $headers['x-ms-lease-id'] = $leaseId;
1339
+ }
1340
+ foreach ($additionalHeaders as $key => $value) {
1341
+ $headers[$key] = $value;
1342
+ }
1343
+
1344
+ // Resource name
1345
+ $resourceName = self::createResourceName($containerName , $blobName);
1346
+
1347
+ // Perform request
1348
+ $response = $this->_performRequest($resourceName, $queryString, Microsoft_Http_Client::GET, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ);
1349
+ if ($response->isSuccessful()) {
1350
+ return $response->getBody();
1351
+ } else {
1352
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
1353
+ }
1354
+ }
1355
+
1356
+ /**
1357
+ * Get blob instance
1358
+ *
1359
+ * @param string $containerName Container name
1360
+ * @param string $blobName Blob name
1361
+ * @param string $snapshotId Snapshot identifier
1362
+ * @param string $leaseId Lease identifier
1363
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
1364
+ * @return Microsoft_WindowsAzure_Storage_BlobInstance
1365
+ * @throws Microsoft_WindowsAzure_Exception
1366
+ */
1367
+ public function getBlobInstance($containerName = '', $blobName = '', $snapshotId = null, $leaseId = null, $additionalHeaders = array())
1368
+ {
1369
+ if ($containerName === '') {
1370
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
1371
+ }
1372
+ if (!self::isValidContainerName($containerName)) {
1373
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1374
+ }
1375
+ if ($blobName === '') {
1376
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
1377
+ }
1378
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
1379
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
1380
+ }
1381
+
1382
+ // Build query string
1383
+ $queryString = array();
1384
+ if (!is_null($snapshotId)) {
1385
+ $queryString[] = 'snapshot=' . $snapshotId;
1386
+ }
1387
+ $queryString = self::createQueryStringFromArray($queryString);
1388
+
1389
+ // Additional headers?
1390
+ $headers = array();
1391
+ if (!is_null($leaseId)) {
1392
+ $headers['x-ms-lease-id'] = $leaseId;
1393
+ }
1394
+ foreach ($additionalHeaders as $key => $value) {
1395
+ $headers[$key] = $value;
1396
+ }
1397
+
1398
+ // Resource name
1399
+ $resourceName = self::createResourceName($containerName , $blobName);
1400
+
1401
+ // Perform request
1402
+ $response = $this->_performRequest($resourceName, $queryString, Microsoft_Http_Client::HEAD, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ);
1403
+ if ($response->isSuccessful()) {
1404
+ // Parse metadata
1405
+ $metadata = $this->_parseMetadataHeaders($response->getHeaders());
1406
+
1407
+ // Return blob
1408
+ return new Microsoft_WindowsAzure_Storage_BlobInstance(
1409
+ $containerName,
1410
+ $blobName,
1411
+ $snapshotId,
1412
+ $response->getHeader('Etag'),
1413
+ $response->getHeader('Last-modified'),
1414
+ $this->getBaseUrl() . '/' . $containerName . '/' . $blobName,
1415
+ $response->getHeader('Content-Length'),
1416
+ $response->getHeader('Content-Type'),
1417
+ $response->getHeader('Content-Encoding'),
1418
+ $response->getHeader('Content-Language'),
1419
+ $response->getHeader('Cache-Control'),
1420
+ $response->getHeader('x-ms-blob-type'),
1421
+ $response->getHeader('x-ms-lease-status'),
1422
+ false,
1423
+ $metadata
1424
+ );
1425
+ } else {
1426
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
1427
+ }
1428
+ }
1429
+
1430
+ /**
1431
+ * Get blob metadata
1432
+ *
1433
+ * @param string $containerName Container name
1434
+ * @param string $blobName Blob name
1435
+ * @param string $snapshotId Snapshot identifier
1436
+ * @param string $leaseId Lease identifier
1437
+ * @return array Key/value pairs of meta data
1438
+ * @throws Microsoft_WindowsAzure_Exception
1439
+ */
1440
+ public function getBlobMetadata($containerName = '', $blobName = '', $snapshotId = null, $leaseId = null)
1441
+ {
1442
+ if ($containerName === '') {
1443
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
1444
+ }
1445
+ if (!self::isValidContainerName($containerName)) {
1446
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1447
+ }
1448
+ if ($blobName === '') {
1449
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
1450
+ }
1451
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
1452
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
1453
+ }
1454
+
1455
+ return $this->getBlobInstance($containerName, $blobName, $snapshotId, $leaseId)->Metadata;
1456
+ }
1457
+
1458
+ /**
1459
+ * Set blob metadata
1460
+ *
1461
+ * Calling the Set Blob Metadata operation overwrites all existing metadata that is associated with the blob. It's not possible to modify an individual name/value pair.
1462
+ *
1463
+ * @param string $containerName Container name
1464
+ * @param string $blobName Blob name
1465
+ * @param array $metadata Key/value pairs of meta data
1466
+ * @param string $leaseId Lease identifier
1467
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
1468
+ * @throws Microsoft_WindowsAzure_Exception
1469
+ */
1470
+ public function setBlobMetadata($containerName = '', $blobName = '', $metadata = array(), $leaseId = null, $additionalHeaders = array())
1471
+ {
1472
+ if ($containerName === '') {
1473
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
1474
+ }
1475
+ if (!self::isValidContainerName($containerName)) {
1476
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1477
+ }
1478
+ if ($blobName === '') {
1479
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
1480
+ }
1481
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
1482
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
1483
+ }
1484
+ if (count($metadata) == 0) {
1485
+ return;
1486
+ }
1487
+
1488
+ // Create metadata headers
1489
+ $headers = array();
1490
+ if (!is_null($leaseId)) {
1491
+ $headers['x-ms-lease-id'] = $leaseId;
1492
+ }
1493
+ $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata));
1494
+
1495
+ // Additional headers?
1496
+ foreach ($additionalHeaders as $key => $value) {
1497
+ $headers[$key] = $value;
1498
+ }
1499
+
1500
+ // Perform request
1501
+ $response = $this->_performRequest($containerName . '/' . $blobName, '?comp=metadata', Microsoft_Http_Client::PUT, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
1502
+ if (!$response->isSuccessful()) {
1503
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
1504
+ }
1505
+ }
1506
+
1507
+ /**
1508
+ * Set blob properties
1509
+ *
1510
+ * All available properties are listed at http://msdn.microsoft.com/en-us/library/ee691966.aspx and should be provided in the $additionalHeaders parameter.
1511
+ *
1512
+ * @param string $containerName Container name
1513
+ * @param string $blobName Blob name
1514
+ * @param string $leaseId Lease identifier
1515
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
1516
+ * @throws Microsoft_WindowsAzure_Exception
1517
+ */
1518
+ public function setBlobProperties($containerName = '', $blobName = '', $leaseId = null, $additionalHeaders = array())
1519
+ {
1520
+ if ($containerName === '') {
1521
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
1522
+ }
1523
+ if (!self::isValidContainerName($containerName)) {
1524
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1525
+ }
1526
+ if ($blobName === '') {
1527
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
1528
+ }
1529
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
1530
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
1531
+ }
1532
+ if (count($additionalHeaders) == 0) {
1533
+ throw new Microsoft_WindowsAzure_Exception('No additional headers are specified.');
1534
+ }
1535
+
1536
+ // Create headers
1537
+ $headers = array();
1538
+
1539
+ // Lease set?
1540
+ if (!is_null($leaseId)) {
1541
+ $headers['x-ms-lease-id'] = $leaseId;
1542
+ }
1543
+
1544
+ // Additional headers?
1545
+ foreach ($additionalHeaders as $key => $value) {
1546
+ $headers[$key] = $value;
1547
+ }
1548
+
1549
+ // Perform request
1550
+ $response = $this->_performRequest($containerName . '/' . $blobName, '?comp=properties', Microsoft_Http_Client::PUT, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
1551
+ if (!$response->isSuccessful()) {
1552
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
1553
+ }
1554
+ }
1555
+
1556
+ /**
1557
+ * Get blob properties
1558
+ *
1559
+ * @param string $containerName Container name
1560
+ * @param string $blobName Blob name
1561
+ * @param string $snapshotId Snapshot identifier
1562
+ * @param string $leaseId Lease identifier
1563
+ * @return Microsoft_WindowsAzure_Storage_BlobInstance
1564
+ * @throws Microsoft_WindowsAzure_Exception
1565
+ */
1566
+ public function getBlobProperties($containerName = '', $blobName = '', $snapshotId = null, $leaseId = null)
1567
+ {
1568
+ if ($containerName === '') {
1569
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
1570
+ }
1571
+ if (!self::isValidContainerName($containerName)) {
1572
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1573
+ }
1574
+ if ($blobName === '') {
1575
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
1576
+ }
1577
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
1578
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
1579
+ }
1580
+
1581
+ return $this->getBlobInstance($containerName, $blobName, $snapshotId, $leaseId);
1582
+ }
1583
+
1584
+ /**
1585
+ * Delete blob
1586
+ *
1587
+ * @param string $containerName Container name
1588
+ * @param string $blobName Blob name
1589
+ * @param string $snapshotId Snapshot identifier
1590
+ * @param string $leaseId Lease identifier
1591
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
1592
+ * @throws Microsoft_WindowsAzure_Exception
1593
+ */
1594
+ public function deleteBlob($containerName = '', $blobName = '', $snapshotId = null, $leaseId = null, $additionalHeaders = array())
1595
+ {
1596
+ if ($containerName === '') {
1597
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
1598
+ }
1599
+ if (!self::isValidContainerName($containerName)) {
1600
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1601
+ }
1602
+ if ($blobName === '') {
1603
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
1604
+ }
1605
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
1606
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
1607
+ }
1608
+
1609
+ // Build query string
1610
+ $queryString = array();
1611
+ if (!is_null($snapshotId)) {
1612
+ $queryString[] = 'snapshot=' . $snapshotId;
1613
+ }
1614
+ $queryString = self::createQueryStringFromArray($queryString);
1615
+
1616
+ // Additional headers?
1617
+ $headers = array();
1618
+ if (!is_null($leaseId)) {
1619
+ $headers['x-ms-lease-id'] = $leaseId;
1620
+ }
1621
+ foreach ($additionalHeaders as $key => $value) {
1622
+ $headers[$key] = $value;
1623
+ }
1624
+
1625
+ // Resource name
1626
+ $resourceName = self::createResourceName($containerName , $blobName);
1627
+
1628
+ // Perform request
1629
+ $response = $this->_performRequest($resourceName, $queryString, Microsoft_Http_Client::DELETE, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
1630
+ if (!$response->isSuccessful()) {
1631
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
1632
+ }
1633
+ }
1634
+
1635
+ /**
1636
+ * Snapshot blob
1637
+ *
1638
+ * @param string $containerName Container name
1639
+ * @param string $blobName Blob name
1640
+ * @param array $metadata Key/value pairs of meta data
1641
+ * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
1642
+ * @return string Date/Time value representing the snapshot identifier.
1643
+ * @throws Microsoft_WindowsAzure_Exception
1644
+ */
1645
+ public function snapshotBlob($containerName = '', $blobName = '', $metadata = array(), $additionalHeaders = array())
1646
+ {
1647
+ if ($containerName === '') {
1648
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
1649
+ }
1650
+ if (!self::isValidContainerName($containerName)) {
1651
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1652
+ }
1653
+ if ($blobName === '') {
1654
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
1655
+ }
1656
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
1657
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
1658
+ }
1659
+
1660
+ // Additional headers?
1661
+ $headers = array();
1662
+ foreach ($additionalHeaders as $key => $value) {
1663
+ $headers[$key] = $value;
1664
+ }
1665
+
1666
+ // Resource name
1667
+ $resourceName = self::createResourceName($containerName , $blobName);
1668
+
1669
+ // Perform request
1670
+ $response = $this->_performRequest($resourceName, '?comp=snapshot', Microsoft_Http_Client::PUT, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
1671
+ if ($response->isSuccessful()) {
1672
+ return $response->getHeader('x-ms-snapshot');
1673
+ } else {
1674
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
1675
+ }
1676
+ }
1677
+
1678
+ /**
1679
+ * Lease blob - See (http://msdn.microsoft.com/en-us/library/ee691972.aspx)
1680
+ *
1681
+ * @param string $containerName Container name
1682
+ * @param string $blobName Blob name
1683
+ * @param string $leaseAction Lease action (Microsoft_WindowsAzure_Storage_Blob::LEASE_*)
1684
+ * @param string $leaseId Lease identifier, required to renew the lease or to release the lease.
1685
+ * @return Microsoft_WindowsAzure_Storage_LeaseInstance Lease instance
1686
+ * @throws Microsoft_WindowsAzure_Exception
1687
+ */
1688
+ public function leaseBlob($containerName = '', $blobName = '', $leaseAction = self::LEASE_ACQUIRE, $leaseId = null)
1689
+ {
1690
+ if ($containerName === '') {
1691
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
1692
+ }
1693
+ if (!self::isValidContainerName($containerName)) {
1694
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1695
+ }
1696
+ if ($blobName === '') {
1697
+ throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
1698
+ }
1699
+ if ($containerName === '$root' && strpos($blobName, '/') !== false) {
1700
+ throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
1701
+ }
1702
+
1703
+ // Additional headers?
1704
+ $headers = array();
1705
+ $headers['x-ms-lease-action'] = strtolower($leaseAction);
1706
+ if (!is_null($leaseId)) {
1707
+ $headers['x-ms-lease-id'] = $leaseId;
1708
+ }
1709
+
1710
+ // Resource name
1711
+ $resourceName = self::createResourceName($containerName , $blobName);
1712
+
1713
+ // Perform request
1714
+ $response = $this->_performRequest($resourceName, '?comp=lease', Microsoft_Http_Client::PUT, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
1715
+ if ($response->isSuccessful()) {
1716
+ return new Microsoft_WindowsAzure_Storage_LeaseInstance(
1717
+ $containerName,
1718
+ $blobName,
1719
+ $response->getHeader('x-ms-lease-id'),
1720
+ $response->getHeader('x-ms-lease-time'));
1721
+ } else {
1722
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
1723
+ }
1724
+ }
1725
+
1726
+ /**
1727
+ * List blobs
1728
+ *
1729
+ * @param string $containerName Container name
1730
+ * @param string $prefix Optional. Filters the results to return only blobs whose name begins with the specified prefix.
1731
+ * @param string $delimiter Optional. Delimiter, i.e. '/', for specifying folder hierarchy
1732
+ * @param int $maxResults Optional. Specifies the maximum number of blobs to return per call to Azure storage. This does NOT affect list size returned by this function. (maximum: 5000)
1733
+ * @param string $marker Optional string value that identifies the portion of the list to be returned with the next list operation.
1734
+ * @param string $include Optional. Specifies that the response should include one or more of the following subsets: '', 'metadata', 'snapshots', 'uncommittedblobs'). Multiple values can be added separated with a comma (,)
1735
+ * @param int $currentResultCount Current result count (internal use)
1736
+ * @return array
1737
+ * @throws Microsoft_WindowsAzure_Exception
1738
+ */
1739
+ public function listBlobs($containerName = '', $prefix = '', $delimiter = '', $maxResults = null, $marker = null, $include = null, $currentResultCount = 0)
1740
+ {
1741
+ if ($containerName === '') {
1742
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
1743
+ }
1744
+ if (!self::isValidContainerName($containerName)) {
1745
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1746
+ }
1747
+
1748
+ // Build query string
1749
+ $queryString = array('restype=container', 'comp=list');
1750
+ if (!is_null($prefix)) {
1751
+ $queryString[] = 'prefix=' . $prefix;
1752
+ }
1753
+ if ($delimiter !== '') {
1754
+ $queryString[] = 'delimiter=' . $delimiter;
1755
+ }
1756
+ if (!is_null($maxResults)) {
1757
+ $queryString[] = 'maxresults=' . $maxResults;
1758
+ }
1759
+ if (!is_null($marker)) {
1760
+ $queryString[] = 'marker=' . $marker;
1761
+ }
1762
+ if (!is_null($include)) {
1763
+ $queryString[] = 'include=' . $include;
1764
+ }
1765
+ $queryString = self::createQueryStringFromArray($queryString);
1766
+
1767
+ // Perform request
1768
+ $response = $this->_performRequest($containerName, $queryString, Microsoft_Http_Client::GET, array(), false, null, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_LIST);
1769
+ if ($response->isSuccessful()) {
1770
+ // Return value
1771
+ $blobs = array();
1772
+
1773
+ // Blobs
1774
+ $xmlBlobs = $this->_parseResponse($response)->Blobs->Blob;
1775
+ if (!is_null($xmlBlobs)) {
1776
+ for ($i = 0; $i < count($xmlBlobs); $i++) {
1777
+ $properties = (array)$xmlBlobs[$i]->Properties;
1778
+
1779
+ $blobs[] = new Microsoft_WindowsAzure_Storage_BlobInstance(
1780
+ $containerName,
1781
+ (string)$xmlBlobs[$i]->Name,
1782
+ (string)$xmlBlobs[$i]->Snapshot,
1783
+ (string)$properties['Etag'],
1784
+ (string)$properties['Last-Modified'],
1785
+ (string)$xmlBlobs[$i]->Url,
1786
+ (string)$properties['Content-Length'],
1787
+ (string)$properties['Content-Type'],
1788
+ (string)$properties['Content-Encoding'],
1789
+ (string)$properties['Content-Language'],
1790
+ (string)$properties['Cache-Control'],
1791
+ (string)$properties['BlobType'],
1792
+ (string)$properties['LeaseStatus'],
1793
+ false,
1794
+ $this->_parseMetadataElement($xmlBlobs[$i])
1795
+ );
1796
+ }
1797
+ }
1798
+
1799
+ // Blob prefixes (folders)
1800
+ $xmlBlobs = $this->_parseResponse($response)->Blobs->BlobPrefix;
1801
+
1802
+ if (!is_null($xmlBlobs)) {
1803
+ for ($i = 0; $i < count($xmlBlobs); $i++) {
1804
+ $blobs[] = new Microsoft_WindowsAzure_Storage_BlobInstance(
1805
+ $containerName,
1806
+ (string)$xmlBlobs[$i]->Name,
1807
+ null,
1808
+ '',
1809
+ '',
1810
+ '',
1811
+ 0,
1812
+ '',
1813
+ '',
1814
+ '',
1815
+ '',
1816
+ '',
1817
+ '',
1818
+ true,
1819
+ $this->_parseMetadataElement($xmlBlobs[$i])
1820
+ );
1821
+ }
1822
+ }
1823
+
1824
+ // More blobs?
1825
+ $xmlMarker = (string)$this->_parseResponse($response)->NextMarker;
1826
+ $currentResultCount = $currentResultCount + count($blobs);
1827
+ if (!is_null($maxResults) && $currentResultCount < $maxResults) {
1828
+ if (!is_null($xmlMarker) && $xmlMarker != '') {
1829
+ $blobs = array_merge($blobs, $this->listBlobs($containerName, $prefix, $delimiter, $maxResults, $marker, $include, $currentResultCount));
1830
+ }
1831
+ }
1832
+ if (!is_null($maxResults) && count($blobs) > $maxResults) {
1833
+ $blobs = array_slice($blobs, 0, $maxResults);
1834
+ }
1835
+
1836
+ return $blobs;
1837
+ } else {
1838
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
1839
+ }
1840
+ }
1841
+
1842
+ /**
1843
+ * Generate shared access URL
1844
+ *
1845
+ * @param string $containerName Container name
1846
+ * @param string $blobName Blob name
1847
+ * @param string $resource Signed resource - container (c) - blob (b)
1848
+ * @param string $permissions Signed permissions - read (r), write (w), delete (d) and list (l)
1849
+ * @param string $start The time at which the Shared Access Signature becomes valid.
1850
+ * @param string $expiry The time at which the Shared Access Signature becomes invalid.
1851
+ * @param string $identifier Signed identifier
1852
+ * @return string
1853
+ */
1854
+ public function generateSharedAccessUrl($containerName = '', $blobName = '', $resource = 'b', $permissions = 'r', $start = '', $expiry = '', $identifier = '')
1855
+ {
1856
+ if ($containerName === '') {
1857
+ throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
1858
+ }
1859
+ if (!self::isValidContainerName($containerName)) {
1860
+ throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
1861
+ }
1862
+
1863
+ // Resource name
1864
+ $resourceName = self::createResourceName($containerName , $blobName);
1865
+
1866
+ // Generate URL
1867
+ return $this->getBaseUrl() . '/' . $resourceName . '?' .
1868
+ $this->_sharedAccessSignatureCredentials->createSignedQueryString(
1869
+ $resourceName,
1870
+ '',
1871
+ $resource,
1872
+ $permissions,
1873
+ $start,
1874
+ $expiry,
1875
+ $identifier);
1876
+ }
1877
+
1878
+ /**
1879
+ * Register this object as stream wrapper client
1880
+ *
1881
+ * @param string $name Protocol name
1882
+ * @return Microsoft_WindowsAzure_Storage_Blob
1883
+ */
1884
+ public function registerAsClient($name)
1885
+ {
1886
+ self::$_wrapperClients[$name] = $this;
1887
+ return $this;
1888
+ }
1889
+
1890
+ /**
1891
+ * Unregister this object as stream wrapper client
1892
+ *
1893
+ * @param string $name Protocol name
1894
+ * @return Microsoft_WindowsAzure_Storage_Blob
1895
+ */
1896
+ public function unregisterAsClient($name)
1897
+ {
1898
+ unset(self::$_wrapperClients[$name]);
1899
+ return $this;
1900
+ }
1901
+
1902
+ /**
1903
+ * Get wrapper client for stream type
1904
+ *
1905
+ * @param string $name Protocol name
1906
+ * @return Microsoft_WindowsAzure_Storage_Blob
1907
+ */
1908
+ public static function getWrapperClient($name)
1909
+ {
1910
+ return self::$_wrapperClients[$name];
1911
+ }
1912
+
1913
+ /**
1914
+ * Register this object as stream wrapper
1915
+ *
1916
+ * @param string $name Protocol name
1917
+ */
1918
+ public function registerStreamWrapper($name = 'azure')
1919
+ {
1920
+ /**
1921
+ * @see Microsoft_WindowsAzure_Storage_Blob_Stream
1922
+ */
1923
+ require_once 'Microsoft/WindowsAzure/Storage/Blob/Stream.php';
1924
+
1925
+ stream_register_wrapper($name, 'Microsoft_WindowsAzure_Storage_Blob_Stream');
1926
+ $this->registerAsClient($name);
1927
+ }
1928
+
1929
+ /**
1930
+ * Unregister this object as stream wrapper
1931
+ *
1932
+ * @param string $name Protocol name
1933
+ * @return Microsoft_WindowsAzure_Storage_Blob
1934
+ */
1935
+ public function unregisterStreamWrapper($name = 'azure')
1936
+ {
1937
+ stream_wrapper_unregister($name);
1938
+ $this->unregisterAsClient($name);
1939
+ }
1940
+
1941
+ /**
1942
+ * Create resource name
1943
+ *
1944
+ * @param string $containerName Container name
1945
+ * @param string $blobName Blob name
1946
+ * @return string
1947
+ */
1948
+ public static function createResourceName($containerName = '', $blobName = '')
1949
+ {
1950
+ // Resource name
1951
+ $resourceName = $containerName . '/' . $blobName;
1952
+ if ($containerName === '' || $containerName === '$root') {
1953
+ $resourceName = $blobName;
1954
+ }
1955
+ if ($blobName === '') {
1956
+ $resourceName = $containerName;
1957
+ }
1958
+
1959
+ return $resourceName;
1960
+ }
1961
+
1962
+ /**
1963
+ * Is valid container name?
1964
+ *
1965
+ * @param string $containerName Container name
1966
+ * @return boolean
1967
+ */
1968
+ public static function isValidContainerName($containerName = '')
1969
+ {
1970
+ if ($containerName == '$root') {
1971
+ return true;
1972
+ }
1973
+
1974
+ if (preg_match("/^[a-z0-9][a-z0-9-]*$/", $containerName) === 0) {
1975
+ return false;
1976
+ }
1977
+
1978
+ if (strpos($containerName, '--') !== false) {
1979
+ return false;
1980
+ }
1981
+
1982
+ if (strtolower($containerName) != $containerName) {
1983
+ return false;
1984
+ }
1985
+
1986
+ if (strlen($containerName) < 3 || strlen($containerName) > 63) {
1987
+ return false;
1988
+ }
1989
+
1990
+ if (substr($containerName, -1) == '-') {
1991
+ return false;
1992
+ }
1993
+
1994
+ return true;
1995
+ }
1996
+
1997
+ /**
1998
+ * Get error message from Microsoft_Http_Response
1999
+ *
2000
+ * @param Microsoft_Http_Response $response Repsonse
2001
+ * @param string $alternativeError Alternative error message
2002
+ * @return string
2003
+ */
2004
+ protected function _getErrorMessage(Microsoft_Http_Response $response, $alternativeError = 'Unknown error.')
2005
+ {
2006
+ $response = $this->_parseResponse($response);
2007
+ if ($response && $response->Message) {
2008
+ return (string)$response->Message;
2009
+ } else {
2010
+ return $alternativeError;
2011
+ }
2012
+ }
2013
+
2014
+ /**
2015
+ * Generate block id
2016
+ *
2017
+ * @param int $part Block number
2018
+ * @return string Windows Azure Blob Storage block number
2019
+ */
2020
+ protected function _generateBlockId($part = 0)
2021
+ {
2022
+ $returnValue = $part;
2023
+ while (strlen($returnValue) < 64) {
2024
+ $returnValue = '0' . $returnValue;
2025
+ }
2026
+
2027
+ return $returnValue;
2028
+ }
2029
+ }
app/libs/Microsoft/WindowsAzure/Storage/Blob/Stream.php ADDED
@@ -0,0 +1,578 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure_Storage
30
+ * @subpackage Blob
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://todo name_todo
33
+ * @version $Id: Blob.php 24511 2009-07-28 09:17:56Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Storage_Blob
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Storage/Blob.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Exception
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Exception.php';
45
+
46
+
47
+ /**
48
+ * @category Microsoft
49
+ * @package Microsoft_WindowsAzure_Storage
50
+ * @subpackage Blob
51
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
52
+ * @license http://phpazure.codeplex.com/license
53
+ */
54
+ class Microsoft_WindowsAzure_Storage_Blob_Stream
55
+ {
56
+ /**
57
+ * Current file name
58
+ *
59
+ * @var string
60
+ */
61
+ private $_fileName = null;
62
+
63
+ /**
64
+ * Temporary file name
65
+ *
66
+ * @var string
67
+ */
68
+ private $_temporaryFileName = null;
69
+
70
+ /**
71
+ * Temporary file handle
72
+ *
73
+ * @var resource
74
+ */
75
+ private $_temporaryFileHandle = null;
76
+
77
+ /**
78
+ * Blob storage client
79
+ *
80
+ * @var Microsoft_WindowsAzure_Storage_Blob
81
+ */
82
+ private $_storageClient = null;
83
+
84
+ /**
85
+ * Write mode?
86
+ *
87
+ * @var boolean
88
+ */
89
+ private $_writeMode = false;
90
+
91
+ /**
92
+ * List of blobs
93
+ *
94
+ * @var array
95
+ */
96
+ private $_blobs = null;
97
+
98
+ /**
99
+ * Retrieve storage client for this stream type
100
+ *
101
+ * @param string $path
102
+ * @return Microsoft_WindowsAzure_Storage_Blob
103
+ */
104
+ protected function _getStorageClient($path = '')
105
+ {
106
+ if (is_null($this->_storageClient)) {
107
+ $url = explode(':', $path);
108
+ if (!$url) {
109
+ throw new Microsoft_WindowsAzure_Exception('Could not parse path "' . $path . '".');
110
+ }
111
+
112
+ $this->_storageClient = Microsoft_WindowsAzure_Storage_Blob::getWrapperClient($url[0]);
113
+ if (!$this->_storageClient) {
114
+ throw new Microsoft_WindowsAzure_Exception('No storage client registered for stream type "' . $url[0] . '://".');
115
+ }
116
+ }
117
+
118
+ return $this->_storageClient;
119
+ }
120
+
121
+ /**
122
+ * Extract container name
123
+ *
124
+ * @param string $path
125
+ * @return string
126
+ */
127
+ protected function _getContainerName($path)
128
+ {
129
+ $url = parse_url($path);
130
+ if ($url['host']) {
131
+ return $url['host'];
132
+ }
133
+
134
+ return '';
135
+ }
136
+
137
+ /**
138
+ * Extract file name
139
+ *
140
+ * @param string $path
141
+ * @return string
142
+ */
143
+ protected function _getFileName($path)
144
+ {
145
+ $url = parse_url($path);
146
+ if ($url['host']) {
147
+ $fileName = isset($url['path']) ? $url['path'] : $url['host'];
148
+ if (strpos($fileName, '/') === 0) {
149
+ $fileName = substr($fileName, 1);
150
+ }
151
+ return $fileName;
152
+ }
153
+
154
+ return '';
155
+ }
156
+
157
+ /**
158
+ * Open the stream
159
+ *
160
+ * @param string $path
161
+ * @param string $mode
162
+ * @param integer $options
163
+ * @param string $opened_path
164
+ * @return boolean
165
+ */
166
+ public function stream_open($path, $mode, $options, $opened_path)
167
+ {
168
+ $this->_fileName = $path;
169
+ $this->_temporaryFileName = tempnam(sys_get_temp_dir(), 'azure');
170
+
171
+ // Check the file can be opened
172
+ $fh = @fopen($this->_temporaryFileName, $mode);
173
+ if ($fh === false) {
174
+ return false;
175
+ }
176
+ fclose($fh);
177
+
178
+ // Write mode?
179
+ if (strpbrk($mode, 'wax+')) {
180
+ $this->_writeMode = true;
181
+ } else {
182
+ $this->_writeMode = false;
183
+ }
184
+
185
+ // If read/append, fetch the file
186
+ if (!$this->_writeMode || strpbrk($mode, 'ra+')) {
187
+ $this->_getStorageClient($this->_fileName)->getBlob(
188
+ $this->_getContainerName($this->_fileName),
189
+ $this->_getFileName($this->_fileName),
190
+ $this->_temporaryFileName
191
+ );
192
+ }
193
+
194
+ // Open temporary file handle
195
+ $this->_temporaryFileHandle = fopen($this->_temporaryFileName, $mode);
196
+
197
+ // Ok!
198
+ return true;
199
+ }
200
+
201
+ /**
202
+ * Close the stream
203
+ *
204
+ * @return void
205
+ */
206
+ public function stream_close()
207
+ {
208
+ @fclose($this->_temporaryFileHandle);
209
+
210
+ // Upload the file?
211
+ if ($this->_writeMode) {
212
+ // Make sure the container exists
213
+ $containerExists = $this->_getStorageClient($this->_fileName)->containerExists(
214
+ $this->_getContainerName($this->_fileName)
215
+ );
216
+ if (!$containerExists) {
217
+ $this->_getStorageClient($this->_fileName)->createContainer(
218
+ $this->_getContainerName($this->_fileName)
219
+ );
220
+ }
221
+
222
+ // Upload the file
223
+ try {
224
+ $this->_getStorageClient($this->_fileName)->putBlob(
225
+ $this->_getContainerName($this->_fileName),
226
+ $this->_getFileName($this->_fileName),
227
+ $this->_temporaryFileName
228
+ );
229
+ } catch (Microsoft_WindowsAzure_Exception $ex) {
230
+ @unlink($this->_temporaryFileName);
231
+ unset($this->_storageClient);
232
+
233
+ throw $ex;
234
+ }
235
+ }
236
+
237
+ @unlink($this->_temporaryFileName);
238
+ unset($this->_storageClient);
239
+ }
240
+
241
+ /**
242
+ * Read from the stream
243
+ *
244
+ * @param integer $count
245
+ * @return string
246
+ */
247
+ public function stream_read($count)
248
+ {
249
+ if (!$this->_temporaryFileHandle) {
250
+ return false;
251
+ }
252
+
253
+ return fread($this->_temporaryFileHandle, $count);
254
+ }
255
+
256
+ /**
257
+ * Write to the stream
258
+ *
259
+ * @param string $data
260
+ * @return integer
261
+ */
262
+ public function stream_write($data)
263
+ {
264
+ if (!$this->_temporaryFileHandle) {
265
+ return 0;
266
+ }
267
+
268
+ $len = strlen($data);
269
+ fwrite($this->_temporaryFileHandle, $data, $len);
270
+ return $len;
271
+ }
272
+
273
+ /**
274
+ * End of the stream?
275
+ *
276
+ * @return boolean
277
+ */
278
+ public function stream_eof()
279
+ {
280
+ if (!$this->_temporaryFileHandle) {
281
+ return true;
282
+ }
283
+
284
+ return feof($this->_temporaryFileHandle);
285
+ }
286
+
287
+ /**
288
+ * What is the current read/write position of the stream?
289
+ *
290
+ * @return integer
291
+ */
292
+ public function stream_tell()
293
+ {
294
+ return ftell($this->_temporaryFileHandle);
295
+ }
296
+
297
+ /**
298
+ * Update the read/write position of the stream
299
+ *
300
+ * @param integer $offset
301
+ * @param integer $whence
302
+ * @return boolean
303
+ */
304
+ public function stream_seek($offset, $whence)
305
+ {
306
+ if (!$this->_temporaryFileHandle) {
307
+ return false;
308
+ }
309
+
310
+ return (fseek($this->_temporaryFileHandle, $offset, $whence) === 0);
311
+ }
312
+
313
+ /**
314
+ * Flush current cached stream data to storage
315
+ *
316
+ * @return boolean
317
+ */
318
+ public function stream_flush()
319
+ {
320
+ $result = fflush($this->_temporaryFileHandle);
321
+
322
+ // Upload the file?
323
+ if ($this->_writeMode) {
324
+ // Make sure the container exists
325
+ $containerExists = $this->_getStorageClient($this->_fileName)->containerExists(
326
+ $this->_getContainerName($this->_fileName)
327
+ );
328
+ if (!$containerExists) {
329
+ $this->_getStorageClient($this->_fileName)->createContainer(
330
+ $this->_getContainerName($this->_fileName)
331
+ );
332
+ }
333
+
334
+ // Upload the file
335
+ try {
336
+ $this->_getStorageClient($this->_fileName)->putBlob(
337
+ $this->_getContainerName($this->_fileName),
338
+ $this->_getFileName($this->_fileName),
339
+ $this->_temporaryFileName
340
+ );
341
+ } catch (Microsoft_WindowsAzure_Exception $ex) {
342
+ @unlink($this->_temporaryFileName);
343
+ unset($this->_storageClient);
344
+
345
+ throw $ex;
346
+ }
347
+ }
348
+
349
+ return $result;
350
+ }
351
+
352
+ /**
353
+ * Returns data array of stream variables
354
+ *
355
+ * @return array
356
+ */
357
+ public function stream_stat()
358
+ {
359
+ if (!$this->_temporaryFileHandle) {
360
+ return false;
361
+ }
362
+
363
+ $stat = array();
364
+ $stat['dev'] = 0;
365
+ $stat['ino'] = 0;
366
+ $stat['mode'] = 0;
367
+ $stat['nlink'] = 0;
368
+ $stat['uid'] = 0;
369
+ $stat['gid'] = 0;
370
+ $stat['rdev'] = 0;
371
+ $stat['size'] = 0;
372
+ $stat['atime'] = 0;
373
+ $stat['mtime'] = 0;
374
+ $stat['ctime'] = 0;
375
+ $stat['blksize'] = 0;
376
+ $stat['blocks'] = 0;
377
+
378
+ $info = null;
379
+ try {
380
+ $info = $this->_getStorageClient($this->_fileName)->getBlobInstance(
381
+ $this->_getContainerName($this->_fileName),
382
+ $this->_getFileName($this->_fileName)
383
+ );
384
+ } catch (Microsoft_WindowsAzure_Exception $ex) {
385
+ // Unexisting file...
386
+ }
387
+ if (!is_null($info)) {
388
+ $stat['size'] = $info->Size;
389
+ $stat['atime'] = time();
390
+ }
391
+
392
+ return $stat;
393
+ }
394
+
395
+ /**
396
+ * Attempt to delete the item
397
+ *
398
+ * @param string $path
399
+ * @return boolean
400
+ */
401
+ public function unlink($path)
402
+ {
403
+ $this->_getStorageClient($path)->deleteBlob(
404
+ $this->_getContainerName($path),
405
+ $this->_getFileName($path)
406
+ );
407
+ }
408
+
409
+ /**
410
+ * Attempt to rename the item
411
+ *
412
+ * @param string $path_from
413
+ * @param string $path_to
414
+ * @return boolean False
415
+ */
416
+ public function rename($path_from, $path_to)
417
+ {
418
+ if ($this->_getContainerName($path_from) != $this->_getContainerName($path_to)) {
419
+ throw new Microsoft_WindowsAzure_Exception('Container name can not be changed.');
420
+ }
421
+
422
+ if ($this->_getFileName($path_from) == $this->_getContainerName($path_to)) {
423
+ return true;
424
+ }
425
+
426
+ $this->_getStorageClient($path_from)->copyBlob(
427
+ $this->_getContainerName($path_from),
428
+ $this->_getFileName($path_from),
429
+ $this->_getContainerName($path_to),
430
+ $this->_getFileName($path_to)
431
+ );
432
+ $this->_getStorageClient($path_from)->deleteBlob(
433
+ $this->_getContainerName($path_from),
434
+ $this->_getFileName($path_from)
435
+ );
436
+ return true;
437
+ }
438
+
439
+ /**
440
+ * Return array of URL variables
441
+ *
442
+ * @param string $path
443
+ * @param integer $flags
444
+ * @return array
445
+ */
446
+ public function url_stat($path, $flags)
447
+ {
448
+ $stat = array();
449
+ $stat['dev'] = 0;
450
+ $stat['ino'] = 0;
451
+ $stat['mode'] = 0;
452
+ $stat['nlink'] = 0;
453
+ $stat['uid'] = 0;
454
+ $stat['gid'] = 0;
455
+ $stat['rdev'] = 0;
456
+ $stat['size'] = 0;
457
+ $stat['atime'] = 0;
458
+ $stat['mtime'] = 0;
459
+ $stat['ctime'] = 0;
460
+ $stat['blksize'] = 0;
461
+ $stat['blocks'] = 0;
462
+
463
+ $info = null;
464
+ try {
465
+ $info = $this->_getStorageClient($path)->getBlobInstance(
466
+ $this->_getContainerName($path),
467
+ $this->_getFileName($path)
468
+ );
469
+ } catch (Microsoft_WindowsAzure_Exception $ex) {
470
+ // Unexisting file...
471
+ }
472
+ if (!is_null($info)) {
473
+ $stat['size'] = $info->Size;
474
+ $stat['atime'] = time();
475
+ }
476
+
477
+ return $stat;
478
+ }
479
+
480
+ /**
481
+ * Create a new directory
482
+ *
483
+ * @param string $path
484
+ * @param integer $mode
485
+ * @param integer $options
486
+ * @return boolean
487
+ */
488
+ public function mkdir($path, $mode, $options)
489
+ {
490
+ if ($this->_getContainerName($path) == $this->_getFileName($path)) {
491
+ // Create container
492
+ try {
493
+ $this->_getStorageClient($path)->createContainer(
494
+ $this->_getContainerName($path)
495
+ );
496
+ } catch (Microsoft_WindowsAzure_Exception $ex) {
497
+ return false;
498
+ }
499
+ } else {
500
+ throw new Microsoft_WindowsAzure_Exception('mkdir() with multiple levels is not supported on Windows Azure Blob Storage.');
501
+ }
502
+ }
503
+
504
+ /**
505
+ * Remove a directory
506
+ *
507
+ * @param string $path
508
+ * @param integer $options
509
+ * @return boolean
510
+ */
511
+ public function rmdir($path, $options)
512
+ {
513
+ if ($this->_getContainerName($path) == $this->_getFileName($path)) {
514
+ // Delete container
515
+ try {
516
+ $this->_getStorageClient($path)->deleteContainer(
517
+ $this->_getContainerName($path)
518
+ );
519
+ } catch (Microsoft_WindowsAzure_Exception $ex) {
520
+ return false;
521
+ }
522
+ } else {
523
+ throw new Microsoft_WindowsAzure_Exception('rmdir() with multiple levels is not supported on Windows Azure Blob Storage.');
524
+ }
525
+ }
526
+
527
+ /**
528
+ * Attempt to open a directory
529
+ *
530
+ * @param string $path
531
+ * @param integer $options
532
+ * @return boolean
533
+ */
534
+ public function dir_opendir($path, $options)
535
+ {
536
+ $this->_blobs = $this->_getStorageClient($path)->listBlobs(
537
+ $this->_getContainerName($path)
538
+ );
539
+ return is_array($this->_blobs);
540
+ }
541
+
542
+ /**
543
+ * Return the next filename in the directory
544
+ *
545
+ * @return string
546
+ */
547
+ public function dir_readdir()
548
+ {
549
+ $object = current($this->_blobs);
550
+ if ($object !== false) {
551
+ next($this->_blobs);
552
+ return $object->Name;
553
+ }
554
+ return false;
555
+ }
556
+
557
+ /**
558
+ * Reset the directory pointer
559
+ *
560
+ * @return boolean True
561
+ */
562
+ public function dir_rewinddir()
563
+ {
564
+ reset($this->_blobs);
565
+ return true;
566
+ }
567
+
568
+ /**
569
+ * Close a directory
570
+ *
571
+ * @return boolean True
572
+ */
573
+ public function dir_closedir()
574
+ {
575
+ $this->_blobs = null;
576
+ return true;
577
+ }
578
+ }
app/libs/Microsoft/WindowsAzure/Storage/BlobContainer.php ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Storage
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: BlobContainer.php 45989 2010-05-03 12:19:11Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Exception.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Storage_StorageEntityAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Storage/StorageEntityAbstract.php';
45
+
46
+ /**
47
+ * @category Microsoft
48
+ * @package Microsoft_WindowsAzure
49
+ * @subpackage Storage
50
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
51
+ * @license http://phpazure.codeplex.com/license
52
+ *
53
+ * @property string $Name Name of the container
54
+ * @property string $Etag Etag of the container
55
+ * @property string $LastModified Last modified date of the container
56
+ * @property array $Metadata Key/value pairs of meta data
57
+ */
58
+ class Microsoft_WindowsAzure_Storage_BlobContainer
59
+ {
60
+ /**
61
+ * Data
62
+ *
63
+ * @var array
64
+ */
65
+ protected $_data = null;
66
+
67
+ /**
68
+ * Constructor
69
+ *
70
+ * @param string $name Name
71
+ * @param string $etag Etag
72
+ * @param string $lastModified Last modified date
73
+ * @param array $metadata Key/value pairs of meta data
74
+ */
75
+ public function __construct($name, $etag, $lastModified, $metadata = array())
76
+ {
77
+ $this->_data = array(
78
+ 'name' => $name,
79
+ 'etag' => $etag,
80
+ 'lastmodified' => $lastModified,
81
+ 'metadata' => $metadata
82
+ );
83
+ }
84
+
85
+ /**
86
+ * Magic overload for setting properties
87
+ *
88
+ * @param string $name Name of the property
89
+ * @param string $value Value to set
90
+ */
91
+ public function __set($name, $value) {
92
+ if (array_key_exists(strtolower($name), $this->_data)) {
93
+ $this->_data[strtolower($name)] = $value;
94
+ return;
95
+ }
96
+
97
+ throw new Exception("Unknown property: " . $name);
98
+ }
99
+
100
+ /**
101
+ * Magic overload for getting properties
102
+ *
103
+ * @param string $name Name of the property
104
+ */
105
+ public function __get($name) {
106
+ if (array_key_exists(strtolower($name), $this->_data)) {
107
+ return $this->_data[strtolower($name)];
108
+ }
109
+
110
+ throw new Exception("Unknown property: " . $name);
111
+ }
112
+ }
app/libs/Microsoft/WindowsAzure/Storage/BlobInstance.php ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Storage
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: BlobInstance.php 53615 2010-11-16 20:45:11Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Exception.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Storage_StorageEntityAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Storage/StorageEntityAbstract.php';
45
+
46
+ /**
47
+ * @category Microsoft
48
+ * @package Microsoft_WindowsAzure
49
+ * @subpackage Storage
50
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
51
+ * @license http://phpazure.codeplex.com/license
52
+ *
53
+ * @property string $Container The name of the blob container in which the blob is stored.
54
+ * @property string $Name The name of the blob.
55
+ * @property string $SnapshotId The blob snapshot ID if it is a snapshot blob (= a backup copy of a blob).
56
+ * @property string $Etag The entity tag, used for versioning and concurrency.
57
+ * @property string $LastModified Timestamp when the blob was last modified.
58
+ * @property string $Url The full URL where the blob can be downloaded.
59
+ * @property int $Size The blob size in bytes.
60
+ * @property string $ContentType The blob content type header.
61
+ * @property string $ContentEncoding The blob content encoding header.
62
+ * @property string $ContentLanguage The blob content language header.
63
+ * @property string $CacheControl The blob cache control header.
64
+ * @property string $BlobType The blob type (block blob / page blob).
65
+ * @property string $LeaseStatus The blob lease status.
66
+ * @property boolean $IsPrefix Is it a blob or a directory prefix?
67
+ * @property array $Metadata Key/value pairs of meta data
68
+ */
69
+ class Microsoft_WindowsAzure_Storage_BlobInstance
70
+ {
71
+ /**
72
+ * Data
73
+ *
74
+ * @var array
75
+ */
76
+ protected $_data = null;
77
+
78
+ /**
79
+ * Constructor
80
+ *
81
+ * @param string $containerName Container name
82
+ * @param string $name Name
83
+ * @param string $snapshotId Snapshot id
84
+ * @param string $etag Etag
85
+ * @param string $lastModified Last modified date
86
+ * @param string $url Url
87
+ * @param int $size Size
88
+ * @param string $contentType Content Type
89
+ * @param string $contentEncoding Content Encoding
90
+ * @param string $contentLanguage Content Language
91
+ * @param string $cacheControl Cache control
92
+ * @param string $blobType Blob type
93
+ * @param string $leaseStatus Lease status
94
+ * @param boolean $isPrefix Is Prefix?
95
+ * @param array $metadata Key/value pairs of meta data
96
+ */
97
+ public function __construct($containerName, $name, $snapshotId, $etag, $lastModified, $url = '', $size = 0, $contentType = '', $contentEncoding = '', $contentLanguage = '', $cacheControl = '', $blobType = '', $leaseStatus = '', $isPrefix = false, $metadata = array())
98
+ {
99
+ $this->_data = array(
100
+ 'container' => $containerName,
101
+ 'name' => $name,
102
+ 'snapshotid' => $snapshotId,
103
+ 'etag' => $etag,
104
+ 'lastmodified' => $lastModified,
105
+ 'url' => $url,
106
+ 'size' => $size,
107
+ 'contenttype' => $contentType,
108
+ 'contentencoding' => $contentEncoding,
109
+ 'contentlanguage' => $contentLanguage,
110
+ 'cachecontrol' => $cacheControl,
111
+ 'blobtype' => $blobType,
112
+ 'leasestatus' => $leaseStatus,
113
+ 'isprefix' => $isPrefix,
114
+ 'metadata' => $metadata
115
+ );
116
+ }
117
+
118
+ /**
119
+ * Magic overload for setting properties
120
+ *
121
+ * @param string $name Name of the property
122
+ * @param string $value Value to set
123
+ */
124
+ public function __set($name, $value) {
125
+ if (array_key_exists(strtolower($name), $this->_data)) {
126
+ $this->_data[strtolower($name)] = $value;
127
+ return;
128
+ }
129
+
130
+ throw new Exception("Unknown property: " . $name);
131
+ }
132
+
133
+ /**
134
+ * Magic overload for getting properties
135
+ *
136
+ * @param string $name Name of the property
137
+ */
138
+ public function __get($name) {
139
+ if (array_key_exists(strtolower($name), $this->_data)) {
140
+ return $this->_data[strtolower($name)];
141
+ }
142
+
143
+ throw new Exception("Unknown property: " . $name);
144
+ }
145
+ }
app/libs/Microsoft/WindowsAzure/Storage/DynamicTableEntity.php ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Storage
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: BlobInstance.php 14561 2009-05-07 08:05:12Z unknown $
34
+ */
35
+
36
+
37
+ /**
38
+ * @see Microsoft_WindowsAzure_Exception
39
+ */
40
+ require_once 'Microsoft/WindowsAzure/Exception.php';
41
+
42
+ /**
43
+ * @see Microsoft_WindowsAzure_Storage_TableEntity
44
+ */
45
+ require_once 'Microsoft/WindowsAzure/Storage/TableEntity.php';
46
+
47
+
48
+ /**
49
+ * @category Microsoft
50
+ * @package Microsoft_WindowsAzure
51
+ * @subpackage Storage
52
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
53
+ * @license http://phpazure.codeplex.com/license
54
+ */
55
+ class Microsoft_WindowsAzure_Storage_DynamicTableEntity extends Microsoft_WindowsAzure_Storage_TableEntity
56
+ {
57
+ /**
58
+ * Dynamic properties
59
+ *
60
+ * @var array
61
+ */
62
+ protected $_dynamicProperties = array();
63
+
64
+ /**
65
+ * Magic overload for setting properties
66
+ *
67
+ * @param string $name Name of the property
68
+ * @param string $value Value to set
69
+ */
70
+ public function __set($name, $value) {
71
+ $this->setAzureProperty($name, $value, null);
72
+ }
73
+
74
+ /**
75
+ * Magic overload for getting properties
76
+ *
77
+ * @param string $name Name of the property
78
+ */
79
+ public function __get($name) {
80
+ return $this->getAzureProperty($name);
81
+ }
82
+
83
+ /**
84
+ * Set an Azure property
85
+ *
86
+ * @param string $name Property name
87
+ * @param mixed $value Property value
88
+ * @param string $type Property type (Edm.xxxx)
89
+ * @return Microsoft_WindowsAzure_Storage_DynamicTableEntity
90
+ */
91
+ public function setAzureProperty($name, $value = '', $type = null)
92
+ {
93
+ if (strtolower($name) == 'partitionkey') {
94
+ $this->setPartitionKey($value);
95
+ } else if (strtolower($name) == 'rowkey') {
96
+ $this->setRowKey($value);
97
+ } else if (strtolower($name) == 'etag') {
98
+ $this->setEtag($value);
99
+ } else {
100
+ if (!array_key_exists(strtolower($name), $this->_dynamicProperties)) {
101
+ // Determine type?
102
+ if (is_null($type)) {
103
+ $type = 'Edm.String';
104
+ if (is_int($value)) {
105
+ $type = 'Edm.Int32';
106
+ } else if (is_float($value)) {
107
+ $type = 'Edm.Double';
108
+ } else if (is_bool($value)) {
109
+ $type = 'Edm.Boolean';
110
+ }
111
+ }
112
+
113
+ // Set dynamic property
114
+ $this->_dynamicProperties[strtolower($name)] = (object)array(
115
+ 'Name' => $name,
116
+ 'Type' => $type,
117
+ 'Value' => $value,
118
+ );
119
+ }
120
+
121
+ $this->_dynamicProperties[strtolower($name)]->Value = $value;
122
+ }
123
+ return $this;
124
+ }
125
+
126
+ /**
127
+ * Set an Azure property type
128
+ *
129
+ * @param string $name Property name
130
+ * @param string $type Property type (Edm.xxxx)
131
+ * @return Microsoft_WindowsAzure_Storage_DynamicTableEntity
132
+ */
133
+ public function setAzurePropertyType($name, $type = 'Edm.String')
134
+ {
135
+ if (!array_key_exists(strtolower($name), $this->_dynamicProperties)) {
136
+ $this->setAzureProperty($name, '', $type);
137
+ } else {
138
+ $this->_dynamicProperties[strtolower($name)]->Type = $type;
139
+ }
140
+ return $this;
141
+ }
142
+
143
+ /**
144
+ * Get an Azure property
145
+ *
146
+ * @param string $name Property name
147
+ * @param mixed $value Property value
148
+ * @param string $type Property type (Edm.xxxx)
149
+ * @return Microsoft_WindowsAzure_Storage_DynamicTableEntity
150
+ */
151
+ public function getAzureProperty($name)
152
+ {
153
+ if (strtolower($name) == 'partitionkey') {
154
+ return $this->getPartitionKey();
155
+ }
156
+ if (strtolower($name) == 'rowkey') {
157
+ return $this->getRowKey();
158
+ }
159
+ if (strtolower($name) == 'etag') {
160
+ return $this->getEtag();
161
+ }
162
+
163
+ if (!array_key_exists(strtolower($name), $this->_dynamicProperties)) {
164
+ $this->setAzureProperty($name);
165
+ }
166
+
167
+ return $this->_dynamicProperties[strtolower($name)]->Value;
168
+ }
169
+
170
+ /**
171
+ * Get an Azure property type
172
+ *
173
+ * @param string $name Property name
174
+ * @return string Property type (Edm.xxxx)
175
+ */
176
+ public function getAzurePropertyType($name)
177
+ {
178
+ if (!array_key_exists(strtolower($name), $this->_dynamicProperties)) {
179
+ $this->setAzureProperty($name, '', $type);
180
+ }
181
+
182
+ return $this->_dynamicProperties[strtolower($name)]->Type;
183
+ }
184
+
185
+ /**
186
+ * Get Azure values
187
+ *
188
+ * @return array
189
+ */
190
+ public function getAzureValues()
191
+ {
192
+ return array_merge(array_values($this->_dynamicProperties), parent::getAzureValues());
193
+ }
194
+
195
+ /**
196
+ * Set Azure values
197
+ *
198
+ * @param array $values
199
+ * @param boolean $throwOnError Throw Microsoft_WindowsAzure_Exception when a property is not specified in $values?
200
+ * @throws Microsoft_WindowsAzure_Exception
201
+ */
202
+ public function setAzureValues($values = array(), $throwOnError = false)
203
+ {
204
+ // Set parent values
205
+ parent::setAzureValues($values, false);
206
+
207
+ // Set current values
208
+ foreach ($values as $key => $value)
209
+ {
210
+ $this->$key = $value;
211
+ }
212
+ }
213
+ }
app/libs/Microsoft/WindowsAzure/Storage/LeaseInstance.php ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Storage
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: BlobInstance.php 45390 2010-04-19 08:28:21Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Exception.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Storage_StorageEntityAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Storage/StorageEntityAbstract.php';
45
+
46
+ /**
47
+ * @category Microsoft
48
+ * @package Microsoft_WindowsAzure
49
+ * @subpackage Storage
50
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
51
+ * @license http://phpazure.codeplex.com/license
52
+ *
53
+ * @property string $Container Container name
54
+ * @property string $Name Name
55
+ * @property string $LeaseId Lease id
56
+ * @property string $LeaseTime Time remaining in the lease period, in seconds. This header is returned only for a successful request to break the lease. It provides an approximation as to when the lease period will expire.
57
+ */
58
+ class Microsoft_WindowsAzure_Storage_LeaseInstance
59
+ extends Microsoft_WindowsAzure_Storage_StorageEntityAbstract
60
+ {
61
+ /**
62
+ * Constructor
63
+ *
64
+ * @param string $containerName Container name
65
+ * @param string $name Name
66
+ * @param string $leaseId Lease id
67
+ * @param string $leaseTime Time remaining in the lease period, in seconds. This header is returned only for a successful request to break the lease. It provides an approximation as to when the lease period will expire.
68
+ */
69
+ public function __construct($containerName, $name, $leaseId, $leaseTime)
70
+ {
71
+ $this->_data = array(
72
+ 'container' => $containerName,
73
+ 'name' => $name,
74
+ 'leaseid' => $leaseId,
75
+ 'leasetime' => $leaseTime
76
+ );
77
+ }
78
+ }
app/libs/Microsoft/WindowsAzure/Storage/PageRegionInstance.php ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Storage
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: BlobInstance.php 45390 2010-04-19 08:28:21Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Exception.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Storage_StorageEntityAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Storage/StorageEntityAbstract.php';
45
+
46
+ /**
47
+ * @category Microsoft
48
+ * @package Microsoft_WindowsAzure
49
+ * @subpackage Storage
50
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
51
+ * @license http://phpazure.codeplex.com/license
52
+ *
53
+ * @property int $start Page range start
54
+ * @property int $end Page range end
55
+ */
56
+ class Microsoft_WindowsAzure_Storage_PageRegionInstance
57
+ extends Microsoft_WindowsAzure_Storage_StorageEntityAbstract
58
+ {
59
+ /**
60
+ * Constructor
61
+ *
62
+ * @param int $start Page range start
63
+ * @param int $end Page range end
64
+ */
65
+ public function __construct($start = 0, $end = 0)
66
+ {
67
+ $this->_data = array(
68
+ 'start' => $start,
69
+ 'end' => $end
70
+ );
71
+ }
72
+ }
app/libs/Microsoft/WindowsAzure/Storage/Queue.php ADDED
@@ -0,0 +1,582 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Storage
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://todo name_todo
33
+ * @version $Id: Blob.php 24241 2009-07-22 09:43:13Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Credentials_SharedKey
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Credentials/SharedKey.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/RetryPolicy/RetryPolicyAbstract.php';
45
+
46
+ /**
47
+ * @see Microsoft_Http_Client
48
+ */
49
+ require_once 'Microsoft/Http/Client.php';
50
+
51
+ /**
52
+ * @see Microsoft_Http_Response
53
+ */
54
+ require_once 'Microsoft/Http/Response.php';
55
+
56
+ /**
57
+ * @see Microsoft_WindowsAzure_Storage
58
+ */
59
+ require_once 'Microsoft/WindowsAzure/Storage.php';
60
+
61
+ /**
62
+ * Microsoft_WindowsAzure_Storage_QueueInstance
63
+ */
64
+ require_once 'Microsoft/WindowsAzure/Storage/QueueInstance.php';
65
+
66
+ /**
67
+ * Microsoft_WindowsAzure_Storage_QueueMessage
68
+ */
69
+ require_once 'Microsoft/WindowsAzure/Storage/QueueMessage.php';
70
+
71
+ /**
72
+ * @see Microsoft_WindowsAzure_Exception
73
+ */
74
+ require_once 'Microsoft/WindowsAzure/Exception.php';
75
+
76
+
77
+ /**
78
+ * @category Microsoft
79
+ * @package Microsoft_WindowsAzure
80
+ * @subpackage Storage
81
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
82
+ * @license http://phpazure.codeplex.com/license
83
+ */
84
+ class Microsoft_WindowsAzure_Storage_Queue extends Microsoft_WindowsAzure_Storage
85
+ {
86
+ /**
87
+ * Maximal message size (in bytes)
88
+ */
89
+ const MAX_MESSAGE_SIZE = 8388608;
90
+
91
+ /**
92
+ * Maximal message ttl (in seconds)
93
+ */
94
+ const MAX_MESSAGE_TTL = 604800;
95
+
96
+ /**
97
+ * Creates a new Microsoft_WindowsAzure_Storage_Queue instance
98
+ *
99
+ * @param string $host Storage host name
100
+ * @param string $accountName Account name for Windows Azure
101
+ * @param string $accountKey Account key for Windows Azure
102
+ * @param boolean $usePathStyleUri Use path-style URI's
103
+ * @param Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy Retry policy to use when making requests
104
+ */
105
+ public function __construct($host = Microsoft_WindowsAzure_Storage::URL_DEV_QUEUE, $accountName = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_ACCOUNT, $accountKey = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_KEY, $usePathStyleUri = false, Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy = null)
106
+ {
107
+ parent::__construct($host, $accountName, $accountKey, $usePathStyleUri, $retryPolicy);
108
+
109
+ // API version
110
+ $this->_apiVersion = '2009-09-19';
111
+ }
112
+
113
+ /**
114
+ * Check if a queue exists
115
+ *
116
+ * @param string $queueName Queue name
117
+ * @return boolean
118
+ */
119
+ public function queueExists($queueName = '')
120
+ {
121
+ if ($queueName === '') {
122
+ throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
123
+ }
124
+ if (!self::isValidQueueName($queueName)) {
125
+ throw new Microsoft_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.');
126
+ }
127
+
128
+ // List queues
129
+ $queues = $this->listQueues($queueName, 1);
130
+ foreach ($queues as $queue) {
131
+ if ($queue->Name == $queueName) {
132
+ return true;
133
+ }
134
+ }
135
+
136
+ return false;
137
+ }
138
+
139
+ /**
140
+ * Create queue
141
+ *
142
+ * @param string $queueName Queue name
143
+ * @param array $metadata Key/value pairs of meta data
144
+ * @return object Queue properties
145
+ * @throws Microsoft_WindowsAzure_Exception
146
+ */
147
+ public function createQueue($queueName = '', $metadata = array())
148
+ {
149
+ if ($queueName === '') {
150
+ throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
151
+ }
152
+ if (!self::isValidQueueName($queueName)) {
153
+ throw new Microsoft_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.');
154
+ }
155
+
156
+ // Create metadata headers
157
+ $headers = array();
158
+ $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata));
159
+
160
+ // Perform request
161
+ $response = $this->_performRequest($queueName, '', Microsoft_Http_Client::PUT, $headers);
162
+ if ($response->isSuccessful()) {
163
+ return new Microsoft_WindowsAzure_Storage_QueueInstance(
164
+ $queueName,
165
+ $metadata
166
+ );
167
+ } else {
168
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
169
+ }
170
+ }
171
+
172
+ /**
173
+ * Create queue if it does not exist
174
+ *
175
+ * @param string $queueName Queue name
176
+ * @param array $metadata Key/value pairs of meta data
177
+ * @throws Microsoft_WindowsAzure_Exception
178
+ */
179
+ public function createQueueIfNotExists($queueName = '', $metadata = array())
180
+ {
181
+ if (!$this->queueExists($queueName)) {
182
+ $this->createQueue($queueName, $metadata);
183
+ }
184
+ }
185
+
186
+ /**
187
+ * Get queue
188
+ *
189
+ * @param string $queueName Queue name
190
+ * @return Microsoft_WindowsAzure_Storage_QueueInstance
191
+ * @throws Microsoft_WindowsAzure_Exception
192
+ */
193
+ public function getQueue($queueName = '')
194
+ {
195
+ if ($queueName === '') {
196
+ throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
197
+ }
198
+ if (!self::isValidQueueName($queueName)) {
199
+ throw new Microsoft_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.');
200
+ }
201
+
202
+ // Perform request
203
+ $response = $this->_performRequest($queueName, '?comp=metadata', Microsoft_Http_Client::GET);
204
+ if ($response->isSuccessful()) {
205
+ // Parse metadata
206
+ $metadata = $this->_parseMetadataHeaders($response->getHeaders());
207
+
208
+ // Return queue
209
+ $queue = new Microsoft_WindowsAzure_Storage_QueueInstance(
210
+ $queueName,
211
+ $metadata
212
+ );
213
+ $queue->ApproximateMessageCount = intval($response->getHeader('x-ms-approximate-message-count'));
214
+ return $queue;
215
+ } else {
216
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
217
+ }
218
+ }
219
+
220
+ /**
221
+ * Get queue metadata
222
+ *
223
+ * @param string $queueName Queue name
224
+ * @return array Key/value pairs of meta data
225
+ * @throws Microsoft_WindowsAzure_Exception
226
+ */
227
+ public function getQueueMetadata($queueName = '')
228
+ {
229
+ if ($queueName === '') {
230
+ throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
231
+ }
232
+ if (!self::isValidQueueName($queueName)) {
233
+ throw new Microsoft_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.');
234
+ }
235
+
236
+ return $this->getQueue($queueName)->Metadata;
237
+ }
238
+
239
+ /**
240
+ * Set queue metadata
241
+ *
242
+ * Calling the Set Queue Metadata operation overwrites all existing metadata that is associated with the queue. It's not possible to modify an individual name/value pair.
243
+ *
244
+ * @param string $queueName Queue name
245
+ * @param array $metadata Key/value pairs of meta data
246
+ * @throws Microsoft_WindowsAzure_Exception
247
+ */
248
+ public function setQueueMetadata($queueName = '', $metadata = array())
249
+ {
250
+ if ($queueName === '') {
251
+ throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
252
+ }
253
+ if (!self::isValidQueueName($queueName)) {
254
+ throw new Microsoft_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.');
255
+ }
256
+ if (count($metadata) == 0) {
257
+ return;
258
+ }
259
+
260
+ // Create metadata headers
261
+ $headers = array();
262
+ $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata));
263
+
264
+ // Perform request
265
+ $response = $this->_performRequest($queueName, '?comp=metadata', Microsoft_Http_Client::PUT, $headers);
266
+
267
+ if (!$response->isSuccessful()) {
268
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
269
+ }
270
+ }
271
+
272
+ /**
273
+ * Delete queue
274
+ *
275
+ * @param string $queueName Queue name
276
+ * @throws Microsoft_WindowsAzure_Exception
277
+ */
278
+ public function deleteQueue($queueName = '')
279
+ {
280
+ if ($queueName === '') {
281
+ throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
282
+ }
283
+ if (!self::isValidQueueName($queueName)) {
284
+ throw new Microsoft_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.');
285
+ }
286
+
287
+ // Perform request
288
+ $response = $this->_performRequest($queueName, '', Microsoft_Http_Client::DELETE);
289
+ if (!$response->isSuccessful()) {
290
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
291
+ }
292
+ }
293
+
294
+ /**
295
+ * List queues
296
+ *
297
+ * @param string $prefix Optional. Filters the results to return only queues whose name begins with the specified prefix.
298
+ * @param int $maxResults Optional. Specifies the maximum number of queues to return per call to Azure storage. This does NOT affect list size returned by this function. (maximum: 5000)
299
+ * @param string $marker Optional string value that identifies the portion of the list to be returned with the next list operation.
300
+ * @param string $include Optional. Include this parameter to specify that the queue's metadata be returned as part of the response body. (allowed values: '', 'metadata')
301
+ * @param int $currentResultCount Current result count (internal use)
302
+ * @return array
303
+ * @throws Microsoft_WindowsAzure_Exception
304
+ */
305
+ public function listQueues($prefix = null, $maxResults = null, $marker = null, $include = null, $currentResultCount = 0)
306
+ {
307
+ // Build query string
308
+ $queryString = array('comp=list');
309
+ if (!is_null($prefix)) {
310
+ $queryString[] = 'prefix=' . $prefix;
311
+ }
312
+ if (!is_null($maxResults)) {
313
+ $queryString[] = 'maxresults=' . $maxResults;
314
+ }
315
+ if (!is_null($marker)) {
316
+ $queryString[] = 'marker=' . $marker;
317
+ }
318
+ if (!is_null($include)) {
319
+ $queryString[] = 'include=' . $include;
320
+ }
321
+ $queryString = self::createQueryStringFromArray($queryString);
322
+
323
+ // Perform request
324
+ $response = $this->_performRequest('', $queryString, Microsoft_Http_Client::GET);
325
+ if ($response->isSuccessful()) {
326
+ $xmlQueues = $this->_parseResponse($response)->Queues->Queue;
327
+ $xmlMarker = (string)$this->_parseResponse($response)->NextMarker;
328
+
329
+ $queues = array();
330
+ if (!is_null($xmlQueues)) {
331
+ for ($i = 0; $i < count($xmlQueues); $i++) {
332
+ $queues[] = new Microsoft_WindowsAzure_Storage_QueueInstance(
333
+ (string)$xmlQueues[$i]->Name,
334
+ $this->_parseMetadataElement($xmlQueues[$i])
335
+ );
336
+ }
337
+ }
338
+ $currentResultCount = $currentResultCount + count($queues);
339
+ if (!is_null($maxResults) && $currentResultCount < $maxResults) {
340
+ if (!is_null($xmlMarker) && $xmlMarker != '') {
341
+ $queues = array_merge($queues, $this->listQueues($prefix, $maxResults, $xmlMarker, $include, $currentResultCount));
342
+ }
343
+ }
344
+ if (!is_null($maxResults) && count($queues) > $maxResults) {
345
+ $queues = array_slice($queues, 0, $maxResults);
346
+ }
347
+
348
+ return $queues;
349
+ } else {
350
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
351
+ }
352
+ }
353
+
354
+ /**
355
+ * Put message into queue
356
+ *
357
+ * @param string $queueName Queue name
358
+ * @param string $message Message
359
+ * @param int $ttl Message Time-To-Live (in seconds). Defaults to 7 days if the parameter is omitted.
360
+ * @throws Microsoft_WindowsAzure_Exception
361
+ */
362
+ public function putMessage($queueName = '', $message = '', $ttl = null)
363
+ {
364
+ if ($queueName === '') {
365
+ throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
366
+ }
367
+ if (!self::isValidQueueName($queueName)) {
368
+ throw new Microsoft_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.');
369
+ }
370
+ if (strlen($message) > self::MAX_MESSAGE_SIZE) {
371
+ throw new Microsoft_WindowsAzure_Exception('Message is too big. Message content should be < 8KB.');
372
+ }
373
+ if ($message == '') {
374
+ throw new Microsoft_WindowsAzure_Exception('Message is not specified.');
375
+ }
376
+ if (!is_null($ttl) && ($ttl <= 0 || $ttl > self::MAX_MESSAGE_SIZE)) {
377
+ throw new Microsoft_WindowsAzure_Exception('Message TTL is invalid. Maximal TTL is 7 days (' . self::MAX_MESSAGE_SIZE . ' seconds) and should be greater than zero.');
378
+ }
379
+
380
+ // Build query string
381
+ $queryString = array();
382
+ if (!is_null($ttl)) {
383
+ $queryString[] = 'messagettl=' . $ttl;
384
+ }
385
+ $queryString = self::createQueryStringFromArray($queryString);
386
+
387
+ // Build body
388
+ $rawData = '';
389
+ $rawData .= '<QueueMessage>';
390
+ $rawData .= ' <MessageText>' . base64_encode($message) . '</MessageText>';
391
+ $rawData .= '</QueueMessage>';
392
+
393
+ // Perform request
394
+ $response = $this->_performRequest($queueName . '/messages', $queryString, Microsoft_Http_Client::POST, array(), false, $rawData);
395
+
396
+ if (!$response->isSuccessful()) {
397
+ throw new Microsoft_WindowsAzure_Exception('Error putting message into queue.');
398
+ }
399
+ }
400
+
401
+ /**
402
+ * Get queue messages
403
+ *
404
+ * @param string $queueName Queue name
405
+ * @param string $numOfMessages Optional. A nonzero integer value that specifies the number of messages to retrieve from the queue, up to a maximum of 32. By default, a single message is retrieved from the queue with this operation.
406
+ * @param int $visibilityTimeout Optional. An integer value that specifies the message's visibility timeout in seconds. The maximum value is 2 hours. The default message visibility timeout is 30 seconds.
407
+ * @param string $peek Peek only?
408
+ * @return array
409
+ * @throws Microsoft_WindowsAzure_Exception
410
+ */
411
+ public function getMessages($queueName = '', $numOfMessages = 1, $visibilityTimeout = null, $peek = false)
412
+ {
413
+ if ($queueName === '') {
414
+ throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
415
+ }
416
+ if (!self::isValidQueueName($queueName)) {
417
+ throw new Microsoft_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.');
418
+ }
419
+ if ($numOfMessages < 1 || $numOfMessages > 32 || intval($numOfMessages) != $numOfMessages) {
420
+ throw new Microsoft_WindowsAzure_Exception('Invalid number of messages to retrieve.');
421
+ }
422
+ if (!is_null($visibilityTimeout) && ($visibilityTimeout <= 0 || $visibilityTimeout > 7200)) {
423
+ throw new Microsoft_WindowsAzure_Exception('Visibility timeout is invalid. Maximum value is 2 hours (7200 seconds) and should be greater than zero.');
424
+ }
425
+
426
+ // Build query string
427
+ $queryString = array();
428
+ if ($peek) {
429
+ $queryString[] = 'peekonly=true';
430
+ }
431
+ if ($numOfMessages > 1) {
432
+ $queryString[] = 'numofmessages=' . $numOfMessages;
433
+ }
434
+ if (!$peek && !is_null($visibilityTimeout)) {
435
+ $queryString[] = 'visibilitytimeout=' . $visibilityTimeout;
436
+ }
437
+ $queryString = self::createQueryStringFromArray($queryString);
438
+
439
+ // Perform request
440
+ $response = $this->_performRequest($queueName . '/messages', $queryString, Microsoft_Http_Client::GET);
441
+ if ($response->isSuccessful()) {
442
+ // Parse results
443
+ $result = $this->_parseResponse($response);
444
+ if (!$result) {
445
+ return array();
446
+ }
447
+
448
+ $xmlMessages = null;
449
+ if (count($result->QueueMessage) > 1) {
450
+ $xmlMessages = $result->QueueMessage;
451
+ } else {
452
+ $xmlMessages = array($result->QueueMessage);
453
+ }
454
+
455
+ $messages = array();
456
+ for ($i = 0; $i < count($xmlMessages); $i++) {
457
+ $messages[] = new Microsoft_WindowsAzure_Storage_QueueMessage(
458
+ (string)$xmlMessages[$i]->MessageId,
459
+ (string)$xmlMessages[$i]->InsertionTime,
460
+ (string)$xmlMessages[$i]->ExpirationTime,
461
+ ($peek ? '' : (string)$xmlMessages[$i]->PopReceipt),
462
+ ($peek ? '' : (string)$xmlMessages[$i]->TimeNextVisible),
463
+ (string)$xmlMessages[$i]->DequeueCount,
464
+ base64_decode((string)$xmlMessages[$i]->MessageText)
465
+ );
466
+ }
467
+
468
+ return $messages;
469
+ } else {
470
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
471
+ }
472
+ }
473
+
474
+ /**
475
+ * Peek queue messages
476
+ *
477
+ * @param string $queueName Queue name
478
+ * @param string $numOfMessages Optional. A nonzero integer value that specifies the number of messages to retrieve from the queue, up to a maximum of 32. By default, a single message is retrieved from the queue with this operation.
479
+ * @return array
480
+ * @throws Microsoft_WindowsAzure_Exception
481
+ */
482
+ public function peekMessages($queueName = '', $numOfMessages = 1)
483
+ {
484
+ return $this->getMessages($queueName, $numOfMessages, null, true);
485
+ }
486
+
487
+ /**
488
+ * Clear queue messages
489
+ *
490
+ * @param string $queueName Queue name
491
+ * @throws Microsoft_WindowsAzure_Exception
492
+ */
493
+ public function clearMessages($queueName = '')
494
+ {
495
+ if ($queueName === '') {
496
+ throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
497
+ }
498
+ if (!self::isValidQueueName($queueName)) {
499
+ throw new Microsoft_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.');
500
+ }
501
+
502
+ // Perform request
503
+ $response = $this->_performRequest($queueName . '/messages', '', Microsoft_Http_Client::DELETE);
504
+ if (!$response->isSuccessful()) {
505
+ throw new Microsoft_WindowsAzure_Exception('Error clearing messages from queue.');
506
+ }
507
+ }
508
+
509
+ /**
510
+ * Delete queue message
511
+ *
512
+ * @param string $queueName Queue name
513
+ * @param Microsoft_WindowsAzure_Storage_QueueMessage $message Message to delete from queue. A message retrieved using "peekMessages" can NOT be deleted!
514
+ * @throws Microsoft_WindowsAzure_Exception
515
+ */
516
+ public function deleteMessage($queueName = '', Microsoft_WindowsAzure_Storage_QueueMessage $message)
517
+ {
518
+ if ($queueName === '') {
519
+ throw new Microsoft_WindowsAzure_Exception('Queue name is not specified.');
520
+ }
521
+ if (!self::isValidQueueName($queueName)) {
522
+ throw new Microsoft_WindowsAzure_Exception('Queue name does not adhere to queue naming conventions. See http://msdn.microsoft.com/en-us/library/dd179349.aspx for more information.');
523
+ }
524
+ if ($message->PopReceipt == '') {
525
+ throw new Microsoft_WindowsAzure_Exception('A message retrieved using "peekMessages" can NOT be deleted! Use "getMessages" instead.');
526
+ }
527
+
528
+ // Perform request
529
+ $response = $this->_performRequest($queueName . '/messages/' . $message->MessageId, '?popreceipt=' . $message->PopReceipt, Microsoft_Http_Client::DELETE);
530
+ if (!$response->isSuccessful()) {
531
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
532
+ }
533
+ }
534
+
535
+ /**
536
+ * Is valid queue name?
537
+ *
538
+ * @param string $queueName Queue name
539
+ * @return boolean
540
+ */
541
+ public static function isValidQueueName($queueName = '')
542
+ {
543
+ if (preg_match("/^[a-z0-9][a-z0-9-]*$/", $queueName) === 0) {
544
+ return false;
545
+ }
546
+
547
+ if (strpos($queueName, '--') !== false) {
548
+ return false;
549
+ }
550
+
551
+ if (strtolower($queueName) != $queueName) {
552
+ return false;
553
+ }
554
+
555
+ if (strlen($queueName) < 3 || strlen($queueName) > 63) {
556
+ return false;
557
+ }
558
+
559
+ if (substr($queueName, -1) == '-') {
560
+ return false;
561
+ }
562
+
563
+ return true;
564
+ }
565
+
566
+ /**
567
+ * Get error message from Microsoft_Http_Response
568
+ *
569
+ * @param Microsoft_Http_Response $response Repsonse
570
+ * @param string $alternativeError Alternative error message
571
+ * @return string
572
+ */
573
+ protected function _getErrorMessage(Microsoft_Http_Response $response, $alternativeError = 'Unknown error.')
574
+ {
575
+ $response = $this->_parseResponse($response);
576
+ if ($response && $response->Message) {
577
+ return (string)$response->Message;
578
+ } else {
579
+ return $alternativeError;
580
+ }
581
+ }
582
+ }
app/libs/Microsoft/WindowsAzure/Storage/QueueInstance.php ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Storage
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: BlobContainer.php 17553 2009-05-15 10:40:55Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Exception.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Storage_StorageEntityAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Storage/StorageEntityAbstract.php';
45
+
46
+ /**
47
+ * @category Microsoft
48
+ * @package Microsoft_WindowsAzure
49
+ * @subpackage Storage
50
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
51
+ * @license http://phpazure.codeplex.com/license
52
+ *
53
+ * @property string $Name Name of the queue
54
+ * @property array $Metadata Key/value pairs of meta data
55
+ * @property integer $ApproximateMessageCount The approximate number of messages in the queue
56
+ */
57
+ class Microsoft_WindowsAzure_Storage_QueueInstance
58
+ extends Microsoft_WindowsAzure_Storage_StorageEntityAbstract
59
+ {
60
+ /**
61
+ * Constructor
62
+ *
63
+ * @param string $name Name
64
+ * @param array $metadata Key/value pairs of meta data
65
+ */
66
+ public function __construct($name, $metadata = array())
67
+ {
68
+ $this->_data = array(
69
+ 'name' => $name,
70
+ 'metadata' => $metadata,
71
+ 'approximatemessagecount' => 0
72
+ );
73
+ }
74
+ }
app/libs/Microsoft/WindowsAzure/Storage/QueueMessage.php ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Storage
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: BlobContainer.php 17553 2009-05-15 10:40:55Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Exception.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Storage_StorageEntityAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Storage/StorageEntityAbstract.php';
45
+
46
+ /**
47
+ * @category Microsoft
48
+ * @package Microsoft_WindowsAzure
49
+ * @subpackage Storage
50
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
51
+ * @license http://phpazure.codeplex.com/license
52
+ *
53
+ * @property string $MessageId Message ID
54
+ * @property string $InsertionTime Insertion time
55
+ * @property string $ExpirationTime Expiration time
56
+ * @property string $PopReceipt Receipt verification for deleting the message from queue.
57
+ * @property string $TimeNextVisible Next time the message is visible in the queue
58
+ * @property int $DequeueCount Number of times the message has been dequeued. This value is incremented each time the message is subsequently dequeued.
59
+ * @property string $MessageText Message text
60
+ */
61
+ class Microsoft_WindowsAzure_Storage_QueueMessage
62
+ extends Microsoft_WindowsAzure_Storage_StorageEntityAbstract
63
+ {
64
+ /**
65
+ * Constructor
66
+ *
67
+ * @param string $messageId Message ID
68
+ * @param string $insertionTime Insertion time
69
+ * @param string $expirationTime Expiration time
70
+ * @param string $popReceipt Receipt verification for deleting the message from queue.
71
+ * @param string $timeNextVisible Next time the message is visible in the queue
72
+ * @param int $dequeueCount Number of times the message has been dequeued. This value is incremented each time the message is subsequently dequeued.
73
+ * @param string $messageText Message text
74
+ */
75
+ public function __construct($messageId, $insertionTime, $expirationTime, $popReceipt, $timeNextVisible, $dequeueCount, $messageText)
76
+ {
77
+ $this->_data = array(
78
+ 'messageid' => $messageId,
79
+ 'insertiontime' => $insertionTime,
80
+ 'expirationtime' => $expirationTime,
81
+ 'popreceipt' => $popReceipt,
82
+ 'timenextvisible' => $timeNextVisible,
83
+ 'dequeuecount' => $dequeueCount,
84
+ 'messagetext' => $messageText
85
+ );
86
+ }
87
+ }
app/libs/Microsoft/WindowsAzure/Storage/SignedIdentifier.php ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Storage
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: BlobContainer.php 24352 2009-07-24 06:44:32Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Exception.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Storage_StorageEntityAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Storage/StorageEntityAbstract.php';
45
+
46
+ /**
47
+ * @category Microsoft
48
+ * @package Microsoft_WindowsAzure
49
+ * @subpackage Storage
50
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
51
+ * @license http://phpazure.codeplex.com/license
52
+ *
53
+ * @property string $Id Id for the signed identifier
54
+ * @property string $Start The time at which the Shared Access Signature becomes valid.
55
+ * @property string $Expiry The time at which the Shared Access Signature becomes invalid.
56
+ * @property string $Permissions Signed permissions - read (r), write (w), delete (d) and list (l)
57
+ */
58
+ class Microsoft_WindowsAzure_Storage_SignedIdentifier
59
+ extends Microsoft_WindowsAzure_Storage_StorageEntityAbstract
60
+ {
61
+ /**
62
+ * Constructor
63
+ *
64
+ * @param string $id Id for the signed identifier
65
+ * @param string $start The time at which the Shared Access Signature becomes valid.
66
+ * @param string $expiry The time at which the Shared Access Signature becomes invalid.
67
+ * @param string $permissions Signed permissions - read (r), write (w), delete (d) and list (l)
68
+ */
69
+ public function __construct($id = '', $start = '', $expiry = '', $permissions = '')
70
+ {
71
+ $this->_data = array(
72
+ 'id' => $id,
73
+ 'start' => $start,
74
+ 'expiry' => $expiry,
75
+ 'permissions' => $permissions
76
+ );
77
+ }
78
+ }
app/libs/Microsoft/WindowsAzure/Storage/StorageEntityAbstract.php ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Storage
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: BlobInstance.php 45390 2010-04-19 08:28:21Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Exception.php';
40
+
41
+
42
+ /**
43
+ * @category Microsoft
44
+ * @package Microsoft_WindowsAzure
45
+ * @subpackage Storage
46
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
47
+ * @license http://phpazure.codeplex.com/license
48
+ *
49
+ */
50
+ abstract class Microsoft_WindowsAzure_Storage_StorageEntityAbstract
51
+ {
52
+ /**
53
+ * Data
54
+ *
55
+ * @var array
56
+ */
57
+ protected $_data = null;
58
+
59
+ /**
60
+ * Magic overload for setting properties
61
+ *
62
+ * @param string $name Name of the property
63
+ * @param string $value Value to set
64
+ */
65
+ public function __set($name, $value) {
66
+ if (array_key_exists(strtolower($name), $this->_data)) {
67
+ $this->_data[strtolower($name)] = $value;
68
+ return;
69
+ }
70
+
71
+ throw new Exception("Unknown property: " . $name);
72
+ }
73
+
74
+ /**
75
+ * Magic overload for getting properties
76
+ *
77
+ * @param string $name Name of the property
78
+ */
79
+ public function __get($name) {
80
+ if (array_key_exists(strtolower($name), $this->_data)) {
81
+ return $this->_data[strtolower($name)];
82
+ }
83
+
84
+ throw new Exception("Unknown property: " . $name);
85
+ }
86
+ }
app/libs/Microsoft/WindowsAzure/Storage/Table.php ADDED
@@ -0,0 +1,919 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Storage
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Blob.php 14561 2009-05-07 08:05:12Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Credentials_CredentialsAbstract
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Credentials/CredentialsAbstract.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Credentials_SharedKey
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Credentials/SharedKey.php';
45
+
46
+ /**
47
+ * @see Microsoft_WindowsAzure_Credentials_SharedKeyLite
48
+ */
49
+ require_once 'Microsoft/WindowsAzure/Credentials/SharedKeyLite.php';
50
+
51
+ /**
52
+ * @see Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract
53
+ */
54
+ require_once 'Microsoft/WindowsAzure/RetryPolicy/RetryPolicyAbstract.php';
55
+
56
+ /**
57
+ * @see Microsoft_Http_Client
58
+ */
59
+ require_once 'Microsoft/Http/Client.php';
60
+
61
+ /**
62
+ * @see Microsoft_Http_Response
63
+ */
64
+ require_once 'Microsoft/Http/Response.php';
65
+
66
+ /**
67
+ * @see Microsoft_WindowsAzure_Storage
68
+ */
69
+ require_once 'Microsoft/WindowsAzure/Storage.php';
70
+
71
+ /**
72
+ * @see Microsoft_WindowsAzure_Storage_BatchStorageAbstract
73
+ */
74
+ require_once 'Microsoft/WindowsAzure/Storage/BatchStorageAbstract.php';
75
+
76
+ /**
77
+ * @see Microsoft_WindowsAzure_Storage_TableInstance
78
+ */
79
+ require_once 'Microsoft/WindowsAzure/Storage/TableInstance.php';
80
+
81
+ /**
82
+ * @see Microsoft_WindowsAzure_Storage_TableEntity
83
+ */
84
+ require_once 'Microsoft/WindowsAzure/Storage/TableEntity.php';
85
+
86
+ /**
87
+ * @see Microsoft_WindowsAzure_Storage_DynamicTableEntity
88
+ */
89
+ require_once 'Microsoft/WindowsAzure/Storage/DynamicTableEntity.php';
90
+
91
+ /**
92
+ * @see Microsoft_WindowsAzure_Storage_TableEntityQuery
93
+ */
94
+ require_once 'Microsoft/WindowsAzure/Storage/TableEntityQuery.php';
95
+
96
+ /**
97
+ * @see Microsoft_WindowsAzure_Exception
98
+ */
99
+ require_once 'Microsoft/WindowsAzure/Exception.php';
100
+
101
+
102
+ /**
103
+ * @category Microsoft
104
+ * @package Microsoft_WindowsAzure
105
+ * @subpackage Storage
106
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
107
+ * @license http://phpazure.codeplex.com/license
108
+ */
109
+ class Microsoft_WindowsAzure_Storage_Table
110
+ extends Microsoft_WindowsAzure_Storage_BatchStorageAbstract
111
+ {
112
+ /**
113
+ * Throw Microsoft_WindowsAzure_Exception when a property is not specified in Windows Azure?
114
+ * Defaults to true, making behaviour similar to Windows Azure StorageClient in .NET.
115
+ *
116
+ * @var boolean
117
+ */
118
+ protected $_throwExceptionOnMissingData = true;
119
+
120
+ /**
121
+ * Throw Microsoft_WindowsAzure_Exception when a property is not specified in Windows Azure?
122
+ * Defaults to true, making behaviour similar to Windows Azure StorageClient in .NET.
123
+ *
124
+ * @param boolean $value
125
+ */
126
+ public function setThrowExceptionOnMissingData($value = true)
127
+ {
128
+ $this->_throwExceptionOnMissingData = $value;
129
+ }
130
+
131
+ /**
132
+ * Throw Microsoft_WindowsAzure_Exception when a property is not specified in Windows Azure?
133
+ */
134
+ public function getThrowExceptionOnMissingData()
135
+ {
136
+ return $this->_throwExceptionOnMissingData;
137
+ }
138
+
139
+ /**
140
+ * Creates a new Microsoft_WindowsAzure_Storage_Table instance
141
+ *
142
+ * @param string $host Storage host name
143
+ * @param string $accountName Account name for Windows Azure
144
+ * @param string $accountKey Account key for Windows Azure
145
+ * @param boolean $usePathStyleUri Use path-style URI's
146
+ * @param Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy Retry policy to use when making requests
147
+ */
148
+ public function __construct($host = Microsoft_WindowsAzure_Storage::URL_DEV_TABLE, $accountName = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_ACCOUNT, $accountKey = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_KEY, $usePathStyleUri = false, Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy = null)
149
+ {
150
+ parent::__construct($host, $accountName, $accountKey, $usePathStyleUri, $retryPolicy);
151
+
152
+ // Always use SharedKeyLite authentication
153
+ $this->_credentials = new Microsoft_WindowsAzure_Credentials_SharedKeyLite($accountName, $accountKey, $this->_usePathStyleUri);
154
+
155
+ // API version
156
+ $this->_apiVersion = '2009-09-19';
157
+ }
158
+
159
+ /**
160
+ * Check if a table exists
161
+ *
162
+ * @param string $tableName Table name
163
+ * @return boolean
164
+ */
165
+ public function tableExists($tableName = '')
166
+ {
167
+ if ($tableName === '') {
168
+ throw new Microsoft_WindowsAzure_Exception('Table name is not specified.');
169
+ }
170
+
171
+ // List tables
172
+ $tables = $this->listTables(); // 2009-09-19 does not support $this->listTables($tableName); all of a sudden...
173
+ foreach ($tables as $table) {
174
+ if ($table->Name == $tableName) {
175
+ return true;
176
+ }
177
+ }
178
+
179
+ return false;
180
+ }
181
+
182
+ /**
183
+ * List tables
184
+ *
185
+ * @param string $nextTableName Next table name, used for listing tables when total amount of tables is > 1000.
186
+ * @return array
187
+ * @throws Microsoft_WindowsAzure_Exception
188
+ */
189
+ public function listTables($nextTableName = '')
190
+ {
191
+ // Build query string
192
+ $queryString = array();
193
+ if ($nextTableName != '') {
194
+ $queryString[] = 'NextTableName=' . $nextTableName;
195
+ }
196
+ $queryString = self::createQueryStringFromArray($queryString);
197
+
198
+ // Perform request
199
+ $response = $this->_performRequest('Tables', $queryString, Microsoft_Http_Client::GET, null, true);
200
+ if ($response->isSuccessful()) {
201
+ // Parse result
202
+ $result = $this->_parseResponse($response);
203
+
204
+ if (!$result || !$result->entry) {
205
+ return array();
206
+ }
207
+
208
+ $entries = null;
209
+ if (count($result->entry) > 1) {
210
+ $entries = $result->entry;
211
+ } else {
212
+ $entries = array($result->entry);
213
+ }
214
+
215
+ // Create return value
216
+ $returnValue = array();
217
+ foreach ($entries as $entry) {
218
+ $tableName = $entry->xpath('.//m:properties/d:TableName');
219
+ $tableName = (string)$tableName[0];
220
+
221
+ $returnValue[] = new Microsoft_WindowsAzure_Storage_TableInstance(
222
+ (string)$entry->id,
223
+ $tableName,
224
+ (string)$entry->link['href'],
225
+ (string)$entry->updated
226
+ );
227
+ }
228
+
229
+ // More tables?
230
+ if (!is_null($response->getHeader('x-ms-continuation-NextTableName'))) {
231
+ $returnValue = array_merge($returnValue, $this->listTables($response->getHeader('x-ms-continuation-NextTableName')));
232
+ }
233
+
234
+ return $returnValue;
235
+ } else {
236
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
237
+ }
238
+ }
239
+
240
+ /**
241
+ * Create table
242
+ *
243
+ * @param string $tableName Table name
244
+ * @return Microsoft_WindowsAzure_Storage_TableInstance
245
+ * @throws Microsoft_WindowsAzure_Exception
246
+ */
247
+ public function createTable($tableName = '')
248
+ {
249
+ if ($tableName === '') {
250
+ throw new Microsoft_WindowsAzure_Exception('Table name is not specified.');
251
+ }
252
+
253
+ // Generate request body
254
+ $requestBody = '<?xml version="1.0" encoding="utf-8" standalone="yes"?>
255
+ <entry
256
+ xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
257
+ xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
258
+ xmlns="http://www.w3.org/2005/Atom">
259
+ <title />
260
+ <updated>{tpl:Updated}</updated>
261
+ <author>
262
+ <name />
263
+ </author>
264
+ <id />
265
+ <content type="application/xml">
266
+ <m:properties>
267
+ <d:TableName>{tpl:TableName}</d:TableName>
268
+ </m:properties>
269
+ </content>
270
+ </entry>';
271
+
272
+ $requestBody = $this->_fillTemplate($requestBody, array(
273
+ 'BaseUrl' => $this->getBaseUrl(),
274
+ 'TableName' => htmlspecialchars($tableName),
275
+ 'Updated' => $this->isoDate(),
276
+ 'AccountName' => $this->_accountName
277
+ ));
278
+
279
+ // Add header information
280
+ $headers = array();
281
+ $headers['Content-Type'] = 'application/atom+xml';
282
+ $headers['DataServiceVersion'] = '1.0;NetFx';
283
+ $headers['MaxDataServiceVersion'] = '1.0;NetFx';
284
+
285
+ // Perform request
286
+ $response = $this->_performRequest('Tables', '', Microsoft_Http_Client::POST, $headers, true, $requestBody);
287
+ if ($response->isSuccessful()) {
288
+ // Parse response
289
+ $entry = $this->_parseResponse($response);
290
+
291
+ $tableName = $entry->xpath('.//m:properties/d:TableName');
292
+ $tableName = (string)$tableName[0];
293
+
294
+ return new Microsoft_WindowsAzure_Storage_TableInstance(
295
+ (string)$entry->id,
296
+ $tableName,
297
+ (string)$entry->link['href'],
298
+ (string)$entry->updated
299
+ );
300
+ } else {
301
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
302
+ }
303
+ }
304
+
305
+ /**
306
+ * Create table if it does not exist
307
+ *
308
+ * @param string $tableName Table name
309
+ * @throws Microsoft_WindowsAzure_Exception
310
+ */
311
+ public function createTableIfNotExists($tableName = '')
312
+ {
313
+ if (!$this->tableExists($tableName)) {
314
+ $this->createTable($tableName);
315
+ }
316
+ }
317
+
318
+ /**
319
+ * Delete table
320
+ *
321
+ * @param string $tableName Table name
322
+ * @throws Microsoft_WindowsAzure_Exception
323
+ */
324
+ public function deleteTable($tableName = '')
325
+ {
326
+ if ($tableName === '') {
327
+ throw new Microsoft_WindowsAzure_Exception('Table name is not specified.');
328
+ }
329
+
330
+ // Add header information
331
+ $headers = array();
332
+ $headers['Content-Type'] = 'application/atom+xml';
333
+
334
+ // Perform request
335
+ $response = $this->_performRequest('Tables(\'' . $tableName . '\')', '', Microsoft_Http_Client::DELETE, $headers, true, null);
336
+ if (!$response->isSuccessful()) {
337
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
338
+ }
339
+ }
340
+
341
+ /**
342
+ * Insert entity into table
343
+ *
344
+ * @param string $tableName Table name
345
+ * @param Microsoft_WindowsAzure_Storage_TableEntity $entity Entity to insert
346
+ * @return Microsoft_WindowsAzure_Storage_TableEntity
347
+ * @throws Microsoft_WindowsAzure_Exception
348
+ */
349
+ public function insertEntity($tableName = '', Microsoft_WindowsAzure_Storage_TableEntity $entity = null)
350
+ {
351
+ if ($tableName === '') {
352
+ throw new Microsoft_WindowsAzure_Exception('Table name is not specified.');
353
+ }
354
+ if (is_null($entity)) {
355
+ throw new Microsoft_WindowsAzure_Exception('Entity is not specified.');
356
+ }
357
+
358
+ // Generate request body
359
+ $requestBody = '<?xml version="1.0" encoding="utf-8" standalone="yes"?>
360
+ <entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
361
+ <title />
362
+ <updated>{tpl:Updated}</updated>
363
+ <author>
364
+ <name />
365
+ </author>
366
+ <id />
367
+ <content type="application/xml">
368
+ <m:properties>
369
+ {tpl:Properties}
370
+ </m:properties>
371
+ </content>
372
+ </entry>';
373
+
374
+ $requestBody = $this->_fillTemplate($requestBody, array(
375
+ 'Updated' => $this->isoDate(),
376
+ 'Properties' => $this->_generateAzureRepresentation($entity)
377
+ ));
378
+
379
+ // Add header information
380
+ $headers = array();
381
+ $headers['Content-Type'] = 'application/atom+xml';
382
+
383
+ // Perform request
384
+ $response = null;
385
+ if ($this->isInBatch()) {
386
+ $this->getCurrentBatch()->enlistOperation($tableName, '', Microsoft_Http_Client::POST, $headers, true, $requestBody);
387
+ return null;
388
+ } else {
389
+ $response = $this->_performRequest($tableName, '', Microsoft_Http_Client::POST, $headers, true, $requestBody);
390
+ }
391
+ if ($response->isSuccessful()) {
392
+ // Parse result
393
+ $result = $this->_parseResponse($response);
394
+
395
+ $timestamp = $result->xpath('//m:properties/d:Timestamp');
396
+ $timestamp = (string)$timestamp[0];
397
+
398
+ $etag = $result->attributes('http://schemas.microsoft.com/ado/2007/08/dataservices/metadata');
399
+ $etag = (string)$etag['etag'];
400
+
401
+ // Update properties
402
+ $entity->setTimestamp($timestamp);
403
+ $entity->setEtag($etag);
404
+
405
+ return $entity;
406
+ } else {
407
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
408
+ }
409
+ }
410
+
411
+ /**
412
+ * Delete entity from table
413
+ *
414
+ * @param string $tableName Table name
415
+ * @param Microsoft_WindowsAzure_Storage_TableEntity $entity Entity to delete
416
+ * @param boolean $verifyEtag Verify etag of the entity (used for concurrency)
417
+ * @throws Microsoft_WindowsAzure_Exception
418
+ */
419
+ public function deleteEntity($tableName = '', Microsoft_WindowsAzure_Storage_TableEntity $entity = null, $verifyEtag = false)
420
+ {
421
+ if ($tableName === '') {
422
+ throw new Microsoft_WindowsAzure_Exception('Table name is not specified.');
423
+ }
424
+ if (is_null($entity)) {
425
+ throw new Microsoft_WindowsAzure_Exception('Entity is not specified.');
426
+ }
427
+
428
+ // Add header information
429
+ $headers = array();
430
+ if (!$this->isInBatch()) {
431
+ // http://social.msdn.microsoft.com/Forums/en-US/windowsazure/thread/9e255447-4dc7-458a-99d3-bdc04bdc5474/
432
+ $headers['Content-Type'] = 'application/atom+xml';
433
+ }
434
+ $headers['Content-Length'] = 0;
435
+ if (!$verifyEtag) {
436
+ $headers['If-Match'] = '*';
437
+ } else {
438
+ $headers['If-Match'] = $entity->getEtag();
439
+ }
440
+
441
+ // Perform request
442
+ $response = null;
443
+ if ($this->isInBatch()) {
444
+ $this->getCurrentBatch()->enlistOperation($tableName . '(PartitionKey=\'' . $entity->getPartitionKey() . '\', RowKey=\'' . $entity->getRowKey() . '\')', '', Microsoft_Http_Client::DELETE, $headers, true, null);
445
+ return null;
446
+ } else {
447
+ $response = $this->_performRequest($tableName . '(PartitionKey=\'' . $entity->getPartitionKey() . '\', RowKey=\'' . $entity->getRowKey() . '\')', '', Microsoft_Http_Client::DELETE, $headers, true, null);
448
+ }
449
+ if (!$response->isSuccessful()) {
450
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
451
+ }
452
+ }
453
+
454
+ /**
455
+ * Retrieve entity from table, by id
456
+ *
457
+ * @param string $tableName Table name
458
+ * @param string $partitionKey Partition key
459
+ * @param string $rowKey Row key
460
+ * @param string $entityClass Entity class name*
461
+ * @return Microsoft_WindowsAzure_Storage_TableEntity
462
+ * @throws Microsoft_WindowsAzure_Exception
463
+ */
464
+ public function retrieveEntityById($tableName = '', $partitionKey = '', $rowKey = '', $entityClass = 'Microsoft_WindowsAzure_Storage_DynamicTableEntity')
465
+ {
466
+ if ($tableName === '') {
467
+ throw new Microsoft_WindowsAzure_Exception('Table name is not specified.');
468
+ }
469
+ if ($partitionKey === '') {
470
+ throw new Microsoft_WindowsAzure_Exception('Partition key is not specified.');
471
+ }
472
+ if ($rowKey === '') {
473
+ throw new Microsoft_WindowsAzure_Exception('Row key is not specified.');
474
+ }
475
+ if ($entityClass === '') {
476
+ throw new Microsoft_WindowsAzure_Exception('Entity class is not specified.');
477
+ }
478
+
479
+
480
+ // Check for combined size of partition key and row key
481
+ // http://msdn.microsoft.com/en-us/library/dd179421.aspx
482
+ if (strlen($partitionKey . $rowKey) >= 256) {
483
+ // Start a batch if possible
484
+ if ($this->isInBatch()) {
485
+ throw new Microsoft_WindowsAzure_Exception('Entity cannot be retrieved. A transaction is required to retrieve the entity, but another transaction is already active.');
486
+ }
487
+
488
+ $this->startBatch();
489
+ }
490
+
491
+ // Fetch entities from Azure
492
+ $result = $this->retrieveEntities(
493
+ $this->select()
494
+ ->from($tableName)
495
+ ->wherePartitionKey($partitionKey)
496
+ ->whereRowKey($rowKey),
497
+ '',
498
+ $entityClass
499
+ );
500
+
501
+ // Return
502
+ if (count($result) == 1) {
503
+ return $result[0];
504
+ }
505
+
506
+ return null;
507
+ }
508
+
509
+ /**
510
+ * Create a new Microsoft_WindowsAzure_Storage_TableEntityQuery
511
+ *
512
+ * @return Microsoft_WindowsAzure_Storage_TableEntityQuery
513
+ */
514
+ public function select()
515
+ {
516
+ return new Microsoft_WindowsAzure_Storage_TableEntityQuery();
517
+ }
518
+
519
+ /**
520
+ * Retrieve entities from table
521
+ *
522
+ * @param string $tableName|Microsoft_WindowsAzure_Storage_TableEntityQuery Table name -or- Microsoft_WindowsAzure_Storage_TableEntityQuery instance
523
+ * @param string $filter Filter condition (not applied when $tableName is a Microsoft_WindowsAzure_Storage_TableEntityQuery instance)
524
+ * @param string $entityClass Entity class name
525
+ * @param string $nextPartitionKey Next partition key, used for listing entities when total amount of entities is > 1000.
526
+ * @param string $nextRowKey Next row key, used for listing entities when total amount of entities is > 1000.
527
+ * @return array Array of Microsoft_WindowsAzure_Storage_TableEntity
528
+ * @throws Microsoft_WindowsAzure_Exception
529
+ */
530
+ public function retrieveEntities($tableName = '', $filter = '', $entityClass = 'Microsoft_WindowsAzure_Storage_DynamicTableEntity', $nextPartitionKey = null, $nextRowKey = null)
531
+ {
532
+ if ($tableName === '') {
533
+ throw new Microsoft_WindowsAzure_Exception('Table name is not specified.');
534
+ }
535
+ if ($entityClass === '') {
536
+ throw new Microsoft_WindowsAzure_Exception('Entity class is not specified.');
537
+ }
538
+
539
+ // Convenience...
540
+ if (class_exists($filter)) {
541
+ $entityClass = $filter;
542
+ $filter = '';
543
+ }
544
+
545
+ // Query string
546
+ $queryString = '';
547
+
548
+ // Determine query
549
+ if (is_string($tableName)) {
550
+ // Option 1: $tableName is a string
551
+
552
+ // Append parentheses
553
+ $tableName .= '()';
554
+
555
+ // Build query
556
+ $query = array();
557
+
558
+ // Filter?
559
+ if ($filter !== '') {
560
+ $query[] = '$filter=' . Microsoft_WindowsAzure_Storage_TableEntityQuery::encodeQuery($filter);
561
+ }
562
+
563
+ // Build queryString
564
+ if (count($query) > 0) {
565
+ $queryString = '?' . implode('&', $query);
566
+ }
567
+ } else if (get_class($tableName) == 'Microsoft_WindowsAzure_Storage_TableEntityQuery') {
568
+ // Option 2: $tableName is a Microsoft_WindowsAzure_Storage_TableEntityQuery instance
569
+
570
+ // Build queryString
571
+ $queryString = $tableName->assembleQueryString(true);
572
+
573
+ // Change $tableName
574
+ $tableName = $tableName->assembleFrom(true);
575
+ } else {
576
+ throw new Microsoft_WindowsAzure_Exception('Invalid argument: $tableName');
577
+ }
578
+
579
+ // Add continuation querystring parameters?
580
+ if (!is_null($nextPartitionKey) && !is_null($nextRowKey)) {
581
+ if ($queryString !== '') {
582
+ $queryString .= '&';
583
+ }
584
+
585
+ $queryString .= '&NextPartitionKey=' . rawurlencode($nextPartitionKey) . '&NextRowKey=' . rawurlencode($nextRowKey);
586
+ }
587
+
588
+ // Perform request
589
+ $response = null;
590
+ if ($this->isInBatch() && $this->getCurrentBatch()->getOperationCount() == 0) {
591
+ $this->getCurrentBatch()->enlistOperation($tableName, $queryString, Microsoft_Http_Client::GET, array(), true, null);
592
+ $response = $this->getCurrentBatch()->commit();
593
+
594
+ // Get inner response (multipart)
595
+ $innerResponse = $response->getBody();
596
+ $innerResponse = substr($innerResponse, strpos($innerResponse, 'HTTP/1.1 200 OK'));
597
+ $innerResponse = substr($innerResponse, 0, strpos($innerResponse, '--batchresponse'));
598
+ $response = Microsoft_Http_Response::fromString($innerResponse);
599
+ } else {
600
+ $response = $this->_performRequest($tableName, $queryString, Microsoft_Http_Client::GET, array(), true, null);
601
+ }
602
+
603
+ if ($response->isSuccessful()) {
604
+ // Parse result
605
+ $result = $this->_parseResponse($response);
606
+ if (!$result) {
607
+ return array();
608
+ }
609
+
610
+ $entries = null;
611
+ if ($result->entry) {
612
+ if (count($result->entry) > 1) {
613
+ $entries = $result->entry;
614
+ } else {
615
+ $entries = array($result->entry);
616
+ }
617
+ } else {
618
+ // This one is tricky... If we have properties defined, we have an entity.
619
+ $properties = $result->xpath('//m:properties');
620
+ if ($properties) {
621
+ $entries = array($result);
622
+ } else {
623
+ return array();
624
+ }
625
+ }
626
+
627
+ // Create return value
628
+ $returnValue = array();
629
+ foreach ($entries as $entry) {
630
+ // Parse properties
631
+ $properties = $entry->xpath('.//m:properties');
632
+ $properties = $properties[0]->children('http://schemas.microsoft.com/ado/2007/08/dataservices');
633
+
634
+ // Create entity
635
+ $entity = new $entityClass('', '');
636
+ $entity->setAzureValues((array)$properties, $this->_throwExceptionOnMissingData);
637
+
638
+ // If we have a Microsoft_WindowsAzure_Storage_DynamicTableEntity, make sure all property types are OK
639
+ if ($entity instanceof Microsoft_WindowsAzure_Storage_DynamicTableEntity) {
640
+ foreach ($properties as $key => $value) {
641
+ $attributes = $value->attributes('http://schemas.microsoft.com/ado/2007/08/dataservices/metadata');
642
+ $type = (string)$attributes['type'];
643
+ if ($type !== '') {
644
+ $entity->setAzurePropertyType($key, $type);
645
+ }
646
+ }
647
+ }
648
+
649
+ // Update etag
650
+ $etag = $entry->attributes('http://schemas.microsoft.com/ado/2007/08/dataservices/metadata');
651
+ $etag = (string)$etag['etag'];
652
+ $entity->setEtag($etag);
653
+
654
+ // Add to result
655
+ $returnValue[] = $entity;
656
+ }
657
+
658
+ // More entities?
659
+ if (!is_null($response->getHeader('x-ms-continuation-NextPartitionKey')) && !is_null($response->getHeader('x-ms-continuation-NextRowKey'))) {
660
+ if (strpos($queryString, '$top') === false) {
661
+ $returnValue = array_merge($returnValue, $this->retrieveEntities($tableName, $filter, $entityClass, $response->getHeader('x-ms-continuation-NextPartitionKey'), $response->getHeader('x-ms-continuation-NextRowKey')));
662
+ }
663
+ }
664
+
665
+ // Return
666
+ return $returnValue;
667
+ } else {
668
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
669
+ }
670
+ }
671
+
672
+ /**
673
+ * Update entity by replacing it
674
+ *
675
+ * @param string $tableName Table name
676
+ * @param Microsoft_WindowsAzure_Storage_TableEntity $entity Entity to update
677
+ * @param boolean $verifyEtag Verify etag of the entity (used for concurrency)
678
+ * @throws Microsoft_WindowsAzure_Exception
679
+ */
680
+ public function updateEntity($tableName = '', Microsoft_WindowsAzure_Storage_TableEntity $entity = null, $verifyEtag = false)
681
+ {
682
+ return $this->_changeEntity(Microsoft_Http_Client::PUT, $tableName, $entity, $verifyEtag);
683
+ }
684
+
685
+ /**
686
+ * Update entity by adding or updating properties
687
+ *
688
+ * @param string $tableName Table name
689
+ * @param Microsoft_WindowsAzure_Storage_TableEntity $entity Entity to update
690
+ * @param boolean $verifyEtag Verify etag of the entity (used for concurrency)
691
+ * @param array $properties Properties to merge. All properties will be used when omitted.
692
+ * @throws Microsoft_WindowsAzure_Exception
693
+ */
694
+ public function mergeEntity($tableName = '', Microsoft_WindowsAzure_Storage_TableEntity $entity = null, $verifyEtag = false, $properties = array())
695
+ {
696
+ $mergeEntity = null;
697
+ if (is_array($properties) && count($properties) > 0) {
698
+ // Build a new object
699
+ $mergeEntity = new Microsoft_WindowsAzure_Storage_DynamicTableEntity($entity->getPartitionKey(), $entity->getRowKey());
700
+
701
+ // Keep only values mentioned in $properties
702
+ $azureValues = $entity->getAzureValues();
703
+ foreach ($azureValues as $key => $value) {
704
+ if (in_array($value->Name, $properties)) {
705
+ $mergeEntity->setAzureProperty($value->Name, $value->Value, $value->Type);
706
+ }
707
+ }
708
+ } else {
709
+ $mergeEntity = $entity;
710
+ }
711
+
712
+ // Ensure entity timestamp matches updated timestamp
713
+ $entity->setTimestamp($this->isoDate());
714
+
715
+ return $this->_changeEntity(Microsoft_Http_Client::MERGE, $tableName, $mergeEntity, $verifyEtag);
716
+ }
717
+
718
+ /**
719
+ * Get error message from Microsoft_Http_Response
720
+ *
721
+ * @param Microsoft_Http_Response $response Repsonse
722
+ * @param string $alternativeError Alternative error message
723
+ * @return string
724
+ */
725
+ protected function _getErrorMessage(Microsoft_Http_Response $response, $alternativeError = 'Unknown error.')
726
+ {
727
+ $response = $this->_parseResponse($response);
728
+ if ($response && $response->message) {
729
+ return (string)$response->message;
730
+ } else {
731
+ return $alternativeError;
732
+ }
733
+ }
734
+
735
+ /**
736
+ * Update entity / merge entity
737
+ *
738
+ * @param string $httpVerb HTTP verb to use (PUT = update, MERGE = merge)
739
+ * @param string $tableName Table name
740
+ * @param Microsoft_WindowsAzure_Storage_TableEntity $entity Entity to update
741
+ * @param boolean $verifyEtag Verify etag of the entity (used for concurrency)
742
+ * @throws Microsoft_WindowsAzure_Exception
743
+ */
744
+ protected function _changeEntity($httpVerb = Microsoft_Http_Client::PUT, $tableName = '', Microsoft_WindowsAzure_Storage_TableEntity $entity = null, $verifyEtag = false)
745
+ {
746
+ if ($tableName === '') {
747
+ throw new Microsoft_WindowsAzure_Exception('Table name is not specified.');
748
+ }
749
+ if (is_null($entity)) {
750
+ throw new Microsoft_WindowsAzure_Exception('Entity is not specified.');
751
+ }
752
+
753
+ // Add header information
754
+ $headers = array();
755
+ $headers['Content-Type'] = 'application/atom+xml';
756
+ $headers['Content-Length'] = 0;
757
+ if (!$verifyEtag) {
758
+ $headers['If-Match'] = '*';
759
+ } else {
760
+ $headers['If-Match'] = $entity->getEtag();
761
+ }
762
+
763
+ // Generate request body
764
+ $requestBody = '<?xml version="1.0" encoding="utf-8" standalone="yes"?>
765
+ <entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
766
+ <title />
767
+ <updated>{tpl:Updated}</updated>
768
+ <author>
769
+ <name />
770
+ </author>
771
+ <id />
772
+ <content type="application/xml">
773
+ <m:properties>
774
+ {tpl:Properties}
775
+ </m:properties>
776
+ </content>
777
+ </entry>';
778
+
779
+ // Attempt to get timestamp from entity
780
+ $timestamp = $entity->getTimestamp();
781
+ if ($timestamp == Microsoft_WindowsAzure_Storage_TableEntity::DEFAULT_TIMESTAMP) {
782
+ $timestamp = $this->isoDate();
783
+ }
784
+
785
+ $requestBody = $this->_fillTemplate($requestBody, array(
786
+ 'Updated' => $timestamp,
787
+ 'Properties' => $this->_generateAzureRepresentation($entity)
788
+ ));
789
+
790
+ // Add header information
791
+ $headers = array();
792
+ $headers['Content-Type'] = 'application/atom+xml';
793
+ if (!$verifyEtag) {
794
+ $headers['If-Match'] = '*';
795
+ } else {
796
+ $headers['If-Match'] = $entity->getEtag();
797
+ }
798
+
799
+ // Perform request
800
+ $response = null;
801
+ if ($this->isInBatch()) {
802
+ $this->getCurrentBatch()->enlistOperation($tableName . '(PartitionKey=\'' . $entity->getPartitionKey() . '\', RowKey=\'' . $entity->getRowKey() . '\')', '', $httpVerb, $headers, true, $requestBody);
803
+ return null;
804
+ } else {
805
+ $response = $this->_performRequest($tableName . '(PartitionKey=\'' . $entity->getPartitionKey() . '\', RowKey=\'' . $entity->getRowKey() . '\')', '', $httpVerb, $headers, true, $requestBody);
806
+ }
807
+ if ($response->isSuccessful()) {
808
+ // Update properties
809
+ $entity->setEtag($response->getHeader('Etag'));
810
+ $entity->setTimestamp($response->getHeader('Last-modified'));
811
+
812
+ return $entity;
813
+ } else {
814
+ throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
815
+ }
816
+ }
817
+
818
+ /**
819
+ * Generate RFC 1123 compliant date string
820
+ *
821
+ * @return string
822
+ */
823
+ protected function _rfcDate()
824
+ {
825
+ return gmdate('D, d M Y H:i:s', time()) . ' GMT'; // RFC 1123
826
+ }
827
+
828
+ /**
829
+ * Fill text template with variables from key/value array
830
+ *
831
+ * @param string $templateText Template text
832
+ * @param array $variables Array containing key/value pairs
833
+ * @return string
834
+ */
835
+ protected function _fillTemplate($templateText, $variables = array())
836
+ {
837
+ foreach ($variables as $key => $value) {
838
+ $templateText = str_replace('{tpl:' . $key . '}', $value, $templateText);
839
+ }
840
+ return $templateText;
841
+ }
842
+
843
+ /**
844
+ * Generate Azure representation from entity (creates atompub markup from properties)
845
+ *
846
+ * @param Microsoft_WindowsAzure_Storage_TableEntity $entity
847
+ * @return string
848
+ */
849
+ protected function _generateAzureRepresentation(Microsoft_WindowsAzure_Storage_TableEntity $entity = null)
850
+ {
851
+ // Generate Azure representation from entity
852
+ $azureRepresentation = array();
853
+ $azureValues = $entity->getAzureValues();
854
+ foreach ($azureValues as $azureValue) {
855
+ $value = array();
856
+ $value[] = '<d:' . $azureValue->Name;
857
+ if ($azureValue->Type != '') {
858
+ $value[] = ' m:type="' . $azureValue->Type . '"';
859
+ }
860
+ if (is_null($azureValue->Value)) {
861
+ $value[] = ' m:null="true"';
862
+ }
863
+ $value[] = '>';
864
+
865
+ if (!is_null($azureValue->Value)) {
866
+ if (strtolower($azureValue->Type) == 'edm.boolean') {
867
+ $value[] = ($azureValue->Value == true ? '1' : '0');
868
+ } else {
869
+ $value[] = htmlspecialchars($azureValue->Value);
870
+ }
871
+ }
872
+
873
+ $value[] = '</d:' . $azureValue->Name . '>';
874
+ $azureRepresentation[] = implode('', $value);
875
+ }
876
+
877
+ return implode('', $azureRepresentation);
878
+ }
879
+
880
+ /**
881
+ * Perform request using Microsoft_Http_Client channel
882
+ *
883
+ * @param string $path Path
884
+ * @param string $queryString Query string
885
+ * @param string $httpVerb HTTP verb the request will use
886
+ * @param array $headers x-ms headers to add
887
+ * @param boolean $forTableStorage Is the request for table storage?
888
+ * @param mixed $rawData Optional RAW HTTP data to be sent over the wire
889
+ * @param string $resourceType Resource type
890
+ * @param string $requiredPermission Required permission
891
+ * @return Microsoft_Http_Response
892
+ */
893
+ protected function _performRequest(
894
+ $path = '/',
895
+ $queryString = '',
896
+ $httpVerb = Microsoft_Http_Client::GET,
897
+ $headers = array(),
898
+ $forTableStorage = false,
899
+ $rawData = null,
900
+ $resourceType = Microsoft_WindowsAzure_Storage::RESOURCE_UNKNOWN,
901
+ $requiredPermission = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ
902
+ ) {
903
+ // Add headers
904
+ $headers['DataServiceVersion'] = '1.0;NetFx';
905
+ $headers['MaxDataServiceVersion'] = '1.0;NetFx';
906
+
907
+ // Perform request
908
+ return parent::_performRequest(
909
+ $path,
910
+ $queryString,
911
+ $httpVerb,
912
+ $headers,
913
+ $forTableStorage,
914
+ $rawData,
915
+ $resourceType,
916
+ $requiredPermission
917
+ );
918
+ }
919
+ }
app/libs/Microsoft/WindowsAzure/Storage/TableEntity.php ADDED
@@ -0,0 +1,344 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Storage
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: BlobInstance.php 14561 2009-05-07 08:05:12Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Exception.php';
40
+
41
+
42
+ /**
43
+ * @category Microsoft
44
+ * @package Microsoft_WindowsAzure
45
+ * @subpackage Storage
46
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
47
+ * @license http://phpazure.codeplex.com/license
48
+ */
49
+ class Microsoft_WindowsAzure_Storage_TableEntity
50
+ {
51
+ /**
52
+ * Default timestamp if none has been provided
53
+ */
54
+ const DEFAULT_TIMESTAMP = '1900-01-01T00:00:00';
55
+
56
+ /**
57
+ * Partition key
58
+ *
59
+ * @var string
60
+ */
61
+ protected $_partitionKey;
62
+
63
+ /**
64
+ * Row key
65
+ *
66
+ * @var string
67
+ */
68
+ protected $_rowKey;
69
+
70
+ /**
71
+ * Timestamp
72
+ *
73
+ * @var string
74
+ */
75
+ protected $_timestamp;
76
+
77
+ /**
78
+ * Etag
79
+ *
80
+ * @var string
81
+ */
82
+ protected $_etag = '';
83
+
84
+ /**
85
+ * Constructor
86
+ *
87
+ * @param string $partitionKey Partition key
88
+ * @param string $rowKey Row key
89
+ */
90
+ public function __construct($partitionKey = '', $rowKey = '')
91
+ {
92
+ $this->_partitionKey = $partitionKey;
93
+ $this->_rowKey = $rowKey;
94
+ }
95
+
96
+ /**
97
+ * Get partition key
98
+ *
99
+ * @azure PartitionKey
100
+ * @return string
101
+ */
102
+ public function getPartitionKey()
103
+ {
104
+ return $this->_partitionKey;
105
+ }
106
+
107
+ /**
108
+ * Set partition key
109
+ *
110
+ * @azure PartitionKey
111
+ * @param string $value
112
+ */
113
+ public function setPartitionKey($value)
114
+ {
115
+ $this->_partitionKey = $value;
116
+ }
117
+
118
+ /**
119
+ * Get row key
120
+ *
121
+ * @azure RowKey
122
+ * @return string
123
+ */
124
+ public function getRowKey()
125
+ {
126
+ return $this->_rowKey;
127
+ }
128
+
129
+ /**
130
+ * Set row key
131
+ *
132
+ * @azure RowKey
133
+ * @param string $value
134
+ */
135
+ public function setRowKey($value)
136
+ {
137
+ $this->_rowKey = $value;
138
+ }
139
+
140
+ /**
141
+ * Get timestamp
142
+ *
143
+ * @azure Timestamp Edm.DateTime
144
+ * @return string
145
+ */
146
+ public function getTimestamp()
147
+ {
148
+ if (null === $this->_timestamp) {
149
+ $this->setTimestamp(self::DEFAULT_TIMESTAMP);
150
+ }
151
+ return $this->_timestamp;
152
+ }
153
+
154
+ /**
155
+ * Set timestamp
156
+ *
157
+ * @azure Timestamp Edm.DateTime
158
+ * @param string $value
159
+ */
160
+ public function setTimestamp($value = '1900-01-01T00:00:00')
161
+ {
162
+ $this->_timestamp = $value;
163
+ }
164
+
165
+ /**
166
+ * Get etag
167
+ *
168
+ * @return string
169
+ */
170
+ public function getEtag()
171
+ {
172
+ return $this->_etag;
173
+ }
174
+
175
+ /**
176
+ * Set etag
177
+ *
178
+ * @param string $value
179
+ */
180
+ public function setEtag($value = '')
181
+ {
182
+ $this->_etag = $value;
183
+ }
184
+
185
+ /**
186
+ * Get Azure values
187
+ *
188
+ * @return array
189
+ */
190
+ public function getAzureValues()
191
+ {
192
+ // Get accessors
193
+ $accessors = self::getAzureAccessors(get_class($this));
194
+
195
+ // Loop accessors and retrieve values
196
+ $returnValue = array();
197
+ foreach ($accessors as $accessor) {
198
+ if ($accessor->EntityType == 'ReflectionProperty') {
199
+ $property = $accessor->EntityAccessor;
200
+ $returnValue[] = (object)array(
201
+ 'Name' => $accessor->AzurePropertyName,
202
+ 'Type' => $accessor->AzurePropertyType,
203
+ 'Value' => $this->$property,
204
+ );
205
+ } else if ($accessor->EntityType == 'ReflectionMethod' && substr(strtolower($accessor->EntityAccessor), 0, 3) == 'get') {
206
+ $method = $accessor->EntityAccessor;
207
+ $returnValue[] = (object)array(
208
+ 'Name' => $accessor->AzurePropertyName,
209
+ 'Type' => $accessor->AzurePropertyType,
210
+ 'Value' => $this->$method(),
211
+ );
212
+ }
213
+ }
214
+
215
+ // Return
216
+ return $returnValue;
217
+ }
218
+
219
+ /**
220
+ * Set Azure values
221
+ *
222
+ * @param array $values
223
+ * @param boolean $throwOnError Throw Microsoft_WindowsAzure_Exception when a property is not specified in $values?
224
+ * @throws Microsoft_WindowsAzure_Exception
225
+ */
226
+ public function setAzureValues($values = array(), $throwOnError = false)
227
+ {
228
+ // Get accessors
229
+ $accessors = self::getAzureAccessors(get_class($this));
230
+
231
+ // Loop accessors and set values
232
+ $returnValue = array();
233
+ foreach ($accessors as $accessor) {
234
+ if (isset($values[$accessor->AzurePropertyName])) {
235
+ // Cast to correct type
236
+ if ($accessor->AzurePropertyType != '') {
237
+ switch (strtolower($accessor->AzurePropertyType)) {
238
+ case 'edm.int32':
239
+ case 'edm.int64':
240
+ $values[$accessor->AzurePropertyName] = intval($values[$accessor->AzurePropertyName]); break;
241
+ case 'edm.boolean':
242
+ if ($values[$accessor->AzurePropertyName] == 'true' || $values[$accessor->AzurePropertyName] == '1')
243
+ $values[$accessor->AzurePropertyName] = true;
244
+ else
245
+ $values[$accessor->AzurePropertyName] = false;
246
+ break;
247
+ case 'edm.double':
248
+ $values[$accessor->AzurePropertyName] = floatval($values[$accessor->AzurePropertyName]); break;
249
+ }
250
+ }
251
+
252
+ // Assign value
253
+ if ($accessor->EntityType == 'ReflectionProperty') {
254
+ $property = $accessor->EntityAccessor;
255
+ $this->$property = $values[$accessor->AzurePropertyName];
256
+ } else if ($accessor->EntityType == 'ReflectionMethod' && substr(strtolower($accessor->EntityAccessor), 0, 3) == 'set') {
257
+ $method = $accessor->EntityAccessor;
258
+ $this->$method($values[$accessor->AzurePropertyName]);
259
+ }
260
+ } else if ($throwOnError) {
261
+ throw new Microsoft_WindowsAzure_Exception("Property '" . $accessor->AzurePropertyName . "' was not found in \$values array");
262
+ }
263
+ }
264
+
265
+ // Return
266
+ return $returnValue;
267
+ }
268
+
269
+ /**
270
+ * Get Azure accessors from class
271
+ *
272
+ * @param string $className Class to get accessors for
273
+ * @return array
274
+ */
275
+ public static function getAzureAccessors($className = '')
276
+ {
277
+ // List of accessors
278
+ $azureAccessors = array();
279
+
280
+ // Get all types
281
+ $type = new ReflectionClass($className);
282
+
283
+ // Loop all properties
284
+ $properties = $type->getProperties();
285
+ foreach ($properties as $property) {
286
+ $accessor = self::getAzureAccessor($property);
287
+ if (!is_null($accessor)) {
288
+ $azureAccessors[] = $accessor;
289
+ }
290
+ }
291
+
292
+ // Loop all methods
293
+ $methods = $type->getMethods();
294
+ foreach ($methods as $method) {
295
+ $accessor = self::getAzureAccessor($method);
296
+ if (!is_null($accessor)) {
297
+ $azureAccessors[] = $accessor;
298
+ }
299
+ }
300
+
301
+ // Return
302
+ return $azureAccessors;
303
+ }
304
+
305
+ /**
306
+ * Get Azure accessor from reflection member
307
+ *
308
+ * @param ReflectionProperty|ReflectionMethod $member
309
+ * @return object
310
+ */
311
+ public static function getAzureAccessor($member)
312
+ {
313
+ // Get comment
314
+ $docComment = $member->getDocComment();
315
+
316
+ // Check for Azure comment
317
+ if (strpos($docComment, '@azure') === false)
318
+ {
319
+ return null;
320
+ }
321
+
322
+ // Search for @azure contents
323
+ $azureComment = '';
324
+ $commentLines = explode("\n", $docComment);
325
+ foreach ($commentLines as $commentLine) {
326
+ if (strpos($commentLine, '@azure') !== false) {
327
+ $azureComment = trim(substr($commentLine, strpos($commentLine, '@azure') + 6));
328
+ while (strpos($azureComment, ' ') !== false) {
329
+ $azureComment = str_replace(' ', ' ', $azureComment);
330
+ }
331
+ break;
332
+ }
333
+ }
334
+
335
+ // Fetch @azure properties
336
+ $azureProperties = explode(' ', $azureComment);
337
+ return (object)array(
338
+ 'EntityAccessor' => $member->getName(),
339
+ 'EntityType' => get_class($member),
340
+ 'AzurePropertyName' => $azureProperties[0],
341
+ 'AzurePropertyType' => isset($azureProperties[1]) ? $azureProperties[1] : ''
342
+ );
343
+ }
344
+ }
app/libs/Microsoft/WindowsAzure/Storage/TableEntityQuery.php ADDED
@@ -0,0 +1,363 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Storage
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: Blob.php 14561 2009-05-07 08:05:12Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @category Microsoft
38
+ * @package Microsoft_WindowsAzure
39
+ * @subpackage Storage
40
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
41
+ * @license http://phpazure.codeplex.com/license
42
+ */
43
+ class Microsoft_WindowsAzure_Storage_TableEntityQuery
44
+ {
45
+ /**
46
+ * From
47
+ *
48
+ * @var string
49
+ */
50
+ protected $_from = '';
51
+
52
+ /**
53
+ * Where
54
+ *
55
+ * @var array
56
+ */
57
+ protected $_where = array();
58
+
59
+ /**
60
+ * Order by
61
+ *
62
+ * @var array
63
+ */
64
+ protected $_orderBy = array();
65
+
66
+ /**
67
+ * Top
68
+ *
69
+ * @var int
70
+ */
71
+ protected $_top = null;
72
+
73
+ /**
74
+ * Partition key
75
+ *
76
+ * @var string
77
+ */
78
+ protected $_partitionKey = null;
79
+
80
+ /**
81
+ * Row key
82
+ *
83
+ * @var string
84
+ */
85
+ protected $_rowKey = null;
86
+
87
+ /**
88
+ * Select clause
89
+ *
90
+ * @return Microsoft_WindowsAzure_Storage_TableEntityQuery
91
+ */
92
+ public function select()
93
+ {
94
+ return $this;
95
+ }
96
+
97
+ /**
98
+ * From clause
99
+ *
100
+ * @param string $name Table name to select entities from
101
+ * @return Microsoft_WindowsAzure_Storage_TableEntityQuery
102
+ */
103
+ public function from($name)
104
+ {
105
+ $this->_from = $name;
106
+ return $this;
107
+ }
108
+
109
+ /**
110
+ * Specify partition key
111
+ *
112
+ * @param string $value Partition key to query for
113
+ * @return Microsoft_WindowsAzure_Storage_TableEntityQuery
114
+ */
115
+ public function wherePartitionKey($value = null)
116
+ {
117
+ $this->_partitionKey = $value;
118
+ return $this;
119
+ }
120
+
121
+ /**
122
+ * Specify row key
123
+ *
124
+ * @param string $value Row key to query for
125
+ * @return Microsoft_WindowsAzure_Storage_TableEntityQuery
126
+ */
127
+ public function whereRowKey($value = null)
128
+ {
129
+ $this->_rowKey = $value;
130
+ return $this;
131
+ }
132
+
133
+ /**
134
+ * Add where clause
135
+ *
136
+ * @param string $condition Condition, can contain question mark(s) (?) for parameter insertion.
137
+ * @param string|array $value Value(s) to insert in question mark (?) parameters.
138
+ * @param string $cond Condition for the clause (and/or/not)
139
+ * @return Microsoft_WindowsAzure_Storage_TableEntityQuery
140
+ */
141
+ public function where($condition, $value = null, $cond = '')
142
+ {
143
+ $condition = $this->_replaceOperators($condition);
144
+
145
+ if (!is_null($value)) {
146
+ $condition = $this->_quoteInto($condition, $value);
147
+ }
148
+
149
+ if (count($this->_where) == 0) {
150
+ $cond = '';
151
+ } else if ($cond !== '') {
152
+ $cond = ' ' . strtolower(trim($cond)) . ' ';
153
+ }
154
+
155
+ $this->_where[] = $cond . $condition;
156
+ return $this;
157
+ }
158
+
159
+ /**
160
+ * Add where clause with AND condition
161
+ *
162
+ * @param string $condition Condition, can contain question mark(s) (?) for parameter insertion.
163
+ * @param string|array $value Value(s) to insert in question mark (?) parameters.
164
+ * @return Microsoft_WindowsAzure_Storage_TableEntityQuery
165
+ */
166
+ public function andWhere($condition, $value = null)
167
+ {
168
+ return $this->where($condition, $value, 'and');
169
+ }
170
+
171
+ /**
172
+ * Add where clause with OR condition
173
+ *
174
+ * @param string $condition Condition, can contain question mark(s) (?) for parameter insertion.
175
+ * @param string|array $value Value(s) to insert in question mark (?) parameters.
176
+ * @return Microsoft_WindowsAzure_Storage_TableEntityQuery
177
+ */
178
+ public function orWhere($condition, $value = null)
179
+ {
180
+ return $this->where($condition, $value, 'or');
181
+ }
182
+
183
+ /**
184
+ * OrderBy clause
185
+ *
186
+ * @param string $column Column to sort by
187
+ * @param string $direction Direction to sort (asc/desc)
188
+ * @return Microsoft_WindowsAzure_Storage_TableEntityQuery
189
+ */
190
+ public function orderBy($column, $direction = 'asc')
191
+ {
192
+ $this->_orderBy[] = $column . ' ' . $direction;
193
+ return $this;
194
+ }
195
+
196
+ /**
197
+ * Top clause
198
+ *
199
+ * @param int $top Top to fetch
200
+ * @return Microsoft_WindowsAzure_Storage_TableEntityQuery
201
+ */
202
+ public function top($top = null)
203
+ {
204
+ $this->_top = (int)$top;
205
+ return $this;
206
+ }
207
+
208
+ /**
209
+ * Assembles the query string
210
+ *
211
+ * @param boolean $urlEncode Apply URL encoding to the query string
212
+ * @return string
213
+ */
214
+ public function assembleQueryString($urlEncode = false)
215
+ {
216
+ $query = array();
217
+ if (count($this->_where) != 0) {
218
+ $filter = implode('', $this->_where);
219
+ $query[] = '$filter=' . ($urlEncode ? self::encodeQuery($filter) : $filter);
220
+ }
221
+
222
+ if (count($this->_orderBy) != 0) {
223
+ $orderBy = implode(',', $this->_orderBy);
224
+ $query[] = '$orderby=' . ($urlEncode ? self::encodeQuery($orderBy) : $orderBy);
225
+ }
226
+
227
+ if (!is_null($this->_top)) {
228
+ $query[] = '$top=' . $this->_top;
229
+ }
230
+
231
+ if (count($query) != 0) {
232
+ return '?' . implode('&', $query);
233
+ }
234
+
235
+ return '';
236
+ }
237
+
238
+ /**
239
+ * Assemble from
240
+ *
241
+ * @param boolean $includeParentheses Include parentheses? ()
242
+ * @return string
243
+ */
244
+ public function assembleFrom($includeParentheses = true)
245
+ {
246
+ $identifier = '';
247
+ if ($includeParentheses) {
248
+ $identifier .= '(';
249
+
250
+ if (!is_null($this->_partitionKey)) {
251
+ $identifier .= 'PartitionKey=\'' . $this->_partitionKey . '\'';
252
+ }
253
+
254
+ if (!is_null($this->_partitionKey) && !is_null($this->_rowKey)) {
255
+ $identifier .= ', ';
256
+ }
257
+
258
+ if (!is_null($this->_rowKey)) {
259
+ $identifier .= 'RowKey=\'' . $this->_rowKey . '\'';
260
+ }
261
+
262
+ $identifier .= ')';
263
+ }
264
+ return $this->_from . $identifier;
265
+ }
266
+
267
+ /**
268
+ * Assemble full query
269
+ *
270
+ * @return string
271
+ */
272
+ public function assembleQuery()
273
+ {
274
+ $assembledQuery = $this->assembleFrom();
275
+
276
+ $queryString = $this->assembleQueryString();
277
+ if ($queryString !== '') {
278
+ $assembledQuery .= $queryString;
279
+ }
280
+
281
+ return $assembledQuery;
282
+ }
283
+
284
+ /**
285
+ * Quotes a variable into a condition
286
+ *
287
+ * @param string $text Condition, can contain question mark(s) (?) for parameter insertion.
288
+ * @param string|array $value Value(s) to insert in question mark (?) parameters.
289
+ * @return string
290
+ */
291
+ protected function _quoteInto($text, $value = null)
292
+ {
293
+ if (!is_array($value)) {
294
+ $text = str_replace('?', '\'' . addslashes($value) . '\'', $text);
295
+ } else {
296
+ $i = 0;
297
+ while(strpos($text, '?') !== false) {
298
+ if (is_numeric($value[$i])) {
299
+ $text = substr_replace($text, $value[$i++], strpos($text, '?'), 1);
300
+ } else {
301
+ $text = substr_replace($text, '\'' . addslashes($value[$i++]) . '\'', strpos($text, '?'), 1);
302
+ }
303
+ }
304
+ }
305
+ return $text;
306
+ }
307
+
308
+ /**
309
+ * Replace operators
310
+ *
311
+ * @param string $text
312
+ * @return string
313
+ */
314
+ protected function _replaceOperators($text)
315
+ {
316
+ $text = str_replace('==', 'eq', $text);
317
+ $text = str_replace('>', 'gt', $text);
318
+ $text = str_replace('<', 'lt', $text);
319
+ $text = str_replace('>=', 'ge', $text);
320
+ $text = str_replace('<=', 'le', $text);
321
+ $text = str_replace('!=', 'ne', $text);
322
+
323
+ $text = str_replace('&&', 'and', $text);
324
+ $text = str_replace('||', 'or', $text);
325
+ $text = str_replace('!', 'not', $text);
326
+
327
+ return $text;
328
+ }
329
+
330
+ /**
331
+ * urlencode a query
332
+ *
333
+ * @param string $query Query to encode
334
+ * @return string Encoded query
335
+ */
336
+ public static function encodeQuery($query)
337
+ {
338
+ $query = str_replace('/', '%2F', $query);
339
+ $query = str_replace('?', '%3F', $query);
340
+ $query = str_replace(':', '%3A', $query);
341
+ $query = str_replace('@', '%40', $query);
342
+ $query = str_replace('&', '%26', $query);
343
+ $query = str_replace('=', '%3D', $query);
344
+ $query = str_replace('+', '%2B', $query);
345
+ $query = str_replace(',', '%2C', $query);
346
+ $query = str_replace('$', '%24', $query);
347
+
348
+
349
+ $query = str_replace(' ', '%20', $query);
350
+
351
+ return $query;
352
+ }
353
+
354
+ /**
355
+ * __toString overload
356
+ *
357
+ * @return string
358
+ */
359
+ public function __toString()
360
+ {
361
+ return $this->assembleQuery();
362
+ }
363
+ }
app/libs/Microsoft/WindowsAzure/Storage/TableInstance.php ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright (c) 2009 - 2010, RealDolmen
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of RealDolmen nor the
14
+ * names of its contributors may be used to endorse or promote products
15
+ * derived from this software without specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
18
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
21
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * @category Microsoft
29
+ * @package Microsoft_WindowsAzure
30
+ * @subpackage Storage
31
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
32
+ * @license http://phpazure.codeplex.com/license
33
+ * @version $Id: BlobInstance.php 14561 2009-05-07 08:05:12Z unknown $
34
+ */
35
+
36
+ /**
37
+ * @see Microsoft_WindowsAzure_Exception
38
+ */
39
+ require_once 'Microsoft/WindowsAzure/Exception.php';
40
+
41
+ /**
42
+ * @see Microsoft_WindowsAzure_Storage_StorageEntityAbstract
43
+ */
44
+ require_once 'Microsoft/WindowsAzure/Storage/StorageEntityAbstract.php';
45
+
46
+ /**
47
+ * @category Microsoft
48
+ * @package Microsoft_WindowsAzure
49
+ * @subpackage Storage
50
+ * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
51
+ * @license http://phpazure.codeplex.com/license
52
+ *
53
+ * @property string $Id Id
54
+ * @property string $Name Name
55
+ * @property string $Href Href
56
+ * @property string $Updated Updated
57
+ */
58
+ class Microsoft_WindowsAzure_Storage_TableInstance
59
+ extends Microsoft_WindowsAzure_Storage_StorageEntityAbstract
60
+ {
61
+ /**
62
+ * Constructor
63
+ *
64
+ * @param string $id Id
65
+ * @param string $name Name
66
+ * @param string $href Href
67
+ * @param string $updated Updated
68
+ */
69
+ public function __construct($id, $name, $href, $updated)
70
+ {
71
+ $this->_data = array(
72
+ 'id' => $id,
73
+ 'name' => $name,
74
+ 'href' => $href,
75
+ 'updated' => $updated
76
+ );
77
+ }
78
+ }
app/libs/aws/lib/requestcore/requestcore.class.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Handles all HTTP requests using cURL and manages the responses.
4
  *
5
- * @version 2011.01.11
6
  * @copyright 2006-2011 Ryan Parman
7
  * @copyright 2006-2010 Foleeo Inc.
8
  * @copyright 2010-2011 Amazon.com, Inc. or its affiliates.
@@ -94,7 +94,7 @@ class RequestCore
94
  /**
95
  * Default useragent string to use.
96
  */
97
- public $useragent = 'RequestCore/1.4';
98
 
99
  /**
100
  * File to read from while streaming up.
@@ -131,6 +131,16 @@ class RequestCore
131
  */
132
  public $seek_position = null;
133
 
 
 
 
 
 
 
 
 
 
 
134
 
135
  /*%******************************************************************************************%*/
136
  // CONSTANTS
@@ -441,6 +451,55 @@ class RequestCore
441
  return $this;
442
  }
443
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
444
 
445
  /*%******************************************************************************************%*/
446
  // PREPARE, SEND, AND PROCESS REQUEST
@@ -474,7 +533,15 @@ class RequestCore
474
  $read = fread($this->read_stream, min($this->read_stream_size - $this->read_stream_read, $length)); // Remaining upload data or cURL's requested chunk size
475
  $this->read_stream_read += strlen($read);
476
 
477
- return $read === false ? '' : $read;
 
 
 
 
 
 
 
 
478
  }
479
 
480
  /**
@@ -502,6 +569,12 @@ class RequestCore
502
  $written_total += $written_last;
503
  }
504
 
 
 
 
 
 
 
505
  return $written_total;
506
  }
507
 
@@ -522,7 +595,6 @@ class RequestCore
522
  curl_setopt($curl_handle, CURLOPT_SSL_VERIFYPEER, false);
523
  curl_setopt($curl_handle, CURLOPT_SSL_VERIFYHOST, true);
524
  curl_setopt($curl_handle, CURLOPT_CLOSEPOLICY, CURLCLOSEPOLICY_LEAST_RECENTLY_USED);
525
- curl_setopt($curl_handle, CURLOPT_FOLLOWLOCATION, true);
526
  curl_setopt($curl_handle, CURLOPT_MAXREDIRS, 5);
527
  curl_setopt($curl_handle, CURLOPT_HEADER, true);
528
  curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, true);
@@ -533,6 +605,11 @@ class RequestCore
533
  curl_setopt($curl_handle, CURLOPT_USERAGENT, $this->useragent);
534
  curl_setopt($curl_handle, CURLOPT_READFUNCTION, array($this, 'streaming_read_callback'));
535
 
 
 
 
 
 
536
  // Enable a proxy connection if requested.
537
  if ($this->proxy)
538
  {
2
  /**
3
  * Handles all HTTP requests using cURL and manages the responses.
4
  *
5
+ * @version 2011.03.01
6
  * @copyright 2006-2011 Ryan Parman
7
  * @copyright 2006-2010 Foleeo Inc.
8
  * @copyright 2010-2011 Amazon.com, Inc. or its affiliates.
94
  /**
95
  * Default useragent string to use.
96
  */
97
+ public $useragent = 'RequestCore/1.4.1';
98
 
99
  /**
100
  * File to read from while streaming up.
131
  */
132
  public $seek_position = null;
133
 
134
+ /**
135
+ * The user-defined callback function to call when a stream is read from.
136
+ */
137
+ public $registered_streaming_read_callback = null;
138
+
139
+ /**
140
+ * The user-defined callback function to call when a stream is written to.
141
+ */
142
+ public $registered_streaming_write_callback = null;
143
+
144
 
145
  /*%******************************************************************************************%*/
146
  // CONSTANTS
451
  return $this;
452
  }
453
 
454
+ /**
455
+ * Register a callback function to execute whenever a data stream is read from using
456
+ * <CFRequest::streaming_read_callback()>.
457
+ *
458
+ * The user-defined callback function should accept three arguments:
459
+ *
460
+ * <ul>
461
+ * <li><code>$curl_handle</code> - <code>resource</code> - Required - The cURL handle resource that represents the in-progress transfer.</li>
462
+ * <li><code>$file_handle</code> - <code>resource</code> - Required - The file handle resource that represents the file on the local file system.</li>
463
+ * <li><code>$length</code> - <code>integer</code> - Required - The length in kilobytes of the data chunk that was transferred.</li>
464
+ * </ul>
465
+ *
466
+ * @param string|array|function $callback (Required) The callback function is called by <php:call_user_func()>, so you can pass the following values: <ul>
467
+ * <li>The name of a global function to execute, passed as a string.</li>
468
+ * <li>A method to execute, passed as <code>array('ClassName', 'MethodName')</code>.</li>
469
+ * <li>An anonymous function (PHP 5.3+).</li></ul>
470
+ * @return $this A reference to the current instance.
471
+ */
472
+ public function register_streaming_read_callback($callback)
473
+ {
474
+ $this->registered_streaming_read_callback = $callback;
475
+
476
+ return $this;
477
+ }
478
+
479
+ /**
480
+ * Register a callback function to execute whenever a data stream is written to using
481
+ * <CFRequest::streaming_write_callback()>.
482
+ *
483
+ * The user-defined callback function should accept two arguments:
484
+ *
485
+ * <ul>
486
+ * <li><code>$curl_handle</code> - <code>resource</code> - Required - The cURL handle resource that represents the in-progress transfer.</li>
487
+ * <li><code>$length</code> - <code>integer</code> - Required - The length in kilobytes of the data chunk that was transferred.</li>
488
+ * </ul>
489
+ *
490
+ * @param string|array|function $callback (Required) The callback function is called by <php:call_user_func()>, so you can pass the following values: <ul>
491
+ * <li>The name of a global function to execute, passed as a string.</li>
492
+ * <li>A method to execute, passed as <code>array('ClassName', 'MethodName')</code>.</li>
493
+ * <li>An anonymous function (PHP 5.3+).</li></ul>
494
+ * @return $this A reference to the current instance.
495
+ */
496
+ public function register_streaming_write_callback($callback)
497
+ {
498
+ $this->registered_streaming_write_callback = $callback;
499
+
500
+ return $this;
501
+ }
502
+
503
 
504
  /*%******************************************************************************************%*/
505
  // PREPARE, SEND, AND PROCESS REQUEST
533
  $read = fread($this->read_stream, min($this->read_stream_size - $this->read_stream_read, $length)); // Remaining upload data or cURL's requested chunk size
534
  $this->read_stream_read += strlen($read);
535
 
536
+ $out = $read === false ? '' : $read;
537
+
538
+ // Execute callback function
539
+ if ($this->registered_streaming_read_callback)
540
+ {
541
+ call_user_func($this->registered_streaming_read_callback, $curl_handle, $file_handle, $out);
542
+ }
543
+
544
+ return $out;
545
  }
546
 
547
  /**
569
  $written_total += $written_last;
570
  }
571
 
572
+ // Execute callback function
573
+ if ($this->registered_streaming_write_callback)
574
+ {
575
+ call_user_func($this->registered_streaming_write_callback, $curl_handle, $written_total);
576
+ }
577
+
578
  return $written_total;
579
  }
580
 
595
  curl_setopt($curl_handle, CURLOPT_SSL_VERIFYPEER, false);
596
  curl_setopt($curl_handle, CURLOPT_SSL_VERIFYHOST, true);
597
  curl_setopt($curl_handle, CURLOPT_CLOSEPOLICY, CURLCLOSEPOLICY_LEAST_RECENTLY_USED);
 
598
  curl_setopt($curl_handle, CURLOPT_MAXREDIRS, 5);
599
  curl_setopt($curl_handle, CURLOPT_HEADER, true);
600
  curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, true);
605
  curl_setopt($curl_handle, CURLOPT_USERAGENT, $this->useragent);
606
  curl_setopt($curl_handle, CURLOPT_READFUNCTION, array($this, 'streaming_read_callback'));
607
 
608
+ if (!ini_get('safe_mode'))
609
+ {
610
+ curl_setopt($curl_handle, CURLOPT_FOLLOWLOCATION, true);
611
+ }
612
+
613
  // Enable a proxy connection if requested.
614
  if ($this->proxy)
615
  {
app/libs/aws/sdk.class.php CHANGED
@@ -102,9 +102,9 @@ function __aws_sdk_ua_callback()
102
  // INTERMEDIARY CONSTANTS
103
 
104
  define('CFRUNTIME_NAME', 'aws-sdk-php');
105
- define('CFRUNTIME_VERSION', '1.2.5');
106
  // define('CFRUNTIME_BUILD', gmdate('YmdHis', filemtime(__FILE__))); // @todo: Hardcode for release.
107
- define('CFRUNTIME_BUILD', '20110224213746');
108
  define('CFRUNTIME_USERAGENT', CFRUNTIME_NAME . '/' . CFRUNTIME_VERSION . ' PHP/' . PHP_VERSION . ' ' . php_uname('s') . '/' . php_uname('r') . ' Arch/' . php_uname('m') . ' SAPI/' . php_sapi_name() . ' Integer/' . PHP_INT_MAX . ' Build/' . CFRUNTIME_BUILD . __aws_sdk_ua_callback());
109
 
110
 
@@ -115,7 +115,7 @@ define('CFRUNTIME_USERAGENT', CFRUNTIME_NAME . '/' . CFRUNTIME_VERSION . ' PHP/'
115
  * Core functionality and default settings shared across all SDK classes. All methods and properties in this
116
  * class are inherited by the service-specific classes.
117
  *
118
- * @version 2011.01.14
119
  * @license See the included NOTICE.md file for more information.
120
  * @copyright See the included NOTICE.md file for more information.
121
  * @link http://aws.amazon.com/php/ PHP Developer Center
@@ -304,6 +304,16 @@ class CFRuntime
304
  */
305
  public $max_retries = 3;
306
 
 
 
 
 
 
 
 
 
 
 
307
 
308
  /*%******************************************************************************************%*/
309
  // CONSTRUCTOR
@@ -578,6 +588,53 @@ class CFRuntime
578
  return $this;
579
  }
580
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
581
 
582
  /*%******************************************************************************************%*/
583
  // SET CUSTOM CLASSES
@@ -808,6 +865,17 @@ class CFRuntime
808
  $request->add_header('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8');
809
  $request->set_body($querystring);
810
 
 
 
 
 
 
 
 
 
 
 
 
811
  // Add authentication headers
812
  if ($signature_version === 3)
813
  {
102
  // INTERMEDIARY CONSTANTS
103
 
104
  define('CFRUNTIME_NAME', 'aws-sdk-php');
105
+ define('CFRUNTIME_VERSION', '1.2.6');
106
  // define('CFRUNTIME_BUILD', gmdate('YmdHis', filemtime(__FILE__))); // @todo: Hardcode for release.
107
+ define('CFRUNTIME_BUILD', '20110302071252');
108
  define('CFRUNTIME_USERAGENT', CFRUNTIME_NAME . '/' . CFRUNTIME_VERSION . ' PHP/' . PHP_VERSION . ' ' . php_uname('s') . '/' . php_uname('r') . ' Arch/' . php_uname('m') . ' SAPI/' . php_sapi_name() . ' Integer/' . PHP_INT_MAX . ' Build/' . CFRUNTIME_BUILD . __aws_sdk_ua_callback());
109
 
110
 
115
  * Core functionality and default settings shared across all SDK classes. All methods and properties in this
116
  * class are inherited by the service-specific classes.
117
  *
118
+ * @version 2011.03.01
119
  * @license See the included NOTICE.md file for more information.
120
  * @copyright See the included NOTICE.md file for more information.
121
  * @link http://aws.amazon.com/php/ PHP Developer Center
304
  */
305
  public $max_retries = 3;
306
 
307
+ /**
308
+ * The user-defined callback function to call when a stream is read from.
309
+ */
310
+ public $registered_streaming_read_callback = null;
311
+
312
+ /**
313
+ * The user-defined callback function to call when a stream is written to.
314
+ */
315
+ public $registered_streaming_write_callback = null;
316
+
317
 
318
  /*%******************************************************************************************%*/
319
  // CONSTRUCTOR
588
  return $this;
589
  }
590
 
591
+ /**
592
+ * Register a callback function to execute whenever a data stream is read from using
593
+ * <CFRequest::streaming_read_callback()>.
594
+ *
595
+ * The user-defined callback function should accept three arguments:
596
+ *
597
+ * <ul>
598
+ * <li><code>$curl_handle</code> - <code>resource</code> - Required - The cURL handle resource that represents the in-progress transfer.</li>
599
+ * <li><code>$file_handle</code> - <code>resource</code> - Required - The file handle resource that represents the file on the local file system.</li>
600
+ * <li><code>$length</code> - <code>integer</code> - Required - The length in kilobytes of the data chunk that was transferred.</li>
601
+ * </ul>
602
+ *
603
+ * @param string|array|function $callback (Required) The callback function is called by <php:call_user_func()>, so you can pass the following values: <ul>
604
+ * <li>The name of a global function to execute, passed as a string.</li>
605
+ * <li>A method to execute, passed as <code>array('ClassName', 'MethodName')</code>.</li>
606
+ * <li>An anonymous function (PHP 5.3+).</li></ul>
607
+ * @return $this A reference to the current instance.
608
+ */
609
+ public function register_streaming_read_callback($callback)
610
+ {
611
+ $this->registered_streaming_read_callback = $callback;
612
+ return $this;
613
+ }
614
+
615
+ /**
616
+ * Register a callback function to execute whenever a data stream is written to using
617
+ * <CFRequest::streaming_write_callback()>.
618
+ *
619
+ * The user-defined callback function should accept two arguments:
620
+ *
621
+ * <ul>
622
+ * <li><code>$curl_handle</code> - <code>resource</code> - Required - The cURL handle resource that represents the in-progress transfer.</li>
623
+ * <li><code>$length</code> - <code>integer</code> - Required - The length in kilobytes of the data chunk that was transferred.</li>
624
+ * </ul>
625
+ *
626
+ * @param string|array|function $callback (Required) The callback function is called by <php:call_user_func()>, so you can pass the following values: <ul>
627
+ * <li>The name of a global function to execute, passed as a string.</li>
628
+ * <li>A method to execute, passed as <code>array('ClassName', 'MethodName')</code>.</li>
629
+ * <li>An anonymous function (PHP 5.3+).</li></ul>
630
+ * @return $this A reference to the current instance.
631
+ */
632
+ public function register_streaming_write_callback($callback)
633
+ {
634
+ $this->registered_streaming_write_callback = $callback;
635
+ return $this;
636
+ }
637
+
638
 
639
  /*%******************************************************************************************%*/
640
  // SET CUSTOM CLASSES
865
  $request->add_header('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8');
866
  $request->set_body($querystring);
867
 
868
+ // Pass along registered stream callbacks
869
+ if ($this->registered_streaming_read_callback)
870
+ {
871
+ $request->register_streaming_read_callback($this->registered_streaming_read_callback);
872
+ }
873
+
874
+ if ($this->registered_streaming_write_callback)
875
+ {
876
+ $request->register_streaming_write_callback($this->registered_streaming_write_callback);
877
+ }
878
+
879
  // Add authentication headers
880
  if ($signature_version === 3)
881
  {
app/libs/aws/services/as.class.php CHANGED
@@ -47,7 +47,7 @@
47
  *
48
  * </ul>
49
  *
50
- * @version Thu Feb 24 12:15:58 PST 2011
51
  * @license See the included NOTICE.md file for complete information.
52
  * @copyright See the included NOTICE.md file for complete information.
53
  * @link http://aws.amazon.com/autoscaling/Amazon Auto-Scaling
@@ -84,6 +84,11 @@ class AmazonAS extends CFRuntime
84
  */
85
  const REGION_APAC_SE1 = 'autoscaling.ap-southeast-1.amazonaws.com';
86
 
 
 
 
 
 
87
 
88
  /*%******************************************************************************************%*/
89
  // SETTERS
47
  *
48
  * </ul>
49
  *
50
+ * @version Tue Mar 01 17:12:19 PST 2011
51
  * @license See the included NOTICE.md file for complete information.
52
  * @copyright See the included NOTICE.md file for complete information.
53
  * @link http://aws.amazon.com/autoscaling/Amazon Auto-Scaling
84
  */
85
  const REGION_APAC_SE1 = 'autoscaling.ap-southeast-1.amazonaws.com';
86
 
87
+ /**
88
+ * Specify the queue URL for the Asia Pacific (Japan) Region.
89
+ */
90
+ const REGION_APAC_NE1 = 'autoscaling.ap-northeast-1.amazonaws.com';
91
+
92
 
93
  /*%******************************************************************************************%*/
94
  // SETTERS
app/libs/aws/services/cloudformation.class.php CHANGED
@@ -33,7 +33,7 @@
33
  * Amazon CloudFormation makes use of other AWS products. If you need additional technical information about a specific AWS
34
  * product, you can find the product's technical documentation at http://aws.amazon.com/documentation/.
35
  *
36
- * @version Thu Feb 24 12:16:40 PST 2011
37
  * @license See the included NOTICE.md file for complete information.
38
  * @copyright See the included NOTICE.md file for complete information.
39
  * @link http://aws.amazon.com/cloudformation/Amazon CloudFormation
@@ -70,6 +70,11 @@ class AmazonCloudFormation extends CFRuntime
70
  */
71
  const REGION_APAC_SE1 = 'cloudformation.ap-southeast-1.amazonaws.com';
72
 
 
 
 
 
 
73
 
74
  /*%******************************************************************************************%*/
75
  // SETTERS
33
  * Amazon CloudFormation makes use of other AWS products. If you need additional technical information about a specific AWS
34
  * product, you can find the product's technical documentation at http://aws.amazon.com/documentation/.
35
  *
36
+ * @version Tue Mar 01 17:13:02 PST 2011
37
  * @license See the included NOTICE.md file for complete information.
38
  * @copyright See the included NOTICE.md file for complete information.
39
  * @link http://aws.amazon.com/cloudformation/Amazon CloudFormation
70
  */
71
  const REGION_APAC_SE1 = 'cloudformation.ap-southeast-1.amazonaws.com';
72
 
73
+ /**
74
+ * Specify the queue URL for the Asia Pacific (Japan) Region.
75
+ */
76
+ const REGION_APAC_NE1 = 'cloudformation.ap-northeast-1.amazonaws.com';
77
+
78
 
79
  /*%******************************************************************************************%*/
80
  // SETTERS
app/libs/aws/services/cloudfront.class.php CHANGED
@@ -197,6 +197,17 @@ class AmazonCloudFront extends CFRuntime
197
  $request->request_class = $this->request_class;
198
  $request->response_class = $this->response_class;
199
 
 
 
 
 
 
 
 
 
 
 
 
200
  // Generate required headers.
201
  $request->set_method($method);
202
  $canonical_date = gmdate($this->util->konst($this->util, 'DATE_FORMAT_RFC2616'));
197
  $request->request_class = $this->request_class;
198
  $request->response_class = $this->response_class;
199
 
200
+ // Pass along registered stream callbacks
201
+ if ($this->registered_streaming_read_callback)
202
+ {
203
+ $request->register_streaming_read_callback($this->registered_streaming_read_callback);
204
+ }
205
+
206
+ if ($this->registered_streaming_write_callback)
207
+ {
208
+ $request->register_streaming_write_callback($this->registered_streaming_write_callback);
209
+ }
210
+
211
  // Generate required headers.
212
  $request->set_method($method);
213
  $canonical_date = gmdate($this->util->konst($this->util, 'DATE_FORMAT_RFC2616'));
app/libs/aws/services/cloudwatch.class.php CHANGED
@@ -31,7 +31,7 @@
31
  * automatically make changes to the resources you are monitoring, based on rules that you define. For example, you can
32
  * create alarms that initiate Auto Scaling and Simple Notification Service actions on your behalf.
33
  *
34
- * @version Thu Feb 24 12:17:14 PST 2011
35
  * @license See the included NOTICE.md file for complete information.
36
  * @copyright See the included NOTICE.md file for complete information.
37
  * @link http://aws.amazon.com/cloudwatch/Amazon CloudWatch
@@ -68,6 +68,11 @@ class AmazonCloudWatch extends CFRuntime
68
  */
69
  const REGION_APAC_SE1 = 'ap-southeast-1';
70
 
 
 
 
 
 
71
 
72
  /*%******************************************************************************************%*/
73
  // SETTERS
31
  * automatically make changes to the resources you are monitoring, based on rules that you define. For example, you can
32
  * create alarms that initiate Auto Scaling and Simple Notification Service actions on your behalf.
33
  *
34
+ * @version Tue Mar 01 17:13:39 PST 2011
35
  * @license See the included NOTICE.md file for complete information.
36
  * @copyright See the included NOTICE.md file for complete information.
37
  * @link http://aws.amazon.com/cloudwatch/Amazon CloudWatch
68
  */
69
  const REGION_APAC_SE1 = 'ap-southeast-1';
70
 
71
+ /**
72
+ * Specify the queue URL for the Asia Pacific (Japan) Region.
73
+ */
74
+ const REGION_APAC_NE1 = 'ap-northeast-1';
75
+
76
 
77
  /*%******************************************************************************************%*/
78
  // SETTERS
app/libs/aws/services/ec2.class.php CHANGED
@@ -28,7 +28,7 @@
28
  *
29
  * Visit <a href="http://aws.amazon.com/ec2/">http://aws.amazon.com/ec2/</a> for more information.
30
  *
31
- * @version Thu Feb 24 12:18:39 PST 2011
32
  * @license See the included NOTICE.md file for complete information.
33
  * @copyright See the included NOTICE.md file for complete information.
34
  * @link http://aws.amazon.com/ec2/Amazon Elastic Compute Cloud
@@ -65,6 +65,11 @@ class AmazonEC2 extends CFRuntime
65
  */
66
  const REGION_APAC_SE1 = 'ap-southeast-1';
67
 
 
 
 
 
 
68
  /**
69
  * The "pending" state code of an EC2 instance. Useful for conditionals.
70
  */
28
  *
29
  * Visit <a href="http://aws.amazon.com/ec2/">http://aws.amazon.com/ec2/</a> for more information.
30
  *
31
+ * @version Tue Mar 01 17:14:56 PST 2011
32
  * @license See the included NOTICE.md file for complete information.
33
  * @copyright See the included NOTICE.md file for complete information.
34
  * @link http://aws.amazon.com/ec2/Amazon Elastic Compute Cloud
65
  */
66
  const REGION_APAC_SE1 = 'ap-southeast-1';
67
 
68
+ /**
69
+ * Specify the queue URL for the Asia Pacific (Japan) Region.
70
+ */
71
+ const REGION_APAC_NE1 = 'ap-northeast-1';
72
+
73
  /**
74
  * The "pending" state code of an EC2 instance. Useful for conditionals.
75
  */
app/libs/aws/services/elasticbeanstalk.class.php CHANGED
@@ -36,7 +36,7 @@
36
  *
37
  * </ul>
38
  *
39
- * @version Thu Feb 24 12:17:55 PST 2011
40
  * @license See the included NOTICE.md file for complete information.
41
  * @copyright See the included NOTICE.md file for complete information.
42
  * @link http://aws.amazon.com/elasticbeanstalk/AWS Elastic Beanstalk
36
  *
37
  * </ul>
38
  *
39
+ * @version Tue Mar 01 17:14:17 PST 2011
40
  * @license See the included NOTICE.md file for complete information.
41
  * @copyright See the included NOTICE.md file for complete information.
42
  * @link http://aws.amazon.com/elasticbeanstalk/AWS Elastic Beanstalk
app/libs/aws/services/elb.class.php CHANGED
@@ -20,7 +20,7 @@
20
  * of your application. It makes it easy for you to distribute application loads between two or more EC2 instances. Elastic
21
  * Load Balancing enables availability through redundancy and supports traffic growth of your application.
22
  *
23
- * @version Thu Feb 24 12:19:28 PST 2011
24
  * @license See the included NOTICE.md file for complete information.
25
  * @copyright See the included NOTICE.md file for complete information.
26
  * @link http://aws.amazon.com/elasticloadbalancing/Amazon Elastic Load Balancing
@@ -57,6 +57,11 @@ class AmazonELB extends CFRuntime
57
  */
58
  const REGION_APAC_SE1 = 'elasticloadbalancing.ap-southeast-1.amazonaws.com';
59
 
 
 
 
 
 
60
 
61
  /*%******************************************************************************************%*/
62
  // SETTERS
20
  * of your application. It makes it easy for you to distribute application loads between two or more EC2 instances. Elastic
21
  * Load Balancing enables availability through redundancy and supports traffic growth of your application.
22
  *
23
+ * @version Tue Mar 01 17:15:42 PST 2011
24
  * @license See the included NOTICE.md file for complete information.
25
  * @copyright See the included NOTICE.md file for complete information.
26
  * @link http://aws.amazon.com/elasticloadbalancing/Amazon Elastic Load Balancing
57
  */
58
  const REGION_APAC_SE1 = 'elasticloadbalancing.ap-southeast-1.amazonaws.com';
59
 
60
+ /**
61
+ * Specify the queue URL for the Asia Pacific (Japan) Region.
62
+ */
63
+ const REGION_APAC_NE1 = 'elasticloadbalancing.ap-northeast-1.amazonaws.com';
64
+
65
 
66
  /*%******************************************************************************************%*/
67
  // SETTERS
app/libs/aws/services/emr.class.php CHANGED
@@ -19,7 +19,7 @@
19
  * This is the Amazon Elastic MapReduce API Reference Guide. This guide is for programmers who need detailed information
20
  * about the Amazon Elastic MapReduce APIs.
21
  *
22
- * @version Thu Feb 24 12:21:27 PST 2011
23
  * @license See the included NOTICE.md file for complete information.
24
  * @copyright See the included NOTICE.md file for complete information.
25
  * @link http://aws.amazon.com/elasticmapreduce/Amazon Elastic MapReduce
@@ -56,6 +56,11 @@ class AmazonEMR extends CFRuntime
56
  */
57
  const REGION_APAC_SE1 = 'ap-southeast-1.elasticmapreduce.amazonaws.com';
58
 
 
 
 
 
 
59
 
60
  /*%******************************************************************************************%*/
61
  // SETTERS
19
  * This is the Amazon Elastic MapReduce API Reference Guide. This guide is for programmers who need detailed information
20
  * about the Amazon Elastic MapReduce APIs.
21
  *
22
+ * @version Tue Mar 01 17:16:53 PST 2011
23
  * @license See the included NOTICE.md file for complete information.
24
  * @copyright See the included NOTICE.md file for complete information.
25
  * @link http://aws.amazon.com/elasticmapreduce/Amazon Elastic MapReduce
56
  */
57
  const REGION_APAC_SE1 = 'ap-southeast-1.elasticmapreduce.amazonaws.com';
58
 
59
+ /**
60
+ * Specify the queue URL for the Asia Pacific (Japan) Region.
61
+ */
62
+ const REGION_APAC_NE1 = 'ap-northeast-1.elasticmapreduce.amazonaws.com';
63
+
64
 
65
  /*%******************************************************************************************%*/
66
  // SETTERS
app/libs/aws/services/iam.class.php CHANGED
@@ -44,7 +44,7 @@
44
  * We will refer to Amazon AWS Identity and Access Management using the abbreviated form IAM. All copyrights and legal
45
  * protections still apply.
46
  *
47
- * @version Thu Feb 24 12:22:01 PST 2011
48
  * @license See the included NOTICE.md file for complete information.
49
  * @copyright See the included NOTICE.md file for complete information.
50
  * @link http://aws.amazon.com/iam/Amazon Identity and Access Management Service
44
  * We will refer to Amazon AWS Identity and Access Management using the abbreviated form IAM. All copyrights and legal
45
  * protections still apply.
46
  *
47
+ * @version Tue Mar 01 17:17:30 PST 2011
48
  * @license See the included NOTICE.md file for complete information.
49
  * @copyright See the included NOTICE.md file for complete information.
50
  * @link http://aws.amazon.com/iam/Amazon Identity and Access Management Service
app/libs/aws/services/importexport.class.php CHANGED
@@ -22,7 +22,7 @@
22
  * high-speed internal network and bypassing the Internet. For large data sets, AWS Import/Export is often faster than
23
  * Internet transfer and more cost effective than upgrading your connectivity.
24
  *
25
- * @version Thu Feb 24 12:22:40 PST 2011
26
  * @license See the included NOTICE.md file for complete information.
27
  * @copyright See the included NOTICE.md file for complete information.
28
  * @link http://aws.amazon.com/importexport/Amazon Import/Export Service
22
  * high-speed internal network and bypassing the Internet. For large data sets, AWS Import/Export is often faster than
23
  * Internet transfer and more cost effective than upgrading your connectivity.
24
  *
25
+ * @version Tue Mar 01 17:18:09 PST 2011
26
  * @license See the included NOTICE.md file for complete information.
27
  * @copyright See the included NOTICE.md file for complete information.
28
  * @link http://aws.amazon.com/importexport/Amazon Import/Export Service
app/libs/aws/services/rds.class.php CHANGED
@@ -28,7 +28,7 @@
28
  * flexible: you can scale your database instance's compute resources and storage capacity to meet your application's
29
  * demand. As with all Amazon Web Services, there are no up-front investments, and you pay only for the resources you use.
30
  *
31
- * @version Thu Feb 24 12:23:23 PST 2011
32
  * @license See the included NOTICE.md file for complete information.
33
  * @copyright See the included NOTICE.md file for complete information.
34
  * @link http://aws.amazon.com/rds/Amazon Relational Database Service
@@ -65,6 +65,11 @@ class AmazonRDS extends CFRuntime
65
  */
66
  const REGION_APAC_SE1 = 'rds.ap-southeast-1.amazonaws.com';
67
 
 
 
 
 
 
68
 
69
  /*%******************************************************************************************%*/
70
  // SETTERS
28
  * flexible: you can scale your database instance's compute resources and storage capacity to meet your application's
29
  * demand. As with all Amazon Web Services, there are no up-front investments, and you pay only for the resources you use.
30
  *
31
+ * @version Tue Mar 01 17:18:44 PST 2011
32
  * @license See the included NOTICE.md file for complete information.
33
  * @copyright See the included NOTICE.md file for complete information.
34
  * @link http://aws.amazon.com/rds/Amazon Relational Database Service
65
  */
66
  const REGION_APAC_SE1 = 'rds.ap-southeast-1.amazonaws.com';
67
 
68
+ /**
69
+ * Specify the queue URL for the Asia Pacific (Japan) Region.
70
+ */
71
+ const REGION_APAC_NE1 = 'rds.ap-northeast-1.amazonaws.com';
72
+
73
 
74
  /*%******************************************************************************************%*/
75
  // SETTERS
app/libs/aws/services/s3.class.php CHANGED
@@ -49,7 +49,7 @@ class S3_Exception extends Exception {}
49
  *
50
  * Visit <http://aws.amazon.com/s3/> for more information.
51
  *
52
- * @version 2011.02.16
53
  * @license See the included NOTICE.md file for more information.
54
  * @copyright See the included NOTICE.md file for more information.
55
  * @link http://aws.amazon.com/s3/ Amazon Simple Storage Service
@@ -85,6 +85,11 @@ class AmazonS3 extends CFRuntime
85
  */
86
  const REGION_APAC_SE1 = 'ap-southeast-1';
87
 
 
 
 
 
 
88
  /**
89
  * ACL: Owner-only read/write.
90
  */
@@ -470,6 +475,17 @@ class AmazonS3 extends CFRuntime
470
  $request->request_class = $this->request_class;
471
  $request->response_class = $this->response_class;
472
 
 
 
 
 
 
 
 
 
 
 
 
473
  // Streaming uploads
474
  if (isset($opt['fileUpload']))
475
  {
@@ -805,16 +821,15 @@ class AmazonS3 extends CFRuntime
805
  * Sets the region to use for subsequent Amazon S3 operations. This will also reset any prior use of
806
  * <enable_path_style()>.
807
  *
808
- * @param string $region (Required) The region to use for subsequent Amazon S3 operations. [Allowed values: `AmazonS3::REGION_US_E1 `, `AmazonS3::REGION_US_W1`, `AmazonS3::REGION_EU_W1`, `AmazonS3::REGION_APAC_SE1`]
809
  * @return $this A reference to the current instance.
810
  */
811
  public function set_region($region)
812
  {
813
  switch ($region)
814
  {
815
- case self::REGION_US_W1: // Northern California
816
- case self::REGION_APAC_SE1: // Singapore
817
- $this->set_hostname('s3-' . $region . '.amazonaws.com');
818
  $this->enable_path_style(false);
819
  break;
820
 
@@ -823,9 +838,11 @@ class AmazonS3 extends CFRuntime
823
  $this->enable_path_style(); // Always use path-style access for EU endpoint.
824
  break;
825
 
 
 
 
826
  default:
827
- // REGION_US_E1 // Northern Virginia
828
- $this->set_hostname(self::DEFAULT_URL);
829
  $this->enable_path_style(false);
830
  break;
831
  }
@@ -870,7 +887,7 @@ class AmazonS3 extends CFRuntime
870
  * However, bucket names must be unique across all of Amazon S3.
871
  *
872
  * @param string $bucket (Required) The name of the bucket to create.
873
- * @param string $region (Required) The preferred geographical location for the bucket. [Allowed values: `AmazonS3::REGION_US_E1 `, `AmazonS3::REGION_US_W1`, `AmazonS3::REGION_EU_W1`, `AmazonS3::REGION_APAC_SE1`]
874
  * @param string $acl (Optional) The ACL settings for the specified bucket. [Allowed values: <code>AmazonS3::ACL_PRIVATE</code>, <code>AmazonS3::ACL_PUBLIC</code>, <code>AmazonS3::ACL_OPEN</code>, <code>AmazonS3::ACL_AUTH_READ</code>, <code>AmazonS3::ACL_OWNER_READ</code>, <code>AmazonS3::ACL_OWNER_FULL_CONTROL</code>]. The default value is <ACL_PRIVATE>.
875
  * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
876
  * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request.</li></ul>
@@ -908,10 +925,8 @@ class AmazonS3 extends CFRuntime
908
 
909
  switch ($region)
910
  {
911
- case self::REGION_US_W1: // Northern California
912
- case self::REGION_APAC_SE1: // Singapore
913
- $xml->LocationConstraint = $region;
914
- $opt['body'] = $xml->asXML();
915
  break;
916
 
917
  case self::REGION_EU_W1: // Ireland
@@ -920,8 +935,12 @@ class AmazonS3 extends CFRuntime
920
  $opt['body'] = $xml->asXML();
921
  break;
922
 
923
- default: // REGION_US_E1 // Northern Virginia
924
- $opt['body'] = '';
 
 
 
 
925
  break;
926
  }
927
 
49
  *
50
  * Visit <http://aws.amazon.com/s3/> for more information.
51
  *
52
+ * @version 2011.03.01
53
  * @license See the included NOTICE.md file for more information.
54
  * @copyright See the included NOTICE.md file for more information.
55
  * @link http://aws.amazon.com/s3/ Amazon Simple Storage Service
85
  */
86
  const REGION_APAC_SE1 = 'ap-southeast-1';
87
 
88
+ /**
89
+ * Specify the queue URL for the Asia Pacific (Japan) Region.
90
+ */
91
+ const REGION_APAC_NE1 = 'ap-northeast-1';
92
+
93
  /**
94
  * ACL: Owner-only read/write.
95
  */
475
  $request->request_class = $this->request_class;
476
  $request->response_class = $this->response_class;
477
 
478
+ // Pass along registered stream callbacks
479
+ if ($this->registered_streaming_read_callback)
480
+ {
481
+ $request->register_streaming_read_callback($this->registered_streaming_read_callback);
482
+ }
483
+
484
+ if ($this->registered_streaming_write_callback)
485
+ {
486
+ $request->register_streaming_write_callback($this->registered_streaming_write_callback);
487
+ }
488
+
489
  // Streaming uploads
490
  if (isset($opt['fileUpload']))
491
  {
821
  * Sets the region to use for subsequent Amazon S3 operations. This will also reset any prior use of
822
  * <enable_path_style()>.
823
  *
824
+ * @param string $region (Required) The region to use for subsequent Amazon S3 operations. [Allowed values: `AmazonS3::REGION_US_E1 `, `AmazonS3::REGION_US_W1`, `AmazonS3::REGION_EU_W1`, `AmazonS3::REGION_APAC_SE1`, `AmazonS3::REGION_APAC_NE1`]
825
  * @return $this A reference to the current instance.
826
  */
827
  public function set_region($region)
828
  {
829
  switch ($region)
830
  {
831
+ case self::REGION_US_E1: // Northern Virginia
832
+ $this->set_hostname(self::DEFAULT_URL);
 
833
  $this->enable_path_style(false);
834
  break;
835
 
838
  $this->enable_path_style(); // Always use path-style access for EU endpoint.
839
  break;
840
 
841
+ case self::REGION_US_W1: // Northern California
842
+ case self::REGION_APAC_SE1: // Singapore
843
+ case self::REGION_APAC_NE1: // Japan
844
  default:
845
+ $this->set_hostname('s3-' . $region . '.amazonaws.com');
 
846
  $this->enable_path_style(false);
847
  break;
848
  }
887
  * However, bucket names must be unique across all of Amazon S3.
888
  *
889
  * @param string $bucket (Required) The name of the bucket to create.
890
+ * @param string $region (Required) The preferred geographical location for the bucket. [Allowed values: `AmazonS3::REGION_US_E1 `, `AmazonS3::REGION_US_W1`, `AmazonS3::REGION_EU_W1`, `AmazonS3::REGION_APAC_SE1`, `AmazonS3::REGION_APAC_NE1`]
891
  * @param string $acl (Optional) The ACL settings for the specified bucket. [Allowed values: <code>AmazonS3::ACL_PRIVATE</code>, <code>AmazonS3::ACL_PUBLIC</code>, <code>AmazonS3::ACL_OPEN</code>, <code>AmazonS3::ACL_AUTH_READ</code>, <code>AmazonS3::ACL_OWNER_READ</code>, <code>AmazonS3::ACL_OWNER_FULL_CONTROL</code>]. The default value is <ACL_PRIVATE>.
892
  * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
893
  * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request.</li></ul>
925
 
926
  switch ($region)
927
  {
928
+ case self::REGION_US_E1: // Northern Virginia
929
+ $opt['body'] = '';
 
 
930
  break;
931
 
932
  case self::REGION_EU_W1: // Ireland
935
  $opt['body'] = $xml->asXML();
936
  break;
937
 
938
+ case self::REGION_US_W1: // Northern California
939
+ case self::REGION_APAC_SE1: // Singapore
940
+ case self::REGION_APAC_NE1: // Japan
941
+ default:
942
+ $xml->LocationConstraint = $region;
943
+ $opt['body'] = $xml->asXML();
944
  break;
945
  }
946
 
app/libs/aws/services/sdb.class.php CHANGED
@@ -31,7 +31,7 @@
31
  *
32
  * Visit <a href="http://aws.amazon.com/simpledb/">http://aws.amazon.com/simpledb/</a> for more information.
33
  *
34
- * @version Thu Feb 24 12:24:00 PST 2011
35
  * @license See the included NOTICE.md file for complete information.
36
  * @copyright See the included NOTICE.md file for complete information.
37
  * @link http://aws.amazon.com/simpledb/Amazon SimpleDB
@@ -68,6 +68,11 @@ class AmazonSDB extends CFRuntime
68
  */
69
  const REGION_APAC_SE1 = 'sdb.ap-southeast-1.amazonaws.com';
70
 
 
 
 
 
 
71
 
72
  /*%******************************************************************************************%*/
73
  // SETTERS
31
  *
32
  * Visit <a href="http://aws.amazon.com/simpledb/">http://aws.amazon.com/simpledb/</a> for more information.
33
  *
34
+ * @version Tue Mar 01 17:19:23 PST 2011
35
  * @license See the included NOTICE.md file for complete information.
36
  * @copyright See the included NOTICE.md file for complete information.
37
  * @link http://aws.amazon.com/simpledb/Amazon SimpleDB
68
  */
69
  const REGION_APAC_SE1 = 'sdb.ap-southeast-1.amazonaws.com';
70
 
71
+ /**
72
+ * Specify the queue URL for the Asia Pacific (Japan) Region.
73
+ */
74
+ const REGION_APAC_NE1 = 'sdb.ap-northeast-1.amazonaws.com';
75
+
76
 
77
  /*%******************************************************************************************%*/
78
  // SETTERS
app/libs/aws/services/ses.class.php CHANGED
@@ -23,7 +23,7 @@
23
  * For specific details on how to construct a service request, please consult the <a
24
  * href="http://docs.amazonwebservices.com/ses/latest/DeveloperGuide">Amazon SES Developer Guide</a>.
25
  *
26
- * @version Thu Feb 24 12:20:37 PST 2011
27
  * @license See the included NOTICE.md file for complete information.
28
  * @copyright See the included NOTICE.md file for complete information.
29
  * @link http://aws.amazon.com/ses/Amazon Simple Email Service
23
  * For specific details on how to construct a service request, please consult the <a
24
  * href="http://docs.amazonwebservices.com/ses/latest/DeveloperGuide">Amazon SES Developer Guide</a>.
25
  *
26
+ * @version Tue Mar 01 17:16:20 PST 2011
27
  * @license See the included NOTICE.md file for complete information.
28
  * @copyright See the included NOTICE.md file for complete information.
29
  * @link http://aws.amazon.com/ses/Amazon Simple Email Service
app/libs/aws/services/sns.class.php CHANGED
@@ -17,7 +17,7 @@
17
  /**
18
 
19
  *
20
- * @version Thu Feb 24 12:24:35 PST 2011
21
  * @license See the included NOTICE.md file for complete information.
22
  * @copyright See the included NOTICE.md file for complete information.
23
  * @link http://aws.amazon.com/sns/Amazon Simple Notification Service
@@ -30,51 +30,44 @@ class AmazonSNS extends CFRuntime
30
  // CLASS CONSTANTS
31
 
32
  /**
33
- * Constant: DEFAULT_URL
34
- * Specify the default queue URL.
35
  */
36
  const DEFAULT_URL = 'sns.us-east-1.amazonaws.com';
37
 
38
  /**
39
- * Constant: REGION_US_E1
40
- * Specify the queue URL for the US-East (Northern Virginia) Region.
41
  */
42
  const REGION_US_E1 = self::DEFAULT_URL;
43
 
44
  /**
45
- * Constant: REGION_US_W1
46
- * Specify the queue URL for the US-West (Northern California) Region.
47
  */
48
  const REGION_US_W1 = 'sns.us-west-1.amazonaws.com';
49
 
50
  /**
51
- * Constant: REGION_EU_W1
52
- * Specify the queue URL for the EU (Ireland) Region.
53
  */
54
  const REGION_EU_W1 = 'sns.eu-west-1.amazonaws.com';
55
 
56
  /**
57
- * Constant: REGION_APAC_SE1
58
- * Specify the queue URL for the Asia Pacific (Singapore) Region.
59
  */
60
  const REGION_APAC_SE1 = 'sns.ap-southeast-1.amazonaws.com';
61
 
 
 
 
 
 
62
 
63
  /*%******************************************************************************************%*/
64
  // SETTERS
65
 
66
  /**
67
- * Method: set_region()
68
- * This allows you to explicitly sets the region for the service to use.
69
- *
70
- * Access:
71
- * public
72
- *
73
- * Parameters:
74
- * $region - _string_ (Required) The region to explicitly set. Available options are <REGION_US_E1>, <REGION_US_W1>, <REGION_EU_W1>, or <REGION_APAC_SE1>.
75
  *
76
- * Returns:
77
- * `$this`
78
  */
79
  public function set_region($region)
80
  {
@@ -87,20 +80,11 @@ class AmazonSNS extends CFRuntime
87
  // CONVENIENCE METHODS
88
 
89
  /**
90
- * Method: get_topic_list()
91
- * Gets a simple list of Topic ARNs.
92
  *
93
- * Access:
94
- * public
95
- *
96
- * Parameters:
97
- * $pcre - _string_ (Optional) A Perl-Compatible Regular Expression (PCRE) to filter the names against.
98
- *
99
- * Returns:
100
- * _array_ A list of Topic ARNs.
101
- *
102
- * See Also:
103
- * [Perl-Compatible Regular Expression (PCRE) Docs](http://php.net/pcre)
104
  */
105
  public function get_topic_list($pcre = null)
106
  {
@@ -125,18 +109,11 @@ class AmazonSNS extends CFRuntime
125
  // CONSTRUCTOR
126
 
127
  /**
128
- * Method: __construct()
129
- * Constructs a new instance of <AmazonSNS>.
130
- *
131
- * Access:
132
- * public
133
- *
134
- * Parameters:
135
- * $key - _string_ (Optional) Your Amazon API Key. If blank, it will look for the <AWS_KEY> constant.
136
- * $secret_key - _string_ (Optional) Your Amazon API Secret Key. If blank, it will look for the <AWS_SECRET_KEY> constant.
137
  *
138
- * Returns:
139
- * _boolean_ false if no valid values are set, otherwise true.
 
140
  */
141
  public function __construct($key = null, $secret_key = null)
142
  {
@@ -438,7 +415,6 @@ class AmazonSNS extends CFRuntime
438
  // EXCEPTIONS
439
 
440
  /**
441
- * Exception: SNS_Exception
442
- * Default SNS Exception.
443
  */
444
  class SNS_Exception extends Exception {}
17
  /**
18
 
19
  *
20
+ * @version Tue Mar 01 17:20:00 PST 2011
21
  * @license See the included NOTICE.md file for complete information.
22
  * @copyright See the included NOTICE.md file for complete information.
23
  * @link http://aws.amazon.com/sns/Amazon Simple Notification Service
30
  // CLASS CONSTANTS
31
 
32
  /**
33
+ * Specify the default queue URL.
 
34
  */
35
  const DEFAULT_URL = 'sns.us-east-1.amazonaws.com';
36
 
37
  /**
38
+ * Specify the queue URL for the US-East (Northern Virginia) Region.
 
39
  */
40
  const REGION_US_E1 = self::DEFAULT_URL;
41
 
42
  /**
43
+ * Specify the queue URL for the US-West (Northern California) Region.
 
44
  */
45
  const REGION_US_W1 = 'sns.us-west-1.amazonaws.com';
46
 
47
  /**
48
+ * Specify the queue URL for the EU (Ireland) Region.
 
49
  */
50
  const REGION_EU_W1 = 'sns.eu-west-1.amazonaws.com';
51
 
52
  /**
53
+ * Specify the queue URL for the Asia Pacific (Singapore) Region.
 
54
  */
55
  const REGION_APAC_SE1 = 'sns.ap-southeast-1.amazonaws.com';
56
 
57
+ /**
58
+ * Specify the queue URL for the Asia Pacific (Japan) Region.
59
+ */
60
+ const REGION_APAC_NE1 = 'sns.ap-northeast-1.amazonaws.com';
61
+
62
 
63
  /*%******************************************************************************************%*/
64
  // SETTERS
65
 
66
  /**
67
+ * This allows you to explicitly sets the region for the service to use.
 
 
 
 
 
 
 
68
  *
69
+ * @param string $region (Required) The region to use for subsequent Amazon S3 operations. [Allowed values: `AmazonSNS::REGION_US_E1 `, `AmazonSNS::REGION_US_W1`, `AmazonSNS::REGION_EU_W1`, `AmazonSNS::REGION_APAC_SE1`]
70
+ * @return $this A reference to the current instance.
71
  */
72
  public function set_region($region)
73
  {
80
  // CONVENIENCE METHODS
81
 
82
  /**
83
+ * Gets a simple list of Topic ARNs.
 
84
  *
85
+ * @param string $pcre (Optional) A Perl-Compatible Regular Expression (PCRE) to filter the names against.
86
+ * @return array A list of Topic ARNs.
87
+ * @link http://php.net/pcre Perl-Compatible Regular Expression (PCRE) Docs
 
 
 
 
 
 
 
 
88
  */
89
  public function get_topic_list($pcre = null)
90
  {
109
  // CONSTRUCTOR
110
 
111
  /**
112
+ * Constructs a new instance of <AmazonSNS>.
 
 
 
 
 
 
 
 
113
  *
114
+ * @param string $key (Optional) Your Amazon API Key. If blank, it will look for the `AWS_KEY` constant.
115
+ * @param string $secret_key (Optional) Your Amazon API Secret Key. If blank, it will look for the `AWS_SECRET_KEY` constant.
116
+ * @return boolean <code>false</code> if no valid values are set, otherwise <code>true</code>.
117
  */
118
  public function __construct($key = null, $secret_key = null)
119
  {
415
  // EXCEPTIONS
416
 
417
  /**
418
+ * Default SNS Exception.
 
419
  */
420
  class SNS_Exception extends Exception {}
app/libs/aws/services/sqs.class.php CHANGED
@@ -30,7 +30,7 @@
30
  *
31
  * Visit <a href="http://aws.amazon.com/sqs/">http://aws.amazon.com/sqs/</a> for more information.
32
  *
33
- * @version Thu Feb 24 12:25:08 PST 2011
34
  * @license See the included NOTICE.md file for complete information.
35
  * @copyright See the included NOTICE.md file for complete information.
36
  * @link http://aws.amazon.com/sqs/Amazon Simple Queue Service
@@ -43,51 +43,44 @@ class AmazonSQS extends CFRuntime
43
  // CLASS CONSTANTS
44
 
45
  /**
46
- * Constant: DEFAULT_URL
47
- * Specify the default queue URL.
48
  */
49
  const DEFAULT_URL = 'sqs.us-east-1.amazonaws.com';
50
 
51
  /**
52
- * Constant: REGION_US_E1
53
- * Specify the queue URL for the US-East (Northern Virginia) Region.
54
  */
55
  const REGION_US_E1 = self::DEFAULT_URL;
56
 
57
  /**
58
- * Constant: REGION_US_W1
59
- * Specify the queue URL for the US-West (Northern California) Region.
60
  */
61
  const REGION_US_W1 = 'sqs.us-west-1.amazonaws.com';
62
 
63
  /**
64
- * Constant: REGION_EU_W1
65
- * Specify the queue URL for the EU (Ireland) Region.
66
  */
67
  const REGION_EU_W1 = 'sqs.eu-west-1.amazonaws.com';
68
 
69
  /**
70
- * Constant: REGION_APAC_SE1
71
- * Specify the queue URL for the Asia Pacific (Singapore) Region.
72
  */
73
  const REGION_APAC_SE1 = 'sqs.ap-southeast-1.amazonaws.com';
74
 
 
 
 
 
 
75
 
76
  /*%******************************************************************************************%*/
77
  // SETTERS
78
 
79
  /**
80
- * Method: set_region()
81
- * This allows you to explicitly sets the region for the service to use.
82
- *
83
- * Access:
84
- * public
85
  *
86
- * Parameters:
87
- * $region - _string_ (Required) The region to explicitly set. Available options are <REGION_US_E1>, <REGION_US_W1>, <REGION_EU_W1>, or <REGION_APAC_SE1>.
88
- *
89
- * Returns:
90
- * `$this`
91
  */
92
  public function set_region($region)
93
  {
@@ -100,17 +93,10 @@ class AmazonSQS extends CFRuntime
100
  // CONVENIENCE METHODS
101
 
102
  /**
103
- * Method: get_queue_arn()
104
- * Converts a queue URI into a queue ARN.
105
- *
106
- * Access:
107
- * public
108
- *
109
- * Parameters:
110
- * $queue_url - _string_ (Required) The queue URL to perform the action on. Retrieved when the queue is first created.
111
  *
112
- * Returns:
113
- * _string_ An ARN representation of the queue URI.
114
  */
115
  function get_queue_arn($queue_url)
116
  {
@@ -122,17 +108,10 @@ class AmazonSQS extends CFRuntime
122
  }
123
 
124
  /**
125
- * Method: get_queue_size()
126
- * Returns the approximate number of messages in the queue.
127
  *
128
- * Access:
129
- * public
130
- *
131
- * Parameters:
132
- * $queue_url - _string_ (Required) The queue URL to perform the action on. Retrieved when the queue is first created.
133
- *
134
- * Returns:
135
- * _mixed_ The Approximate number of messages in the queue as an integer. If the queue doesn't exist, it returns the entire <CFResponse> object.
136
  */
137
  public function get_queue_size($queue_url)
138
  {
@@ -149,20 +128,11 @@ class AmazonSQS extends CFRuntime
149
  }
150
 
151
  /**
152
- * Method: get_queue_list()
153
- * ONLY lists the queue URLs, as an array, on the SQS account.
154
- *
155
- * Access:
156
- * public
157
- *
158
- * Parameters:
159
- * $pcre - _string_ (Optional) A Perl-Compatible Regular Expression (PCRE) to filter the names against.
160
  *
161
- * Returns:
162
- * _array_ The list of matching queue names. If there are no results, the method will return an empty array.
163
- *
164
- * See Also:
165
- * [Perl-Compatible Regular Expression (PCRE) Docs](http://php.net/pcre)
166
  */
167
  public function get_queue_list($pcre = null)
168
  {
@@ -187,18 +157,11 @@ class AmazonSQS extends CFRuntime
187
  // CONSTRUCTOR
188
 
189
  /**
190
- * Method: __construct()
191
- * Constructs a new instance of <AmazonSQS>.
192
- *
193
- * Access:
194
- * public
195
- *
196
- * Parameters:
197
- * $key - _string_ (Optional) Your Amazon API Key. If blank, it will look for the <AWS_KEY> constant.
198
- * $secret_key - _string_ (Optional) Your Amazon API Secret Key. If blank, it will look for the <AWS_SECRET_KEY> constant.
199
  *
200
- * Returns:
201
- * _boolean_ false if no valid values are set, otherwise true.
 
202
  */
203
  public function __construct($key = null, $secret_key = null)
204
  {
@@ -498,7 +461,6 @@ class AmazonSQS extends CFRuntime
498
  // EXCEPTIONS
499
 
500
  /**
501
- * Exception: SQS_Exception
502
- * Default SQS Exception.
503
  */
504
  class SQS_Exception extends Exception {}
30
  *
31
  * Visit <a href="http://aws.amazon.com/sqs/">http://aws.amazon.com/sqs/</a> for more information.
32
  *
33
+ * @version Tue Mar 01 17:20:35 PST 2011
34
  * @license See the included NOTICE.md file for complete information.
35
  * @copyright See the included NOTICE.md file for complete information.
36
  * @link http://aws.amazon.com/sqs/Amazon Simple Queue Service
43
  // CLASS CONSTANTS
44
 
45
  /**
46
+ * Specify the default queue URL.
 
47
  */
48
  const DEFAULT_URL = 'sqs.us-east-1.amazonaws.com';
49
 
50
  /**
51
+ * Specify the queue URL for the US-East (Northern Virginia) Region.
 
52
  */
53
  const REGION_US_E1 = self::DEFAULT_URL;
54
 
55
  /**
56
+ * Specify the queue URL for the US-West (Northern California) Region.
 
57
  */
58
  const REGION_US_W1 = 'sqs.us-west-1.amazonaws.com';
59
 
60
  /**
61
+ * Specify the queue URL for the EU (Ireland) Region.
 
62
  */
63
  const REGION_EU_W1 = 'sqs.eu-west-1.amazonaws.com';
64
 
65
  /**
66
+ * Specify the queue URL for the Asia Pacific (Singapore) Region.
 
67
  */
68
  const REGION_APAC_SE1 = 'sqs.ap-southeast-1.amazonaws.com';
69
 
70
+ /**
71
+ * Specify the queue URL for the Asia Pacific (Japan) Region.
72
+ */
73
+ const REGION_APAC_NE1 = 'sqs.ap-northeast-1.amazonaws.com';
74
+
75
 
76
  /*%******************************************************************************************%*/
77
  // SETTERS
78
 
79
  /**
80
+ * This allows you to explicitly sets the region for the service to use.
 
 
 
 
81
  *
82
+ * @param string $region (Required) The region to use for subsequent Amazon S3 operations. [Allowed values: `AmazonSQS::REGION_US_E1 `, `AmazonSQS::REGION_US_W1`, `AmazonSQS::REGION_EU_W1`, `AmazonSQS::REGION_APAC_SE1`]
83
+ * @return $this A reference to the current instance.
 
 
 
84
  */
85
  public function set_region($region)
86
  {
93
  // CONVENIENCE METHODS
94
 
95
  /**
96
+ * Converts a queue URI into a queue ARN.
 
 
 
 
 
 
 
97
  *
98
+ * @param string $queue_url (Required) The queue URL to perform the action on. Retrieved when the queue is first created.
99
+ * @return string An ARN representation of the queue URI.
100
  */
101
  function get_queue_arn($queue_url)
102
  {
108
  }
109
 
110
  /**
111
+ * Returns the approximate number of messages in the queue.
 
112
  *
113
+ * @param string $queue_url (Required) The queue URL to perform the action on. Retrieved when the queue is first created.
114
+ * @return mixed The Approximate number of messages in the queue as an integer. If the queue doesn't exist, it returns the entire <CFResponse> object.
 
 
 
 
 
 
115
  */
116
  public function get_queue_size($queue_url)
117
  {
128
  }
129
 
130
  /**
131
+ * ONLY lists the queue URLs, as an array, on the SQS account.
 
 
 
 
 
 
 
132
  *
133
+ * @param string $pcre (Optional) A Perl-Compatible Regular Expression (PCRE) to filter the names against.
134
+ * @return array The list of matching queue names. If there are no results, the method will return an empty array.
135
+ * @link http://php.net/pcre Perl-Compatible Regular Expression (PCRE) Docs
 
 
136
  */
137
  public function get_queue_list($pcre = null)
138
  {
157
  // CONSTRUCTOR
158
 
159
  /**
160
+ * Constructs a new instance of <AmazonSQS>.
 
 
 
 
 
 
 
 
161
  *
162
+ * @param string $key (Optional) Your Amazon API Key. If blank, it will look for the `AWS_KEY` constant.
163
+ * @param string $secret_key (Optional) Your Amazon API Secret Key. If blank, it will look for the `AWS_SECRET_KEY` constant.
164
+ * @return boolean <code>false</code> if no valid values are set, otherwise <code>true</code>.
165
  */
166
  public function __construct($key = null, $secret_key = null)
167
  {
461
  // EXCEPTIONS
462
 
463
  /**
464
+ * Default SQS Exception.
 
465
  */
466
  class SQS_Exception extends Exception {}
app/list-tables.php CHANGED
@@ -469,6 +469,8 @@ class BackWPup_Backups_Table extends WP_List_Table {
469
  $r .= "<td $attributes><strong>".basename($backup['file'])."</strong><br />ftp://".$jobvalue['ftphost'].dirname($backup['file'])."/";
470
  } elseif ($backup['type']=='RSC') {
471
  $r .= "<td $attributes><strong>".basename($backup['file'])."</strong><br />RSC://".$jobvalue['rscContainer']."/".dirname($backup['file'])."/";
 
 
472
  }
473
  $actions = array();
474
  $actions['delete'] = "<a class=\"submitdelete\" href=\"" . wp_nonce_url('admin.php?page=BackWPup&subpage=backups&action=delete&paged='.$this->get_pagenum().'&backupfiles[]='.esc_attr($backup['file'].':'.$backup['jobid'].':'.$backup['type']), 'bulk-backups') . "\" onclick=\"if ( confirm('" . esc_js(__("You are about to delete this Backup Archive. \n 'Cancel' to stop, 'OK' to delete.","backwpup")) . "') ) { return true;}return false;\">" . __('Delete') . "</a>";
469
  $r .= "<td $attributes><strong>".basename($backup['file'])."</strong><br />ftp://".$jobvalue['ftphost'].dirname($backup['file'])."/";
470
  } elseif ($backup['type']=='RSC') {
471
  $r .= "<td $attributes><strong>".basename($backup['file'])."</strong><br />RSC://".$jobvalue['rscContainer']."/".dirname($backup['file'])."/";
472
+ } elseif ($backup['type']=='MSAZURE') {
473
+ $r .= "<td $attributes><strong>".basename($backup['file'])."</strong><br />azure://".$jobvalue['msazureContainer']."/".dirname($backup['file'])."/";
474
  }
475
  $actions = array();
476
  $actions['delete'] = "<a class=\"submitdelete\" href=\"" . wp_nonce_url('admin.php?page=BackWPup&subpage=backups&action=delete&paged='.$this->get_pagenum().'&backupfiles[]='.esc_attr($backup['file'].':'.$backup['jobid'].':'.$backup['type']), 'bulk-backups') . "\" onclick=\"if ( confirm('" . esc_js(__("You are about to delete this Backup Archive. \n 'Cancel' to stop, 'OK' to delete.","backwpup")) . "') ) { return true;}return false;\">" . __('Delete') . "</a>";
app/options-edit-job.php CHANGED
@@ -367,7 +367,7 @@ $dests=explode(',',strtoupper(BACKWPUP_DESTS));
367
  <b><?PHP _e('Bucket:','backwpup'); ?></b><br />
368
  <input id="awsBucketselected" name="awsBucketselected" type="hidden" value="<?PHP echo $jobvalue['awsBucket'];?>" />
369
  <?PHP if (!empty($jobvalue['awsAccessKey']) and !empty($jobvalue['awsSecretKey'])) backwpup_get_aws_buckets(array('awsAccessKey'=>$jobvalue['awsAccessKey'],'awsSecretKey'=>$jobvalue['awsSecretKey'],'awsselected'=>$jobvalue['awsBucket'])); ?>
370
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<?PHP _e('Create Bucket:','backwpup'); ?><input name="newawsBucket" type="text" value="" class="text" /> <select name="awsRegion" title="<?php _e('Bucket Region', 'backwpup'); ?>"><option value=""><?php _e('US-East (Northern Virginia)', 'backwpup'); ?></option><option value="us-west-1"><?php _e('US-West (Northern California)', 'backwpup'); ?></option><option value="EU"><?php _e('EU (Ireland)', 'backwpup'); ?></option><option value="ap-southeast-1"><?php _e('Asia Pacific (Singapore)', 'backwpup'); ?></option></select><br />
371
  <b><?PHP _e('Directory in Bucket:','backwpup'); ?></b><br />
372
  <input name="awsdir" type="text" value="<?PHP echo $jobvalue['awsdir'];?>" class="large-text" /><br />
373
  <?PHP _e('Max. Backup Files in Bucket Folder:','backwpup'); ?><input name="awsmaxbackups" type="text" size="3" value="<?PHP echo $jobvalue['awsmaxbackups'];?>" class="small-text" /><span class="description"><?PHP _e('(Oldest files will deleted first.)','backwpup');?></span><br />
@@ -376,6 +376,31 @@ $dests=explode(',',strtoupper(BACKWPUP_DESTS));
376
  </div>
377
  </div>
378
  <?PHP } ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
379
 
380
  <?PHP if (in_array('RSC',$dests)) { ?>
381
  <div id="torsc" class="postbox" <?PHP if (!in_array("FILE",$todo) and !in_array("DB",$todo) and !in_array("WPEXP",$todo)) echo 'style="display:none;"';?>>
@@ -401,7 +426,7 @@ $dests=explode(',',strtoupper(BACKWPUP_DESTS));
401
  <?PHP } ?>
402
 
403
  <?PHP if (in_array('DROPBOX',$dests)) { ?>
404
- <div id="toftp" class="postbox" <?PHP if (!in_array("FILE",$todo) and !in_array("DB",$todo) and !in_array("WPEXP",$todo)) echo 'style="display:none;"';?>>
405
  <h3 class="hndle"><span><?PHP _e('Backup to Dropbox','backwpup'); ?></span></h3>
406
  <div class="inside">
407
  <b><?PHP _e('Email:','backwpup'); ?></b><br />
367
  <b><?PHP _e('Bucket:','backwpup'); ?></b><br />
368
  <input id="awsBucketselected" name="awsBucketselected" type="hidden" value="<?PHP echo $jobvalue['awsBucket'];?>" />
369
  <?PHP if (!empty($jobvalue['awsAccessKey']) and !empty($jobvalue['awsSecretKey'])) backwpup_get_aws_buckets(array('awsAccessKey'=>$jobvalue['awsAccessKey'],'awsSecretKey'=>$jobvalue['awsSecretKey'],'awsselected'=>$jobvalue['awsBucket'])); ?>
370
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<?PHP _e('Create Bucket:','backwpup'); ?><input name="newawsBucket" type="text" value="" class="text" /> <select name="awsRegion" title="<?php _e('Bucket Region', 'backwpup'); ?>"><option value=""><?php _e('US-East (Northern Virginia)', 'backwpup'); ?></option><option value="us-west-1"><?php _e('US-West (Northern California)', 'backwpup'); ?></option><option value="EU"><?php _e('EU (Ireland)', 'backwpup'); ?></option><option value="ap-southeast-1"><?php _e('Asia Pacific (Singapore)', 'backwpup'); ?></option><option value="ap-northeast-1"><?php _e('Asia Pacific (Japan)', 'backwpup'); ?></option></select><br />
371
  <b><?PHP _e('Directory in Bucket:','backwpup'); ?></b><br />
372
  <input name="awsdir" type="text" value="<?PHP echo $jobvalue['awsdir'];?>" class="large-text" /><br />
373
  <?PHP _e('Max. Backup Files in Bucket Folder:','backwpup'); ?><input name="awsmaxbackups" type="text" size="3" value="<?PHP echo $jobvalue['awsmaxbackups'];?>" class="small-text" /><span class="description"><?PHP _e('(Oldest files will deleted first.)','backwpup');?></span><br />
376
  </div>
377
  </div>
378
  <?PHP } ?>
379
+
380
+ <?PHP if (in_array('MSAZURE',$dests)) { ?>
381
+ <div id="tomsazure" class="postbox" <?PHP if (!in_array("FILE",$todo) and !in_array("DB",$todo) and !in_array("WPEXP",$todo)) echo 'style="display:none;"';?>>
382
+ <h3 class="hndle"><span><?PHP _e('Backup to Micosoft Azure (Blob)','backwpup'); ?></span></h3>
383
+ <div class="inside">
384
+ <?PHP if (!(extension_loaded('curl') or @dl(PHP_SHLIB_SUFFIX == 'so' ? 'curl.so' : 'php_curl.dll'))) {
385
+ echo "<b>".__('curl Support required','backwpup')."</b>";
386
+ } else { ?>
387
+ <b><?PHP _e('Host:','backwpup'); ?></b><br />
388
+ <input id="msazureHost" name="msazureHost" type="text" value="<?PHP echo $jobvalue['msazureHost'];?>" class="large-text" /><span class="description"><?PHP _e('Normely: blob.core.windows.net','backwpup');?></span><br />
389
+ <b><?PHP _e('Account Name:','backwpup'); ?></b><br />
390
+ <input id="msazureAccName" name="msazureAccName" type="text" value="<?PHP echo $jobvalue['msazureAccName'];?>" class="large-text" /><br />
391
+ <b><?PHP _e('Access Key:','backwpup'); ?></b><br />
392
+ <input id="msazureKey" name="msazureKey" type="password" value="<?PHP echo $jobvalue['msazureKey'];?>" class="large-text" /><br />
393
+ <b><?PHP _e('Container:','backwpup'); ?></b><br />
394
+ <input id="msazureContainerselected" name="msazureContainerselected" type="hidden" value="<?PHP echo $jobvalue['msazureContainer'];?>" />
395
+ <?PHP if (!empty($jobvalue['msazureAccName']) and !empty($jobvalue['msazureKey'])) backwpup_get_msazure_container(array('msazureHost'=>$jobvalue['msazureHost'],'msazureAccName'=>$jobvalue['msazureAccName'],'msazureKey'=>$jobvalue['msazureKey'],'msazureselected'=>$jobvalue['msazureContainer'])); ?>
396
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<?PHP _e('Create Container:','backwpup'); ?><input name="newmsazureContainer" type="text" value="" class="text" /> <br />
397
+ <b><?PHP _e('Directory in Container:','backwpup'); ?></b><br />
398
+ <input name="msazuredir" type="text" value="<?PHP echo $jobvalue['msazuredir'];?>" class="large-text" /><br />
399
+ <?PHP _e('Max. Backup Files in Container Folder:','backwpup'); ?><input name="msazuremaxbackups" type="text" size="3" value="<?PHP echo $jobvalue['msazuremaxbackups'];?>" class="small-text" /><span class="description"><?PHP _e('(Oldest files will deleted first.)','backwpup');?></span><br />
400
+ <?PHP } ?>
401
+ </div>
402
+ </div>
403
+ <?PHP } ?>
404
 
405
  <?PHP if (in_array('RSC',$dests)) { ?>
406
  <div id="torsc" class="postbox" <?PHP if (!in_array("FILE",$todo) and !in_array("DB",$todo) and !in_array("WPEXP",$todo)) echo 'style="display:none;"';?>>
426
  <?PHP } ?>
427
 
428
  <?PHP if (in_array('DROPBOX',$dests)) { ?>
429
+ <div id="todropbox" class="postbox" <?PHP if (!in_array("FILE",$todo) and !in_array("DB",$todo) and !in_array("WPEXP",$todo)) echo 'style="display:none;"';?>>
430
  <h3 class="hndle"><span><?PHP _e('Backup to Dropbox','backwpup'); ?></span></h3>
431
  <div class="inside">
432
  <b><?PHP _e('Email:','backwpup'); ?></b><br />
app/options-save.php CHANGED
@@ -156,10 +156,13 @@ function backwpup_backups_operations($action) {
156
 
157
  $jobs=get_option('backwpup_jobs'); //Load jobs
158
  if (extension_loaded('curl') or @dl(PHP_SHLIB_SUFFIX == 'so' ? 'curl.so' : 'php_curl.dll')) {
159
- if (!class_exists('CFRuntime'))
160
- require_once(dirname(__FILE__).'/libs/aws/sdk.class.php');
161
- if (!class_exists('CF_Authentication'))
162
- require_once(plugin_dir_path(__FILE__).'libs/rackspace/cloudfiles.php');
 
 
 
163
  }
164
 
165
  $num=0;
@@ -175,6 +178,13 @@ function backwpup_backups_operations($action) {
175
  $s3->delete_object($jobvalue['awsBucket'],$backups['file']);
176
  }
177
  }
 
 
 
 
 
 
 
178
  } elseif ($backups['type']=='RSC') {
179
  if (class_exists('CF_Authentication')) {
180
  if (!empty($jobvalue['rscUsername']) and !empty($jobvalue['rscAPIKey']) and !empty($jobvalue['rscContainer'])) {
@@ -265,6 +275,29 @@ function backwpup_backups_operations($action) {
265
  header('HTTP/1.0 '.$s3file->status.' Not Found');
266
  die();
267
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
268
  break;
269
  case 'downloadrsc': //Download RSC Backup
270
  check_admin_referer('download-backup');
@@ -425,6 +458,12 @@ function backwpup_save_job() { //Save Job settings
425
  $jobs[$jobid]['awsBucket']=$_POST['awsBucket'];
426
  $jobs[$jobid]['awsdir']=stripslashes($_POST['awsdir']);
427
  $jobs[$jobid]['awsmaxbackups']=(int)$_POST['awsmaxbackups'];
 
 
 
 
 
 
428
  $jobs[$jobid]['rscUsername']=$_POST['rscUsername'];
429
  $jobs[$jobid]['rscAPIKey']=$_POST['rscAPIKey'];
430
  $jobs[$jobid]['rscContainer']=$_POST['rscContainer'];
@@ -442,11 +481,30 @@ function backwpup_save_job() { //Save Job settings
442
  if (!empty($_POST['newawsBucket']) and !empty($_POST['awsAccessKey']) and !empty($_POST['awsSecretKey'])) { //create new s3 bucket if needed
443
  if (!class_exists('CFRuntime'))
444
  require_once(dirname(__FILE__).'/libs/aws/sdk.class.php');
445
- $s3 = new AmazonS3($_POST['awsAccessKey'], $_POST['awsSecretKey']);
446
- $s3->create_bucket($_POST['newawsBucket'], $_POST['awsRegion']);
447
- $jobs[$jobid]['awsBucket']=$_POST['newawsBucket'];
 
 
 
 
448
  }
449
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
450
  if (!empty($_POST['rscUsername']) and !empty($_POST['rscAPIKey']) and !empty($_POST['newrscContainer'])) { //create new Rackspase Container if needed
451
  if (!class_exists('CF_Authentication'))
452
  require_once(plugin_dir_path(__FILE__).'libs/rackspace/cloudfiles.php');
156
 
157
  $jobs=get_option('backwpup_jobs'); //Load jobs
158
  if (extension_loaded('curl') or @dl(PHP_SHLIB_SUFFIX == 'so' ? 'curl.so' : 'php_curl.dll')) {
159
+ set_include_path(get_include_path().PATH_SEPARATOR.dirname(__FILE__).'/libs');
160
+ if (!class_exists('Microsoft_WindowsAzure_Storage_Blob'))
161
+ require_once 'Microsoft/WindowsAzure/Storage/Blob.php';
162
+ if (!class_exists('CFRuntime'))
163
+ require_once(dirname(__FILE__).'/libs/aws/sdk.class.php');
164
+ if (!class_exists('CF_Authentication'))
165
+ require_once(plugin_dir_path(__FILE__).'libs/rackspace/cloudfiles.php');
166
  }
167
 
168
  $num=0;
178
  $s3->delete_object($jobvalue['awsBucket'],$backups['file']);
179
  }
180
  }
181
+ } elseif ($backups['type']=='MSAZURE') {
182
+ if (class_exists('Microsoft_WindowsAzure_Storage_Blob')) {
183
+ if (!empty($jobvalue['msazureHost']) and !empty($jobvalue['msazureAccName']) and !empty($jobvalue['msazureKey']) and !empty($jobvalue['msazureContainer'])) {
184
+ $storageClient = new Microsoft_WindowsAzure_Storage_Blob($jobvalue['msazureHost'],$jobvalue['msazureAccName'],$jobvalue['msazureKey']);
185
+ $storageClient->deleteBlob($jobvalue['msazureContainer'],$backups['file']);
186
+ }
187
+ }
188
  } elseif ($backups['type']=='RSC') {
189
  if (class_exists('CF_Authentication')) {
190
  if (!empty($jobvalue['rscUsername']) and !empty($jobvalue['rscAPIKey']) and !empty($jobvalue['rscContainer'])) {
275
  header('HTTP/1.0 '.$s3file->status.' Not Found');
276
  die();
277
  }
278
+ break;
279
+ case 'downloadmsazure': //Download Microsoft Azure Backup
280
+ check_admin_referer('download-backup');
281
+ set_include_path(get_include_path().PATH_SEPARATOR.dirname(__FILE__).'/libs');
282
+ if (!class_exists('Microsoft_WindowsAzure_Storage_Blob'))
283
+ require_once 'Microsoft/WindowsAzure/Storage/Blob.php';
284
+ $jobs=get_option('backwpup_jobs');
285
+ $jobid=$_GET['jobid'];
286
+ $storageClient = new Microsoft_WindowsAzure_Storage_Blob($jobs[$jobid]['msazureHost'],$jobs[$jobid]['msazureAccName'],$jobs[$jobid]['msazureKey']);
287
+
288
+ header("Pragma: public");
289
+ header("Expires: 0");
290
+ header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
291
+ //header("Content-Type: ".$s3file->header->_info->content_type);
292
+ header("Content-Type: application/force-download");
293
+ header("Content-Type: application/octet-stream");
294
+ header("Content-Type: application/download");
295
+ header("Content-Disposition: attachment; filename=".basename($_GET['file']).";");
296
+ header("Content-Transfer-Encoding: binary");
297
+ //header("Content-Length: ".$s3file->header->_info->size_download);
298
+ echo $storageClient->getBlobData($jobs[$jobid]['msazureContainer'], $_GET['file']);
299
+ die();
300
+
301
  break;
302
  case 'downloadrsc': //Download RSC Backup
303
  check_admin_referer('download-backup');
458
  $jobs[$jobid]['awsBucket']=$_POST['awsBucket'];
459
  $jobs[$jobid]['awsdir']=stripslashes($_POST['awsdir']);
460
  $jobs[$jobid]['awsmaxbackups']=(int)$_POST['awsmaxbackups'];
461
+ $jobs[$jobid]['msazureHost']=$_POST['msazureHost'];
462
+ $jobs[$jobid]['msazureAccName']=$_POST['msazureAccName'];
463
+ $jobs[$jobid]['msazureKey']=$_POST['msazureKey'];
464
+ $jobs[$jobid]['msazureContainer']=$_POST['msazureContainer'];
465
+ $jobs[$jobid]['msazuredir']=stripslashes($_POST['msazuredir']);
466
+ $jobs[$jobid]['msazuremaxbackups']=(int)$_POST['msazuremaxbackups'];
467
  $jobs[$jobid]['rscUsername']=$_POST['rscUsername'];
468
  $jobs[$jobid]['rscAPIKey']=$_POST['rscAPIKey'];
469
  $jobs[$jobid]['rscContainer']=$_POST['rscContainer'];
481
  if (!empty($_POST['newawsBucket']) and !empty($_POST['awsAccessKey']) and !empty($_POST['awsSecretKey'])) { //create new s3 bucket if needed
482
  if (!class_exists('CFRuntime'))
483
  require_once(dirname(__FILE__).'/libs/aws/sdk.class.php');
484
+ try {
485
+ $s3 = new AmazonS3($_POST['awsAccessKey'], $_POST['awsSecretKey']);
486
+ $s3->create_bucket($_POST['newawsBucket'], $_POST['awsRegion']);
487
+ $jobs[$jobid]['awsBucket']=$_POST['newawsBucket'];
488
+ } catch (Exception $e) {
489
+ $backwpup_message=__($e->getMessage(),'backwpup');
490
+ }
491
  }
492
 
493
+ if (!empty($_POST['newmsazureContainer']) and !empty($_POST['msazureHost']) and !empty($_POST['msazureAccName']) and !empty($_POST['msazureKey'])) { //create new s3 bucket if needed
494
+ if (!class_exists('Microsoft_WindowsAzure_Storage_Blob')) {
495
+ set_include_path(get_include_path().PATH_SEPARATOR.dirname(__FILE__).'/libs');
496
+ require_once 'Microsoft/WindowsAzure/Storage/Blob.php';
497
+ }
498
+ try {
499
+ $storageClient = new Microsoft_WindowsAzure_Storage_Blob($_POST['msazureHost'],$_POST['msazureAccName'],$_POST['msazureKey']);
500
+ $result = $storageClient->createContainer($_POST['newmsazureContainer']);
501
+ $jobs[$jobid]['msazureContainer']=$result->Name;
502
+ } catch (Exception $e) {
503
+ $backwpup_message=__($e->getMessage(),'backwpup');
504
+ }
505
+ }
506
+
507
+
508
  if (!empty($_POST['rscUsername']) and !empty($_POST['rscAPIKey']) and !empty($_POST['newrscContainer'])) { //create new Rackspase Container if needed
509
  if (!class_exists('CF_Authentication'))
510
  require_once(plugin_dir_path(__FILE__).'libs/rackspace/cloudfiles.php');
backwpup.php CHANGED
@@ -4,7 +4,7 @@ Plugin Name: BackWPup
4
  Plugin URI: http://danielhuesken.de/portfolio/backwpup/
5
  Description: Backup and more of your WordPress Blog Database and Files.
6
  Author: Daniel H&uuml;sken
7
- Version: 1.5.2
8
  Author URI: http://danielhuesken.de
9
  Text Domain: backwpup
10
  Domain Path: /lang/
@@ -34,12 +34,12 @@ if ( !defined('ABSPATH') )
34
  //Set plugin dirname
35
  define('BACKWPUP_PLUGIN_BASEDIR', dirname(plugin_basename(__FILE__)));
36
  //Set Plugin Version
37
- define('BACKWPUP_VERSION', '1.5.2');
38
  //Set User Capability
39
  define('BACKWPUP_USER_CAPABILITY', 'export');
40
  //Set useable destinations
41
  if (!defined('BACKWPUP_DESTS'))
42
- define('BACKWPUP_DESTS', 'S3,RSC,FTP,DROPBOX');
43
  //load Text Domain
44
  load_plugin_textdomain('backwpup', false, BACKWPUP_PLUGIN_BASEDIR.'/lang');
45
  //Load functions file
@@ -67,6 +67,7 @@ if (backwpup_env_checks()) {
67
  // add ajax function
68
  add_action('wp_ajax_backwpup_get_aws_buckets', 'backwpup_get_aws_buckets');
69
  add_action('wp_ajax_backwpup_get_rsc_container', 'backwpup_get_rsc_container');
 
70
  //Disabele WP_Corn
71
  $cfg=get_option('backwpup');
72
  if ($cfg['disablewpcron'])
4
  Plugin URI: http://danielhuesken.de/portfolio/backwpup/
5
  Description: Backup and more of your WordPress Blog Database and Files.
6
  Author: Daniel H&uuml;sken
7
+ Version: 1.5.5
8
  Author URI: http://danielhuesken.de
9
  Text Domain: backwpup
10
  Domain Path: /lang/
34
  //Set plugin dirname
35
  define('BACKWPUP_PLUGIN_BASEDIR', dirname(plugin_basename(__FILE__)));
36
  //Set Plugin Version
37
+ define('BACKWPUP_VERSION', '1.5.5');
38
  //Set User Capability
39
  define('BACKWPUP_USER_CAPABILITY', 'export');
40
  //Set useable destinations
41
  if (!defined('BACKWPUP_DESTS'))
42
+ define('BACKWPUP_DESTS', 'S3,RSC,FTP,DROPBOX,MSAZURE');
43
  //load Text Domain
44
  load_plugin_textdomain('backwpup', false, BACKWPUP_PLUGIN_BASEDIR.'/lang');
45
  //Load functions file
67
  // add ajax function
68
  add_action('wp_ajax_backwpup_get_aws_buckets', 'backwpup_get_aws_buckets');
69
  add_action('wp_ajax_backwpup_get_rsc_container', 'backwpup_get_rsc_container');
70
+ add_action('wp_ajax_backwpup_get_msazure_container', 'backwpup_get_msazure_container');
71
  //Disabele WP_Corn
72
  $cfg=get_option('backwpup');
73
  if ($cfg['disablewpcron'])
readme.txt CHANGED
@@ -1,10 +1,10 @@
1
  === BackWPup ===
2
  Contributors: danielhuesken, zlli
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=daniel%40huesken-net%2ede&item_name=Daniel%20Huesken%20Plugin%20Donation&item_number=BackWPup&no_shipping=0&no_note=1&tax=0&currency_code=EUR&lc=DE&bn=PP%2dDonationsBF&charset=UTF%2d8
4
- Tags: backup, admin, file, Database, mysql, cron, ftp, S3, export, xml, Rackspase, cloud, webdav, dropbox
5
  Requires at least: 2.8
6
  Tested up to: 3.1.0
7
- Stable tag: 1.5.2
8
 
9
  Backup and more of your WordPress Blog Database and Files
10
 
@@ -21,6 +21,7 @@ Backup and more your Blog.
21
  * Store backup to Folder
22
  * Store backup to FTP Server
23
  * Store backup to Amazon S3
 
24
  * Store backup to RackSpaceCloud
25
  * Store backup to DropBox
26
  * Send Log/Backup by eMail
@@ -92,12 +93,19 @@ Destinations are:
92
  * RSC = RackSpaceCloud
93
  * FTP = FTP Server
94
  * DROPBOX = Dropbox
 
95
 
96
  == Screenshots ==
97
 
98
  1. Job Page
99
 
100
  == Changelog ==
 
 
 
 
 
 
101
  = 1.5.2 =
102
  * changes for user checking
103
  * removed Plugin init action
1
  === BackWPup ===
2
  Contributors: danielhuesken, zlli
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=daniel%40huesken-net%2ede&item_name=Daniel%20Huesken%20Plugin%20Donation&item_number=BackWPup&no_shipping=0&no_note=1&tax=0&currency_code=EUR&lc=DE&bn=PP%2dDonationsBF&charset=UTF%2d8
4
+ Tags: backup, admin, file, Database, mysql, cron, ftp, S3, export, xml, Rackspase, cloud, azure, dropbox
5
  Requires at least: 2.8
6
  Tested up to: 3.1.0
7
+ Stable tag: 1.5.5
8
 
9
  Backup and more of your WordPress Blog Database and Files
10
 
21
  * Store backup to Folder
22
  * Store backup to FTP Server
23
  * Store backup to Amazon S3
24
+ * Store backup to Microsoft Azure (Blob)
25
  * Store backup to RackSpaceCloud
26
  * Store backup to DropBox
27
  * Send Log/Backup by eMail
93
  * RSC = RackSpaceCloud
94
  * FTP = FTP Server
95
  * DROPBOX = Dropbox
96
+ * MSAZURE = Microsoft Azure (Blob)
97
 
98
  == Screenshots ==
99
 
100
  1. Job Page
101
 
102
  == Changelog ==
103
+ = 1.5.5 =
104
+ * Updatet AWS SDK to ver.1.2.6 for Amazon S3
105
+ * Added AWS Regin "Northeast" (Japan)
106
+ * Added Microsoft Azure (Blob) as backup destination
107
+ * bug fixes
108
+
109
  = 1.5.2 =
110
  * changes for user checking
111
  * removed Plugin init action