diff --git a/src/applications/drydock/management/DrydockManagementLeaseWorkflow.php b/src/applications/drydock/management/DrydockManagementLeaseWorkflow.php
index 616239eeb..9df072d88 100644
--- a/src/applications/drydock/management/DrydockManagementLeaseWorkflow.php
+++ b/src/applications/drydock/management/DrydockManagementLeaseWorkflow.php
@@ -1,78 +1,79 @@
 <?php
 
 final class DrydockManagementLeaseWorkflow
   extends DrydockManagementWorkflow {
 
   public function didConstruct() {
     $this
       ->setName('lease')
       ->setSynopsis('Lease a resource.')
       ->setArguments(
         array(
           array(
             'name'      => 'type',
             'param'     => 'resource_type',
             'help'      => 'Resource type.',
           ),
           array(
             'name'      => 'attributes',
             'param'     => 'name=value,...',
             'help'      => 'Resource specficiation.',
           ),
         ));
   }
 
   public function execute(PhutilArgumentParser $args) {
     $console = PhutilConsole::getConsole();
 
     $resource_type = $args->getArg('type');
     if (!$resource_type) {
       throw new PhutilArgumentUsageException(
         "Specify a resource type with `--type`.");
     }
 
     $attributes = $args->getArg('attributes');
     if ($attributes) {
       $options = new PhutilSimpleOptions();
+      $options->setCaseSensitive(true);
       $attributes = $options->parse($attributes);
     }
 
     $lease = new DrydockLease();
     $lease->setResourceType($resource_type);
     if ($attributes) {
       $lease->setAttributes($attributes);
     }
     $lease->queueForActivation();
 
     $root = dirname(phutil_get_library_root('phabricator'));
     $wait = new ExecFuture(
       'php -f %s wait-for-lease --id %s',
       $root.'/scripts/drydock/drydock_control.php',
       $lease->getID());
 
     $cursor = 0;
     foreach (Futures(array($wait))->setUpdateInterval(1) as $key => $future) {
       if ($future) {
         $future->resolvex();
         break;
       }
 
       $logs = id(new DrydockLogQuery())
         ->withLeaseIDs(array($lease->getID()))
         ->withAfterID($cursor)
         ->setOrder(DrydockLogQuery::ORDER_ID)
         ->execute();
 
       if ($logs) {
         foreach ($logs as $log) {
           $console->writeErr("%s\n", $log->getMessage());
         }
         $cursor = max(mpull($logs, 'getID'));
       }
     }
 
     $console->writeOut("Acquired Lease %s\n", $lease->getID());
     return 0;
   }
 
 }
