<commit_before>﻿/**
* Copyright (c) Microsoft.  All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

// Module dependencies.
var http = require('http');
var url = require('url');
var util = require('util');
var qs = require('qs');
var crypto = require('crypto');
var xml2js = require('xml2js');

var azureutil = require('../../util/util');

var StorageServiceSettings = require('../core/storageservicesettings');

var ServiceClient = require('./serviceclient');
var Constants = require('../../util/constants');
var HeaderConstants = Constants.HeaderConstants;
var QueryStringConstants = Constants.QueryStringConstants;
var HttpConstants = Constants.HttpConstants;
var Logger = require('../../diagnostics/logger');

// Expose 'StorageServiceClient'.
exports = module.exports = StorageServiceClient;

// Validation error messages
StorageServiceClient.incorrectStorageAccountErr = 'You must supply an account name or use the environment variable AZURE_STORAGE_ACCOUNT if you are not running in the emulator.';
StorageServiceClient.incorrectStorageAccessKeyErr = 'You must supply an account key or use the environment variable AZURE_STORAGE_ACCESS_KEY if you are not running in the emulator.';

/**
* Creates a new ServiceClient object.
*
* @constructor
* @param {string} storageAccount           The storage account.
* @param {string} storageAccessKey         The storage access key.
* @param {string} host                     The host for the service.
* @param {bool}   usePathStyleUri          Boolean value indicating wether to use path style uris.
* @param {object} authenticationProvider   The authentication provider object (e.g. sharedkey / sharedkeytable / sharedaccesssignature).
*/
function StorageServiceClient(storageAccount, storageAccessKey, host, usePathStyleUri, authenticationProvider) {
  this._setAccountCredentials(storageAccount, storageAccessKey);
  this.apiVersion = HeaderConstants.TARGET_STORAGE_VERSION;
  this.usePathStyleUri = usePathStyleUri;

  StorageServiceClient.super_.call(this, host, authenticationProvider);

  this._initDefaultFilter();
}

util.inherits(StorageServiceClient, ServiceClient);

/**
* Gets the storage settings.
*
* @param {string} [storageAccountOrConnectionString]  The storage account or the connection string.
* @param {string} [storageAccessKey]                  The storage access key.
* @param {string} [host]                              The host address.
*
* @return {StorageServiceSettings}
*/
StorageServiceClient.getStorageSettings = function (storageAccountOrConnectionString, storageAccessKey, host) {
  var storageServiceSettings;

  if (storageAccountOrConnectionString && !storageAccessKey) {
    // If storageAccountOrConnectionString was passed and no accessKey was passed, assume connection string
    storageServiceSettings = StorageServiceSettings.createFromConnectionString(storageAccountOrConnectionString);
  } else {
    if (!(storageAccountOrConnectionString && storageAccessKey) && ServiceClient.isEmulated()) {
      // Dev storage scenario
      storageServiceSettings = StorageServiceSettings.getDevelopmentStorageAccountSettings();
    } else {
      // Explicit credentials scenario
      if (!storageAccountOrConnectionString) {
        storageAccountOrConnectionString = process.env[ServiceClient.EnvironmentVariables.AZURE_STORAGE_ACCOUNT];
      }

      if (!storageAccessKey) {
        storageAccessKey = process.env[ServiceClient.EnvironmentVariables.AZURE_STORAGE_ACCESS_KEY];
      }

      // Default endpoints
      var blobendpoint = url.format({ protocol: 'http:', host: storageAccountOrConnectionString + '.' + ServiceClient.CLOUD_BLOB_HOST });
      var tableendpoint = url.format({ protocol: 'http:', host: storageAccountOrConnectionString + '.' + ServiceClient.CLOUD_TABLE_HOST });
      var queueendpoint = url.format({ protocol: 'http:', host: storageAccountOrConnectionString + '.' + ServiceClient.CLOUD_QUEUE_HOST });

      if (host) {
        var parsedHost = ServiceClient._parseHost(host);

        blobendpoint = url.format({ protocol: parsedHost.protocol, port: parsedHost.port, hostname: storageAccountOrConnectionString + '.' + parsedHost.hostname });
        tableendpoint = url.format({ protocol: parsedHost.protocol, port: parsedHost.port, hostname: storageAccountOrConnectionString + '.' + parsedHost.hostname });
        queueendpoint = url.format({ protocol: parsedHost.protocol, port: parsedHost.port, hostname: storageAccountOrConnectionString + '.' + parsedHost.hostname });
      }

      var settings = { 
        accountname: storageAccountOrConnectionString,
        accountkey: storageAccessKey,
        blobendpoint: blobendpoint,
        tableendpoint: tableendpoint,
        queueendpoint: queueendpoint
      };

      storageServiceSettings = StorageServiceSettings.createFromSettings(settings);
    }
  }

  return storageServiceSettings;
};

