+++ /dev/null
-<?php
-/*
- (c) Hallo Welt! Medienwerkstatt GmbH, 2011 GPL
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- http://www.gnu.org/copyleft/gpl.html
-*/
-
-if ( !defined( 'MEDIAWIKI' ) ) {
- echo 'To install WindowsAzureStorage, put the following line in LocalSettings.php: include_once( "$IP/extensions/WindowsAzureStorage/WindowsAzureStorage.php" );'."\n";
- exit( 1 );
-}
-
-$wgExtensionCredits['other'][] = array(
- 'path' => __FILE__,
- 'name' => 'WindowsAzureStorage',
- 'author' => array( 'Hallo Welt! Medienwerkstatt GmbH' ),
- 'url' => 'http://www.hallowelt.biz',
- 'version' => '1.0.0',
- 'descriptionmsg' => 'windowsazurestorage-desc',
-);
-
-$dir = dirname(__FILE__) . '/';
-$wgExtensionMessagesFiles['WindowsAzureStorage'] = $dir . 'WindowsAzureStorage.i18n.php';
-
-$wgAutoloadClasses['WindowsAzureFileBackend'] = $dir . 'includes/filerepo/backend/WindowsAzureFileBackend.php';
-
-/* Those are just development values. You may override them or specify your own backend definition in LocalSettings.php */
-$wgFileBackends[] = array(
- 'name' => 'azure-backend',
- 'class' => 'WindowsAzureFileBackend',
- //'wikiId' => 'some_unique_ID',
- 'lockManager' => 'nullLockManager',
- 'azureHost' => 'http://127.0.0.1:10000',
- 'azureAccount' => 'devstoreaccount1',
- 'azureKey' => 'Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==',
- //'azureContainer' => 'developcontainer',
-
- //IMPORTANT: Mind the container naming conventions! http://msdn.microsoft.com/en-us/library/dd135715.aspx
- 'containerPaths' => array(
- 'media-public' => 'media-public',
- 'media-thumb' => 'media-thumb',
- 'media-deleted' => 'media-deleted',
- 'media-temp' => 'media-temp',
-
- )
-);
\ No newline at end of file
+++ /dev/null
-<?php
-/**
- * @file
- * @ingroup FileBackend
- * @author Markus Glaser
- * @author Robert Vogel
- * @author Hallo Welt! - Medienwerkstatt GmbH for Microsoft Corp.
- */
-
-/**
- * Copied and modified from Swift FileBackend:
- *
- * Class for a Windows Azure Blob Storage based file backend.
- * Status messages should avoid mentioning the Azure account name
- * Likewise, error suppression should be used to avoid path disclosure.
- *
- * This requires the PHPAzure library to be present,
- * which is available at http://phpazure.codeplex.com/.
- * All of the library classes must be registed in $wgAutoloadClasses.
- * You may use the WindowsAzureSDK MediaWiki extension to fulfill this
- * requirement.
- *
- * @ingroup FileBackend
- */
-class WindowsAzureFileBackend extends FileBackend {
-
- function doStore( array $p ) {
- return $this->doStoreInternal( $p );
- }
-
- function doCopy( array $p ) {
- return $this->doCopyInternal( $p );
- }
-
- function doDelete( array $p ) {
- return $this->doDeleteInternal( $p );
- }
-
- function doConcatenate( array $p ) {
- return $this->dodoConcatenateInternal( $p );
- }
-
- function doCreate( array $p ) {
- return $this->doCreateInternal( $p );
- }
-
- /**
- * @see FileBackend::move()
- */
- protected function doMove( array $params ) {
- // Copy source to dest
- // TODO: Remove backend. I assume, this function does not need to be overridden.
- $status = $this->backend->copy( $params );
- if ( !$status->isOK() ) {
- return $status;
- }
- // Delete source (only fails due to races or medium going down)
- // TODO: Remoce backend
- $status->merge( $this->backend->delete( array( 'src' => $params['src'] ) ) );
- $status->setResult( true, $status->value ); // ignore delete() errors
- return $status;
- }
-
- /** @var Microsoft_WindowsAzure_Storage_Blob */
- protected $storageClient = null;
-
- /** @var Array Map of container names to Azure container names */
- protected $containerPaths = array();
-
- /**
- * @see FileBackend::__construct()
- * Additional $config params include:
- * azureHost : Windows Azure server URL
- * azureAccount : Windows Azure user used by MediaWiki
- * azureKey : Authentication key for the above user (used to get sessions)
- * //azureContainer : Identifier of the container. (Optional. If not provided wikiId will be used as container name)
- * containerPaths : Map of container names to Azure container names
- */
- public function __construct( array $config ) {
- parent::__construct( $config );
- $this->storageClient = new Microsoft_WindowsAzure_Storage_Blob(
- $config['azureHost'],
- $config['azureAccount'],
- $config['azureKey']
- );
-
- $this->containerPaths = (array)$config['containerPaths'];
- }
-
- /**
- * @see FileBackend::resolveContainerPath()
- */
- protected function resolveContainerPath( $container, $relStoragePath ) {
- //Azure container naming conventions; http://msdn.microsoft.com/en-us/library/dd135715.aspx
-
- if ( strlen( urlencode( $relStoragePath ) ) > 1024 ) {
- return null;
- }
- // TODO: Should storagepath not be urlencoded?
- return $relStoragePath;
- }
-
- /**
- * @see FileBackend::doStoreInternal()
- */
- function doStoreInternal( array $params ) {
- $status = Status::newGood();
- // TODO: Use more telling names
- list( $c, $dir ) = $this->resolveStoragePath( $params['dst'] );
- try {
- $result = $this->storageClient->putBlob( $c, $dir, $params['src']);
- }
- catch ( Exception $e ) {
- // TODO: Read exception. Are there different ones?
- $status->fatal( 'backend-fail-put' );
- }
- //error_log( __METHOD__.'::putBlob - result: '.print_r( $result, true ) );
- return $status;
- }
-
- /**
- * @see FileBackend::doCopyInternal()
- */
- function doCopyInternal( array $params ) {
- $status = Status::newGood();
- list( $srcContainer, $srcDir ) = $this->resolveStoragePath( $params['src'] );
- list( $dstContainer, $dstDir ) = $this->resolveStoragePath( $params['dst'] );
- // TODO: check for null
- try {
- $result = $this->storageClient->copyBlob( $srcContainer, $srcDir, $dstContainer, $dstDir);
- }
- catch ( Exception $e ) {
- $status->fatal( 'backend-fail-copy', $e->getMessage() );
- }
- //error_log( __METHOD__.'::copyBlob - result: '.print_r( $result, true ) );
- return $status;
- }
-
- /**
- * @see FileBackend::doDeleteInternal()
- */
- function doDeleteInternal( array $params ) {
- $status = Status::newGood();
-
- list( $srcCont, $srcRel ) = $this->resolveStoragePath( $params['src'] );
- if ( $srcRel === null ) {
- $status->fatal( 'backend-fail-invalidpath', $params['src'] );
- return $status;
- }
-
- // (a) Check the source container
- try { //TODO: Unnecessary --> remove
- $container = $this->storageClient->getContainer( $srcCont );
- }
- catch ( Exception $e ) {
- // TODO: remove error_log
- error_log( __METHOD__.':'.__LINE__.' '.$e->getMessage() );
- $status->fatal( 'backend-fail-internal' );
- return $status;
- }
-
- // (b) Actually delete the object
- try {
- $this->storageClient->deleteBlob( $srcCont, $srcRel );
- }
- catch ( Exception $e ) {
- error_log( __METHOD__.':'.__LINE__.' '.$e->getMessage() );
- $status->fatal( 'backend-fail-internal' );
- }
-
- return $status;
- }
-
- /**
- * @see FileBackend::doCreateInternal()
- */
- function doCreateInternal( array $params ) {
- $status = Status::newGood();
-
- list( $dstCont, $dstRel ) = $this->resolveStoragePath( $params['dst'] );
- if ( $dstRel === null ) {
- $status->fatal( 'backend-fail-invalidpath', $params['dst'] );
- return $status;
- }
-
- // (a) Check if the destination object already exists
- $blobExists = $this->storageClient->blobExists( $dstCont, $dstRel );
- if ( $blobExists && empty( $params['overwriteDest'] ) ) { //Blob exists _and_ should not be overridden
- $status->fatal( 'backend-fail-alreadyexists', $params['dst'] );
- return $status;
- }
-
- // (b) Actually create the object
- try {
- // TODO: how do I know the container exists? Should we call prepare?
- $this->storageClient->putBlobData( $dstCont, $dstRel, $params['content'] );
- }
- catch ( Exception $e ) {
- error_log( __METHOD__.':'.__LINE__.' '.$e->getMessage() );
- $status->fatal( 'backend-fail-internal' );
- }
-
- return $status;
- }
-
- /**
- * @see FileBackend::prepare()
- */
- function prepare( array $params ) {
- $status = Status::newGood();
-
- list( $c, $dir ) = $this->resolveStoragePath( $params['dir'] );
- if ( $dir === null ) {
- $status->fatal( 'backend-fail-invalidpath', $params['dir'] );
- return $status; // invalid storage path
- }
- try {
- $this->storageClient->createContainerIfNotExists( $c );
- $this->storageClient->setContainerAcl( $c, Microsoft_WindowsAzure_Storage_Blob::ACL_PUBLIC );//TODO: Really set public?
-
- //TODO: check if readable and writeable
- //$container = $this->storageClient->getContainer( $c );
- //$status->fatal( 'directoryreadonlyerror', $params['dir'] );
- //$status->fatal( 'directorynotreadableerror', $params['dir'] );
- }
- catch (Exception $e ) {
- $status->fatal( 'directorycreateerror', $params['dir'] );
- return $status;
- }
- return $status;
- }
-
- /**
- * @see FileBackend::resolveContainerName()
- */
- protected function resolveContainerName( $container ) {
- //Azure container naming conventions; http://msdn.microsoft.com/en-us/library/dd135715.aspx
- $container = strtolower($container);
- $container = preg_replace( '#[^a-z0-9\-]#', '', $container );
- // TODO: -test und test- geht auch nicht
- $container = preg_replace( '#-{2,}#', '-', $container );
-
- return $container;
- }
-
- /**
- * @see FileBackend::secure()
- */
- function secure( array $params ) {
- $status = Status::newGood();
- // @TODO: restrict container from $this->swiftProxyUser
- return $status; // badgers? We don't need no steenking badgers!
- }
-
- /**
- * @see FileBackend::fileExists()
- */
- function fileExists( array $params ) {
- list( $c, $dir ) = $this->resolveStoragePath( $params['src'] );
- // TODO: null? Telling names
- $exists = $this->storageClient->blobExists( $c, $dir );
- //error_log( __METHOD__.'::blobExists - result: '.$exists );
- return $exists;
- }
-
- /**
- * @see FileBackend::getFileTimestamp()
- */
- function getFileTimestamp( array $params ) {
- list( $srcCont, $srcRel ) = $this->resolveStoragePath( $params['src'] );
- if ( $srcRel === null ) {
- return false; // invalid storage path
- }
-
- $timestamp= false;
- try {
- //TODO Maybe use getBlobData()?
- $blob = $this->storageClient->getBlobInstance( $srcCont, $srcRel );
- $timestamp = wfTimestamp( TS_MW, $blob->lastmodified ); //TODO: Timezone?
- } catch ( Exception $e ) { // some other exception?
- error_log( __METHOD__.':'.__LINE__.' '.$e->getMessage() );
- }
- return $timestamp;
- }
-
- /**
- * @see FileBackend::getFileList()
- */
- function getFileList( array $params ) {
- $files = array();
- list( $c, $dir ) = $this->resolveStoragePath( $params['dir'] );
- try {
- if ( $dir === null ) {
- $blobs = $this->storageClient->listBlobs($c);
- }
- else {
- $blobs = $this->storageClient->listBlobs( $c, $dir );//TODO:Check if $dir really is a startsequence of the blob name
- }
- foreach( $blobs as $blob ) {
- $files[] = $blob->name;
- }
- }
- catch( Exception $e ) {
- error_log( __METHOD__.':'.__LINE__.' '.$e->getMessage() );
- return null;
- }
-
- // if there are no files matching the prefix, return empty array
- return $files;
- }
-
- /**
- * @see FileBackend::getLocalCopy()
- */
- function getLocalCopy( array $params ) {
- list( $srcCont, $srcRel ) = $this->resolveStoragePath( $params['src'] );
- if ( $srcRel === null ) {
- return null;
- }
-
- // Get source file extension
- $ext = FileBackend::extensionFromPath( $srcRel );
- // Create a new temporary file...
- // TODO: Caution: tempfile should not write a local file.
- $tmpFile = TempFSFile::factory( wfBaseName( $srcRel ) . '_', $ext );
- if ( !$tmpFile ) {
- return null;
- }
- $tmpPath = $tmpFile->getPath();
-
- try {
- $this->storageClient->getBlob( $srcCont, $srcRel, $tmpPath );
- }
- catch ( Exception $e ) {
- error_log( __METHOD__.':'.__LINE__.' '.$e->getMessage() );
- $tmpFile = null;
- }
-
- return $tmpFile;
- }
-}