diff --git a/src/applications/drydock/storage/DrydockLease.php b/src/applications/drydock/storage/DrydockLease.php
index de0ebf9bf..fd657f631 100644
--- a/src/applications/drydock/storage/DrydockLease.php
+++ b/src/applications/drydock/storage/DrydockLease.php
@@ -1,161 +1,161 @@
 <?php
 
 final class DrydockLease extends DrydockDAO {
 
   protected $resourceID;
   protected $resourceType;
   protected $until;
   protected $ownerPHID;
   protected $attributes = array();
   protected $status = DrydockLeaseStatus::STATUS_PENDING;
   protected $taskID;
 
   private $resource;
 
   public function getLeaseName() {
     return pht('Lease %d', $this->getID());
   }
 
   public function getConfiguration() {
     return array(
       self::CONFIG_AUX_PHID => true,
       self::CONFIG_SERIALIZATION => array(
         'attributes'    => self::SERIALIZATION_JSON,
       ),
     ) + parent::getConfiguration();
   }
 
   public function setAttribute($key, $value) {
-    $this->attributes[strtolower($key)] = $value;
+    $this->attributes[$key] = $value;
     return $this;
   }
 
   public function getAttribute($key, $default = null) {
-    return idx($this->attributes, strtolower($key), $default);
+    return idx($this->attributes, $key, $default);
   }
 
   public function generatePHID() {
     return PhabricatorPHID::generateNewPHID(
       PhabricatorPHIDConstants::PHID_TYPE_DRYL);
   }
 
   public function getInterface($type) {
     return $this->getResource()->getInterface($this, $type);
   }
 
   public function getResource() {
     $this->assertActive();
     if ($this->resource === null) {
       throw new Exception("Resource is not yet loaded.");
     }
     return $this->resource;
   }
 
   public function attachResource(DrydockResource $resource) {
     $this->assertActive();
     $this->resource = $resource;
     return $this;
   }
 
   public function loadResource() {
     $this->assertActive();
     return id(new DrydockResource())->loadOneWhere(
       'id = %d',
       $this->getResourceID());
   }
 
   public function queueForActivation() {
     if ($this->getID()) {
       throw new Exception(
         "Only new leases may be queued for activation!");
     }
 
     $this->setStatus(DrydockLeaseStatus::STATUS_PENDING);
     $this->save();
 
     // NOTE: Prevent a race where some eager worker quickly grabs the task
     // before we can save the Task ID.
 
     $this->openTransaction();
       $this->beginReadLocking();
 
         $this->reload();
 
         $task = PhabricatorWorker::scheduleTask(
           'DrydockAllocatorWorker',
           $this->getID());
 
         $this->setTaskID($task->getID());
         $this->save();
 
       $this->endReadLocking();
     $this->saveTransaction();
 
     return $this;
   }
 
   public function release() {
     $this->setStatus(DrydockLeaseStatus::STATUS_RELEASED);
     $this->save();
 
     $this->resource = null;
 
     return $this;
   }
 
   private function assertActive() {
     if ($this->status != DrydockLeaseStatus::STATUS_ACTIVE) {
       throw new Exception(
         "Lease is not active! You can not interact with resources through ".
         "an inactive lease.");
     }
   }
 
   public static function waitForLeases(array $leases) {
     assert_instances_of($leases, 'DrydockLease');
 
     $task_ids = array_filter(mpull($leases, 'getTaskID'));
 
     PhabricatorWorker::waitForTasks($task_ids);
 
     $unresolved = $leases;
     while (true) {
       foreach ($unresolved as $key => $lease) {
         $lease->reload();
         switch ($lease->getStatus()) {
           case DrydockLeaseStatus::STATUS_ACTIVE:
             unset($unresolved[$key]);
             break;
           case DrydockLeaseStatus::STATUS_RELEASED:
             throw new Exception("Lease has already been released!");
           case DrydockLeaseStatus::STATUS_EXPIRED:
             throw new Exception("Lease has already expired!");
           case DrydockLeaseStatus::STATUS_BROKEN:
             throw new Exception("Lease has been broken!");
           case DrydockLeaseStatus::STATUS_PENDING:
             break;
         }
       }
 
       if ($unresolved) {
         sleep(1);
       } else {
         break;
       }
     }
 
     foreach ($leases as $lease) {
       $lease->attachResource($lease->loadResource());
     }
   }
 
   public function waitUntilActive() {
     if (!$this->getID()) {
       $this->queueForActivation();
     }
 
     self::waitForLeases(array($this));
     return $this;
   }
 
 }