/**
* Builds the request options to be passed to the http.request method.
*
* @param {WebResource} webResource The webresource where to build the options from.
* @param {object}      options     The request options.
* @param {function(error, requestOptions)}  callback  The callback function.
* @return {undefined}
*/
StorageServiceClient.prototype._buildRequestOptions = function (webResource, options, callback) {
  var self = this;

  if (!webResource.headers || !webResource.headers[HeaderConstants.CONTENT_TYPE]) {
    webResource.addOptionalHeader(HeaderConstants.CONTENT_TYPE, '');
  }

  if (!webResource.headers || webResource.headers[HeaderConstants.CONTENT_LENGTH] === undefined) {
    webResource.addOptionalHeader(HeaderConstants.CONTENT_LENGTH, 0);
  } else if(webResource.headers && webResource.headers[HeaderConstants.CONTENT_LENGTH] === null) {
    delete webResource.headers[HeaderConstants.CONTENT_LENGTH];
  }

  webResource.addOptionalHeader(HeaderConstants.STORAGE_VERSION_HEADER, this.apiVersion);
  webResource.addOptionalHeader(HeaderConstants.DATE_HEADER, new Date().toUTCString());<commit_msg>Avoiding breaking change with devstore host detection.<commit_after>﻿/**
* Copyright (c) Microsoft.  All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

// Module dependencies.
var http = require('http');
var url = require('url');
var util = require('util');
var qs = require('qs');
var crypto = require('crypto');
var xml2js = require('xml2js');

var azureutil = require('../../util/util');

var StorageServiceSettings = require('../core/storageservicesettings');

var ServiceClient = require('./serviceclient');
var Constants = require('../../util/constants');
var HeaderConstants = Constants.HeaderConstants;
var QueryStringConstants = Constants.QueryStringConstants;
var HttpConstants = Constants.HttpConstants;
var Logger = require('../../diagnostics/logger');

// Expose 'StorageServiceClient'.
exports = module.exports = StorageServiceClient;

// Validation error messages
StorageServiceClient.incorrectStorageAccountErr = 'You must supply an account name or use the environment variable AZURE_STORAGE_ACCOUNT if you are not running in the emulator.';
StorageServiceClient.incorrectStorageAccessKeyErr = 'You must supply an account key or use the environment variable AZURE_STORAGE_ACCESS_KEY if you are not running in the emulator.';

/**
* Creates a new ServiceClient object.
*
* @constructor
* @param {string} storageAccount           The storage account.
* @param {string} storageAccessKey         The storage access key.
* @param {string} host                     The host for the service.
* @param {bool}   usePathStyleUri          Boolean value indicating wether to use path style uris.
* @param {object} authenticationProvider   The authentication provider object (e.g. sharedkey / sharedkeytable / sharedaccesssignature).
*/
function StorageServiceClient(storageAccount, storageAccessKey, host, usePathStyleUri, authenticationProvider) {
  this._setAccountCredentials(storageAccount, storageAccessKey);
  this.apiVersion = HeaderConstants.TARGET_STORAGE_VERSION;
  this.usePathStyleUri = usePathStyleUri;

  StorageServiceClient.super_.call(this, host, authenticationProvider);

  this._initDefaultFilter();
}

util.inherits(StorageServiceClient, ServiceClient);

/**
* Gets the storage settings.
*
* @param {string} [storageAccountOrConnectionString]  The storage account or the connection string.
* @param {string} [storageAccessKey]                  The storage access key.
* @param {string} [host]                              The host address.
*
* @return {StorageServiceSettings}
*/
StorageServiceClient.getStorageSettings = function (storageAccountOrConnectionString, storageAccessKey, host) {
  var storageServiceSettings;

  if (storageAccountOrConnectionString && !storageAccessKey) {
    // If storageAccountOrConnectionString was passed and no accessKey was passed, assume connection string
    storageServiceSettings = StorageServiceSettings.createFromConnectionString(storageAccountOrConnectionString);
  } else {
    if (!(storageAccountOrConnectionString && storageAccessKey) && ServiceClient.isEmulated()) {
      // Dev storage scenario
      storageServiceSettings = StorageServiceSettings.getDevelopmentStorageAccountSettings();
    } else {
      var usePathStyleUri = false;

      // Explicit credentials scenario
      if (!storageAccountOrConnectionString) {
        storageAccountOrConnectionString = process.env[ServiceClient.EnvironmentVariables.AZURE_STORAGE_ACCOUNT];
      }

      if (!storageAccessKey) {
        storageAccessKey = process.env[ServiceClient.EnvironmentVariables.AZURE_STORAGE_ACCESS_KEY];
      }

      // Default endpoints
      var blobendpoint = url.format({ protocol: 'http:', host: storageAccountOrConnectionString + '.' + ServiceClient.CLOUD_BLOB_HOST });
      var tableendpoint = url.format({ protocol: 'http:', host: storageAccountOrConnectionString + '.' + ServiceClient.CLOUD_TABLE_HOST });
      var queueendpoint = url.format({ protocol: 'http:', host: storageAccountOrConnectionString + '.' + ServiceClient.CLOUD_QUEUE_HOST });

      if (host) {
        if (host === ServiceClient.DEVSTORE_BLOB_HOST ||
            host === ServiceClient.DEVSTORE_TABLE_HOST ||
            host === ServiceClient.DEVSTORE_QUEUE_HOST) {

          usePathStyleUri = true;
        }

        var parsedHost = ServiceClient._parseHost(host);

        blobendpoint = url.format({ protocol: parsedHost.protocol, port: parsedHost.port, hostname: storageAccountOrConnectionString + '.' + parsedHost.hostname });
        tableendpoint = url.format({ protocol: parsedHost.protocol, port: parsedHost.port, hostname: storageAccountOrConnectionString + '.' + parsedHost.hostname });
        queueendpoint = url.format({ protocol: parsedHost.protocol, port: parsedHost.port, hostname: storageAccountOrConnectionString + '.' + parsedHost.hostname });
      }

      var settings = { 
        accountname: storageAccountOrConnectionString,
        accountkey: storageAccessKey,
        blobendpoint: blobendpoint,
        tableendpoint: tableendpoint,
        queueendpoint: queueendpoint
      };

      storageServiceSettings = StorageServiceSettings.createFromSettings(settings);
      storageServiceSettings._usePathStyleUri = usePathStyleUri;
    }
  }

  return storageServiceSettings;
};

/**
* Builds the request options to be passed to the http.request method.
*
* @param {WebResource} webResource The webresource where to build the options from.
* @param {object}      options     The request options.
* @param {function(error, requestOptions)}  callback  The callback function.
* @return {undefined}
*/
StorageServiceClient.prototype._buildRequestOptions = function (webResource, options, callback) {
  var self = this;

  if (!webResource.headers || !webResource.headers[HeaderConstants.CONTENT_TYPE]) {
    webResource.addOptionalHeader(HeaderConstants.CONTENT_TYPE, '');
  }

  if (!webResource.headers || webResource.headers[HeaderConstants.CONTENT_LENGTH] === undefined) {
    webResource.addOptionalHeader(HeaderConstants.CONTENT_LENGTH, 0);
  } else if(webResource.headers && webResource.headers[HeaderConstants.CONTENT_LENGTH] === null) {
    delete webResource.headers[HeaderConstants.CONTENT_LENGTH];
  }

  webResource.addOptionalHeader(HeaderConstants.STORAGE_VERSION_HEADER, this.apiVersion);
  webResource.addOptionalHeader(HeaderConstants.DATE_HEADER, new Date().toUTCString());
{'fraction_non_alphanumeric': 0.09643417806683113, 'fraction_numerical': 0.0010465724751439038, 'mean_word_length': 4.557955961778147, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5989119', 'n_tokens_mistral': 3399, 'n_tokens_neox': 3359, 'n_words': 943}