diff --git a/src/infrastructure/celerity/__tests__/CelerityResourceTransformerTestCase.php b/src/infrastructure/celerity/__tests__/CelerityResourceTransformerTestCase.php
index 6dd3d772e..883e41554 100644
--- a/src/infrastructure/celerity/__tests__/CelerityResourceTransformerTestCase.php
+++ b/src/infrastructure/celerity/__tests__/CelerityResourceTransformerTestCase.php
@@ -1,38 +1,39 @@
 <?php
 
 /**
  * @group celerity
  */
 final class CelerityResourceTransformerTestCase extends PhabricatorTestCase {
 
   public function testTransformation() {
     $files = dirname(__FILE__).'/transformer/';
     foreach (Filesystem::listDirectory($files) as $file) {
       $name = basename($file);
       $data = Filesystem::readFile($files.'/'.$file);
       $parts = preg_split('/^~~~+\n/m', $data);
       $parts = array_merge($parts, array(null));
 
       list($options, $in, $expect) = $parts;
 
-      $options = PhutilSimpleOptions::parse($options) + array(
+      $parser = new PhutilSimpleOptions();
+      $options = $parser->parse($options) + array(
         'minify' => false,
         'name'   => $name,
       );
 
       $xformer = new CelerityResourceTransformer();
       $xformer->setRawResourceMap(
         array(
           '/rsrc/example.png' => array(
             'uri' => '/res/hash/example.png',
           ),
         ));
       $xformer->setMinify($options['minify']);
 
       $result = $xformer->transformResource($options['name'], $in);
 
       $this->assertEqual(rtrim($expect), rtrim($result), $file);
     }
   }
 
 }
diff --git a/src/infrastructure/markup/rule/PhabricatorRemarkupRuleEmbedFile.php b/src/infrastructure/markup/rule/PhabricatorRemarkupRuleEmbedFile.php
index 0f5ba3cbb..7a92eada9 100644
--- a/src/infrastructure/markup/rule/PhabricatorRemarkupRuleEmbedFile.php
+++ b/src/infrastructure/markup/rule/PhabricatorRemarkupRuleEmbedFile.php
@@ -1,165 +1,166 @@
 <?php
 
 /**
  * @group markup
  */
 final class PhabricatorRemarkupRuleEmbedFile
   extends PhutilRemarkupRule {
 
   const KEY_RULE_EMBED_FILE = 'rule.embed.file';
 
   public function apply($text) {
     return preg_replace_callback(
       "@{F(\d+)([^}]+?)?}@",
       array($this, 'markupEmbedFile'),
       $text);
   }
 
   public function markupEmbedFile($matches) {
 
     $file = null;
     if ($matches[1]) {
       // TODO: This is pretty inefficient if there are a bunch of files.
       $file = id(new PhabricatorFile())->load($matches[1]);
     }
 
     if (!$file) {
       return $matches[0];
     }
     $phid = $file->getPHID();
 
     $engine = $this->getEngine();
     $token = $engine->storeText('');
     $metadata_key = self::KEY_RULE_EMBED_FILE;
     $metadata = $engine->getTextMetadata($metadata_key, array());
     $bundle = array('token' => $token);
 
     $options = array(
       'size'    => 'thumb',
       'layout'  => 'left',
       'float'   => false,
       'name'    => null,
     );
 
     if (!empty($matches[2])) {
       $matches[2] = trim($matches[2], ', ');
-      $options = PhutilSimpleOptions::parse($matches[2]) + $options;
+      $parser = new PhutilSimpleOptions();
+      $options = $parser->parse($matches[2]) + $options;
     }
     $file_name = coalesce($options['name'], $file->getName());
     $options['name'] = $file_name;
 
     $attrs = array();
     switch ($options['size']) {
       case 'full':
         $attrs['src'] = $file->getBestURI();
         $options['image_class'] = null;
         break;
       case 'thumb':
       default:
         $attrs['src'] = $file->getPreview220URI();
         $options['image_class'] = 'phabricator-remarkup-embed-image';
         break;
     }
     $bundle['attrs'] = $attrs;
     $bundle['options'] = $options;
 
     $bundle['meta'] = array(
       'phid'     => $file->getPHID(),
       'viewable' => $file->isViewableImage(),
       'uri'      => $file->getBestURI(),
       'dUri'     => $file->getDownloadURI(),
       'name'     => $options['name'],
     );
     $metadata[$phid][] = $bundle;
     $engine->setTextMetadata($metadata_key, $metadata);
 
     return $token;
   }
 
   public function didMarkupText() {
     $engine = $this->getEngine();
 
     $metadata_key = self::KEY_RULE_EMBED_FILE;
     $metadata = $engine->getTextMetadata($metadata_key, array());
 
     if (!$metadata) {
       return;
     }
 
     foreach ($metadata as $phid => $bundles) {
       foreach ($bundles as $data) {
 
         $options = $data['options'];
         $meta    = $data['meta'];
 
         if (!$meta['viewable'] || $options['layout'] == 'link') {
           $link = id(new PhabricatorFileLinkView())
             ->setFilePHID($meta['phid'])
             ->setFileName($meta['name'])
             ->setFileDownloadURI($meta['dUri'])
             ->setFileViewURI($meta['uri'])
             ->setFileViewable($meta['viewable']);
           $embed = $link->render();
           $engine->overwriteStoredText($data['token'], $embed);
           continue;
         }
 
         require_celerity_resource('lightbox-attachment-css');
         $img = phutil_render_tag('img', $data['attrs']);
 
         $embed = javelin_render_tag(
           'a',
           array(
             'href'        => $meta['uri'],
             'class'       => $options['image_class'],
             'sigil'       => 'lightboxable',
             'mustcapture' => true,
             'meta'        => $meta,
           ),
           $img);
 
         $layout_class = null;
         switch ($options['layout']) {
           case 'right':
           case 'center':
           case 'inline':
           case 'left':
             $layout_class = 'phabricator-remarkup-embed-layout-'.
               $options['layout'];
             break;
           default:
             $layout_class = 'phabricator-remarkup-embed-layout-left';
             break;
         }
 
         if ($options['float']) {
           switch ($options['layout']) {
             case 'center':
             case 'inline':
               break;
             case 'right':
               $layout_class .= ' phabricator-remarkup-embed-float-right';
               break;
             case 'left':
             default:
               $layout_class .= ' phabricator-remarkup-embed-float-left';
               break;
           }
         }
 
         if ($layout_class) {
           $embed = phutil_render_tag(
             'div',
             array(
               'class' => $layout_class,
             ),
             $embed);
         }
 
         $engine->overwriteStoredText($data['token'], $embed);
       }
     }
     $engine->setTextMetadata($metadata_key, array());
   }
 
 }