text:
// Licensed to Cloudera, Inc. under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  Cloudera, Inc. licenses this file
// to you 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.

(function (root, factory) {
  if(typeof define === "function" && define.amd) {
    define(['knockout'], factory);
  } else {
    root.ApiHelper = factory(ko);
  }
}(this, function (ko) {

  var TIME_TO_LIVE_IN_MILLIS = $.totalStorage('hue.cacheable.ttl.override') || $.totalStorage('hue.cacheable.ttl'); // 1 day by default, configurable with desktop.custom.cacheable_ttl in the .ini or $.totalStorage('hue.cacheable.ttl.override', 1234567890)

  var AUTOCOMPLETE_API_PREFIX = "/notebook/api/autocomplete/";
  var SAMPLE_API_PREFIX = "/notebook/api/sample/";
  var DOCUMENTS_API = "/desktop/api2/doc/";
  var DOCUMENTS_SEARCH_API = "/desktop/api2/docs/";
  var HDFS_API_PREFIX = "/filebrowser/view=";
  var HDFS_PARAMETERS = "?pagesize=100&format=json";
  var IMPALA_INVALIDATE_API = '/impala/api/invalidate';
  var CONFIG_SAVE_API = '/desktop/api/configurations/save/';
  var CONFIG_APPS_API = '/desktop/api/configurations';

  /**
   * @param {Object} i18n
   * @param {string} i18n.errorLoadingDatabases
   * @param {string} i18n.errorLoadingTablePreview
   * @param {string} user
   *
   * @constructor
   */
  function ApiHelper (i18n, user) {
    var self = this;
    self.i18n = i18n;
    self.user = user;
    self.lastKnownDatabases = {};
    self.fetchQueue = {};
    self.invalidateImpala = 'cache';

    huePubSub.subscribe('assist.clear.db.cache', function (options) {
      self.clearDbCache(options);
    });

    huePubSub.subscribe('assist.clear.hdfs.cache', function () {
      $.totalStorage("hue.assist." + self.getTotalStorageUserPrefix('hdfs'), {});
    });
  }

  ApiHelper.prototype.hasExpired = function (timestamp) {
    return (new Date()).getTime() - timestamp > TIME_TO_LIVE_IN_MILLIS;
  };

  /**
   * @param {string} sourceType
   * @returns {string}
   */
  ApiHelper.prototype.getTotalStorageUserPrefix = function (sourceType) {
    var self = this;
    return sourceType + "_" + self.user;
  };

  /**
   *
   * @param {string} owner - 'assist', 'viewModelA' etc.
   * @param {string} id
   * @param {*} [value] - Optional, undefined and null will remove the value
   */
  ApiHelper.prototype.setInTotalStorage = function(owner, id, value) {
    var self = this;
    var cachedData = $.totalStorage("hue.user.settings." + self.getTotalStorageUserPrefix(owner)) || {};
    if (typeof value !== 'undefined' && value !== null) {
      cachedData[id] = value;
      $.totalStorage("hue.user.settings." + self.getTotalStorageUserPrefix(owner), cachedData);
    } else if (cachedData[id]) {
      delete cachedData[id];
      $.totalStorage("hue.user.settings." + self.getTotalStorageUserPrefix(owner), cachedData);
    }
  };

  /**
   *
   * @param {string} owner - 'assist', 'viewModelA' etc.
   * @param {string} id
   * @param {*} [defaultValue]
   * @returns {*}
   */
  ApiHelper.prototype.getFromTotalStorage = function(owner, id, defaultValue) {
    var self = this;
    var cachedData = $.totalStorage("hue.user.settings." + self.getTotalStorageUserPrefix(owner)) || {};
    return typeof cachedData[id] !== 'undefined' ? cachedData[id] : defaultValue;
  };

  /**
   * @param {string} owner - 'assist', 'viewModelA' etc.
   * @param {string} id
   * @param {Observable} observable
   * @param {*} [defaultValue] - Optional default value to use if not in total storage initially
   */
  ApiHelper.prototype.withTotalStorage = function(owner, id, observable, defaultValue, noInit) {
    var self = this;

    var cachedValue = self.getFromTotalStorage(owner, id, defaultValue);

    if (! noInit && cachedValue !== 'undefined') {
      observable(cachedValue);
    }

    observable.subscribe(function (newValue) {
      if (owner === 'assist' && id === 'assist_panel_visible') {
        huePubSub.publish('assist.forceRender');
      }
      self.setInTotalStorage(owner, id, newValue);
    });
  };

  /**
   * @param {Object} [response]
   * @param {number} [response.status]
   * @returns {boolean} - True if actually an error
   */
  ApiHelper.prototype.successResponseIsError = function (response) {
    return typeof response !== 'undefined' && (
        typeof response.traceback !== 'undefined' ||
        (typeof response.status !== 'undefined' && response.status !== 0) ||
        response.code === 503 ||
        response.code === 500);
  };

  /**
   * @param {Object} options
   * @param {Function} [options.errorCallback]
   * @param {boolean} [options.silenceErrors]
   * @returns {Function}
   */
  ApiHelper.prototype.assistErrorCallback = function (options) {
    return function (errorResponse) {
      var errorMessage = 'Unknown error occurred';
      if (errorResponse !== 'undefined') {
        if (typeof errorResponse.responseText !== 'undefined') {
          try {
            var errorJs = JSON.parse(errorResponse.responseText);
            if (typeof errorJs.message !== 'undefined') {
              errorMessage = errorJs.message;
            } else {
              errorMessage = errorResponse.responseText;
            }
          } catch(err) {
            errorMessage = errorResponse.responseText;
          }
        } else if (typeof errorResponse.message !== 'undefined') {
          errorMessage = errorResponse.message;
        } else if (typeof errorResponse.statusText !== 'undefined') {
          errorMessage = errorResponse.statusText;
        } else if (errorResponse.error !== 'undefined' && toString.call(errorResponse.error) === '[object String]' ) {
          errorMessage = errorResponse.error;
        } else if (toString.call(errorResponse) === '[object String]') {
          errorMessage = errorResponse;
        }
      }

      if (! options.silenceErrors) {
        if (typeof window.console !== 'undefined') {
          console.error(errorResponse);
          console.error(new Error().stack);
        }
        $(document).trigger("error", errorMessage);
      }

      if (options.errorCallback) {
        options.errorCallback(errorMessage);
      }
    };
  };

  /**
   * @param {string} url
   * @param {Object} data
   * @param {Object} options
   * @param {function} [options.successCallback]
   * @param {function} [options.errorCallback]
   * @param {boolean} [options.silenceErrors]
   */
  ApiHelper.prototype.simplePost = function (url, data, options) {
    var self = this;
    $.post(url, data, function (data) {
      if (self.successResponseIsError(data)) {
        self.assistErrorCallback(options)(data);
      } else if (typeof options.successCallback !== 'undefined') {
        options.successCallback(data);
      }
    })
    .fail(self.assistErrorCallback(options));
  };

  /**
   * @param {string} url
   * @param {Object} data
   * @param {Object} options
   * @param {function} [options.successCallback]
   * @param {function} [options.errorCallback]
   * @param {boolean} [options.silenceErrors]
   */
  ApiHelper.prototype.simpleGet = function (url, data, options) {
    var self = this;
    $.get(url, data, function (data) {
      if (self.successResponseIsError(data)) {
        self.assistErrorCallback(options)(data);
      } else if (typeof options.successCallback !== 'undefined') {
        options.successCallback(data);
      }
    })
    .fail(self.assistErrorCallback(options));
  };

  ApiHelper.prototype.fetchUsersAndGroups = function (options) {
    var self = this;
    self.simpleGet('/desktop/api/users/autocomplete', {}, options);
  };

  /**
   * @param {Object} options
   * @param {Function} options.successCallback
   * @param {Function} [options.errorCallback]
   * @param {boolean} [options.silenceErrors]
   * @param {Object} [options.editor] - Ace editor
   *
   * @param {string[]} options.pathParts
   */
  ApiHelper.prototype.fetchHdfsPath = function (options) {
    var self = this;
    var url = HDFS_API_PREFIX + "/" + options.pathParts.join("/") + HDFS_PARAMETERS;

    var fetchFunction = function (storeInCache) {
      $.ajax({
        dataType: "json",
        url: url,
        success: function (data) {
          if (!data.error && !self.successResponseIsError(data) && typeof data.files !== 'undefined' && data.files !== null) {
            if (data.files.length > 2) {
              storeInCache(data);
            }
            options.successCallback(data);
          } else {
            self.assistErrorCallback(options)(data);
          }
        }
      })
      .fail(self.assistErrorCallback(options))
      .always(function () {
        if (typeof options.editor !== 'undefined' && options.editor !== null) {
          options.editor.hideSpinner();
        }
      });
    };

    fetchCached.bind(self)($.extend({}, options, {
      sourceType: 'hdfs',
      url: url,
      fetchFunction: fetchFunction
    }));
  };

  ApiHelper.prototype.getFetchQueue = function (fetchFunction, identifier) {
    var self = this;
    if (! self.fetchQueue[fetchFunction]) {
      self.fetchQueue[fetchFunction] = {};
    }
    var queueForFunction = self.fetchQueue[fetchFunction];

    var id = typeof identifier === 'undefined' || identifier === null ? 'DEFAULT_QUEUE' : identifier;

    if (! queueForFunction[id]) {
      queueForFunction[id] = [];
    }
    return queueForFunction[id];
  };

  /**
   * @param {Object} options
   * @param {Function} [options.successCallback]
   * @param {Function} [options.errorCallback]
   * @param {boolean} [options.silenceErrors]
   */
  ApiHelper.prototype.fetchConfigurations = function (options) {
    var self = this;
    self.simpleGet(CONFIG_APPS_API, {}, options);
  };

  ApiHelper.prototype.saveGlobalConfiguration = function (options) {
    var self = this;
    self.simplePost(CONFIG_APPS_API, {
      configuration: ko.mapping.toJSON(options.configuration)
    }, options);
  };

  /**
   * @param {Object} options
   * @param {Function} [options.successCallback]
   * @param {Function} [options.errorCallback]
   * @param {boolean} [options.silenceErrors]
   *
   * @param {string} options.app
   * @param {Object} options.properties
   * @param {boolean} [options.isDefault]
   * @param {Number} [options.groupId]
   * @param {Number} [options.userId]
   */
  ApiHelper.prototype.saveConfiguration = function (options) {
    var self = this;
    self.simplePost(CONFIG_SAVE_API, {
      app: options.app,
      properties: ko.mapping.toJSON(options.properties),
      is_default: options.isDefault,
      group_id: options.groupId,
      user_id: options.userId
    }, options);
  };

  /**
   * @param {Object} options
   * @param {Function} options.successCallback
   * @param {Function} [options.errorCallback]
   * @param {boolean} [options.silenceErrors]
   *
   * @param {string} [options.uuid]
   */
  ApiHelper.prototype.fetchDocuments = function (options) {
    var self = this;

    var queue = self.getFetchQueue('fetchDocuments', options.uuid);
    queue.push(options);
    if (queue.length > 1) {
      return;
    }

    $.ajax({
      url: DOCUMENTS_API,
      data: {
        uuid: options.uuid
      },
      success: function (data) {
        while (queue.length > 0) {
          var next = queue.shift();
          if (! self.successResponseIsError(data)) {
            next.successCallback(data);
          } else {
            self.assistErrorCallback(next)(data);
          }
        }
      }
    })
    .fail(function (response) {
      while (queue.length > 0) {
        var next = queue.shift();
        self.assistErrorCallback(next)(response);
      }
    });
  };

  /**
   * @param {Object} options
   * @param {Function} options.successCallback
   * @param {Function} [options.errorCallback]
   * @param {boolean} [options.silenceErrors]
   *
   * @param {string} [options.path]
   * @param {string} [options.query]
   * @param {string} [options.type]
   * @param {int} [options.page]
   * @param {int} [options.limit]
   */
  ApiHelper.prototype.searchDocuments = function (options) {
    var self = this;
    $.ajax({
      url: DOCUMENTS_SEARCH_API,
      data: {
        uuid: options.uuid,
        text: options.query,
        type: options.type,
        page: options.page,
        limit: options.limit
      },
      success: function (data) {
        if (! self.successResponseIsError(data)) {
          options.successCallback(data);
        } else {
          self.assistErrorCallback(options)(data);
        }
      }
    })
    .fail(self.assistErrorCallback(options));
  };

  /**
   * @param {Object} options
   * @param {Function} options.successCallback
   * @param {Function} [options.errorCallback]
   * @param {boolean} [options.silenceErrors]
   *
   * @param {number} options.uuid
   */
  ApiHelper.prototype.fetchDocument = function (options) {
    var self = this;
    $.ajax({
      url: DOCUMENTS_API,
      data: {
        uuid: options.uuid
      },
      success: function (data) {
        if (! self.successResponseIsError(data)) {
          options.successCallback(data);
        } else {
          self.assistErrorCallback(options)(data);
        }
      }
    })
    .fail(self.assistErrorCallback(options));
  };

  /**
   * @param {Object} options
   * @param {Function} options.successCallback
   * @param {Function} [options.errorCallback]
   * @param {boolean} [options.silenceErrors]
   *
   * @param {string} options.parentUuid
   * @param {string} options.name
   */
  ApiHelper.prototype.createDocumentsFolder = function (options) {
    var self = this;
    self.simplePost("/desktop/api2/doc/mkdir", {
      parent_uuid: ko.mapping.toJSON(options.parentUuid),
      name: ko.mapping.toJSON(options.name)
    }, options);
  };

  /**
   * @param {Object} options
   * @param {Function} options.successCallback
   * @param {Function} [options.errorCallback]
   * @param {Function} [options.progressHandler]
   * @param {boolean} [options.silenceErrors]
   *
   * @param {FormData} options.formData
   */
  ApiHelper.prototype.uploadDocument = function (options) {
    var self = this;
    $.ajax({
      url: '/desktop/api2/doc/import',
      type: 'POST',
      success: function (data) {
        if (! self.successResponseIsError(data)) {
          options.successCallback(data);
        } else {
          self.assistErrorCallback(options)(data);
        }
      },
      xhr: function() {
        var myXhr = $.ajaxSettings.xhr();
        if(myXhr.upload && options.progressHandler) {
          myXhr.upload.addEventListener('progress', options.progressHandler, false);
        }
        return myXhr;
      },
      dataType: 'json',
      data: options.formData,
      cache: false,
      contentType: false,
      processData: false
    })
    .fail(self.assistErrorCallback(options));
  };

  /**
   *
   * @param {Function} options.successCallback
   * @param {Function} [options.errorCallback]
   * @param {boolean} [options.silenceErrors]
   *
   * @param {number} options.sourceId - The ID of the source document
   * @param {number} options.destinationId - The ID of the target document
   */
  ApiHelper.prototype.moveDocument = function (options) {
    var self = this;
    self.simplePost("/desktop/api2/doc/move", {
      source_doc_uuid: ko.mapping.toJSON(options.sourceId),
      destination_doc_uuid: ko.mapping.toJSON(options.destinationId)
    }, options);
  };

  /**
   * @param {Object} options
   * @param {Function} options.successCallback
   * @param {Function} [options.errorCallback]
   * @param {boolean} [options.silenceErrors]
   *
   * @param {string} options.uuid
   * @param {string} [options.skipTrash] - Default false
   */
  ApiHelper.prototype.deleteDocument = function (options) {
    var self = this;
    self.simplePost("/desktop/api2/doc/delete", {
      uuid: ko.mapping.toJSON(options.uuid),
      skip_trash: ko.mapping.toJSON(options.skipTrash || false)
    }, options);
  };

  /**
   *
   * @param {Object} options
   * @param {string} options.sourceType
   * @param {string} [options.databaseName]
   * @param {boolean} [options.invalidateImpala]
   * @param {string} [options.tableName]
   * @param {string[]} [options.fields]
   * @param {boolean} [options.clearAll]
   */
  ApiHelper.prototype.clearDbCache = function (options) {
    var self = this;
    self.invalidateImpala = options.invalidateImpala || 'cache';
    if (options.clearAll) {
      $.totalStorage("hue.assist." + self.getTotalStorageUserPrefix(options.sourceType), {});
    } else {
      var url = AUTOCOMPLETE_API_PREFIX;
      if (options.databaseName) {
        url += options.databaseName;
      }
      if (options.tableName) {
        url += "/" + options.tableName;
      }
      if (options.fields) {
        url += options.fields.length > 0 ? "/" + options.fields.join("/") : "";
      }
      var cachedData = $.totalStorage("hue.assist." + self.getTotalStorageUserPrefix(options.sourceType)) || {};
      delete cachedData[url];
      $.totalStorage("hue.assist." + self.getTotalStorageUserPrefix(options.sourceType), cachedData);
    }
  };

  /**
   * @param {Object} options
   * @param {Function} options.successCallback
   * @param {Function} [options.errorCallback]
   * @param {boolean} [options.silenceErrors]
   *
   * @param {string} options.sourceType
   * @param {string} [options.database]
   **/
  ApiHelper.prototype.loadDatabases = function (options) {
    var self = this;

    var loadFunction = function () {
      self.invalidateImpala = 'cache';
      fetchAssistData.bind(self)($.extend({}, options, {
        url: AUTOCOMPLETE_API_PREFIX,
        successCallback: function (data) {
          var databases = data.databases || [];
          // Blacklist of system databases
          self.lastKnownDatabases[options.sourceType] = $.grep(databases, function (database) {
            return database !== "_impala_builtins";
          });
          options.successCallback(self.lastKnownDatabases[options.sourceType]);
        },
        errorCallback: function (response) {
          if (response.status == 401) {
            $(document).trigger("showAuthModal", {
              'type': options.sourceType, 'callback': function () {
                self.loadDatabases(options);
              }
            });
            return;
          }
          self.lastKnownDatabases[options.sourceType] = [];
          self.assistErrorCallback(options)(response);
        },
        cacheCondition: function (data) {
          return typeof data !== 'undefined' && data !== null && typeof data.databases !== 'undefined' && data.databases !== null && data.databases.length > 0;
        }
      }));
    };

    if (options.sourceType === 'impala' && self.invalidateImpala == 'invalidateAndFlush') {
      $.post(IMPALA_INVALIDATE_API, { flush_all: true, database: options.database }, loadFunction);
    } else if (options.sourceType === 'impala' && self.invalidateImpala == 'invalidate') {
      $.post(IMPALA_INVALIDATE_API, { flush_all: false, database: options.database }, loadFunction);
    } else {
      loadFunction();
    }
  };

  /**
   * @param {Object} options
   * @param {Function} options.successCallback
   * @param {Function} [options.errorCallback]
   * @param {boolean} [options.silenceErrors]
   *
   * @param {string} options.databaseName
   * @param {string} options.tableName
   */
  ApiHelper.prototype.fetchPartitions = function (options) {
    var self = this;
    $.ajax({
      url: "/metastore/table/" + options.databaseName + "/" + options.tableName + "/partitions",
      data: {
        "format" : 'json'
      },
      beforeSend: function (xhr) {
        xhr.setRequestHeader("X-Requested-With", "Hue");
      },
      success: function (response) {
        if (! self.successResponseIsError(response)) {
          options.successCallback(response);
        } else {
          self.assistErrorCallback(options)(response);
        }

      },
      error: self.assistErrorCallback(options)
    });
  };

  /**
   * @param {Object} options
   * @param {string} options.sourceType
   * @param {Function} options.successCallback
   * @param {Function} [options.errorCallback]
   * @param {boolean} [options.silenceErrors]
   *
   * @param {string} options.databaseName
   * @param {string} options.tableName
   */
  ApiHelper.prototype.fetchTableDetails = function (options) {
    var self = this;
    $.ajax({
      url: "/" + (options.sourceType == "hive" ? "beeswax" : options.sourceType) + "/api/table/" + options.databaseName + "/" + options.tableName,
      data: {
        "format" : 'json'
      },
      beforeSend: function (xhr) {
        xhr.setRequestHeader("X-Requested-With", "Hue");
      },
      success: function (response) {
        if (! self.successResponseIsError(response)) {
          options.successCallback(response);
        } else {
          self.assistErrorCallback(options)(response);
        }
      },
      error: self.assistErrorCallback(options)
    });
  };

  /**
   * @param {Object} options
   * @param {string} options.sourceType
   * @param {Function} options.successCallback
   * @param {Function} [options.errorCallback]
   * @param {boolean} [options.silenceErrors]
   *
   * @param {string} options.databaseName
   * @param {string} options.tableName
   * @param {string} [options.columnName]
   * @param {Object} [options.editor] - Ace editor
   */
  ApiHelper.prototype.fetchTableSample = function (options) {
    var self = this;
    var url = SAMPLE_API_PREFIX + options.databaseName + '/' + options.tableName + (options.columnName ? '/' + options.columnName : '');

    var fetchFunction = function (storeInCache) {
      $.post(url, {
        notebook: {},
        snippet: ko.mapping.toJSON({
          type: options.sourceType
        })
      })
      .done(function (data) {
        if (! self.successResponseIsError(data)) {
          if ((typeof data.rows !== 'undefined' && data.rows.length > 0) || typeof data.sample !== 'undefined') {
            storeInCache(data);
          }
          options.successCallback(data);
        } else {
          self.assistErrorCallback(options)(data);
        }
      })
      .fail(self.assistErrorCallback(options))
      .always(function () {
        if (typeof options.editor !== 'undefined' && options.editor !== null) {
          options.editor.hideSpinner();
        }
      });
    };

    if (options.columnName) {
      fetchCached.bind(self)($.extend({}, options, {
        url: url,
        fetchFunction: fetchFunction
      }));
    } else {
      fetchFunction($.noop);
    }
  };

  /**
   * @param {Object} options
   * @param {string} options.sourceType
   * @param {Function} options.successCallback
   * @param {Function} [options.errorCallback]
   * @param {boolean} [options.silenceErrors]
   *
   * @param {string} options.databaseName
   * @param {string} options.tableName
   * @param {string} options.columnName
   */
  ApiHelper.prototype.refreshTableStats = function (options) {
    var self = this;
    var pollRefresh = function (url) {
      $.post(url, function (data) {
        if (data.isSuccess) {
          options.successCallback(data);
        } else if (data.isFailure) {
          self.assistErrorCallback(options)(data.message);
        } else {
          window.setTimeout(function () {
            pollRefresh(url);
          }, 1000);
        }
      }).fail(self.assistErrorCallback(options));
    };

    $.post("/" + (options.sourceType == "hive" ? "beeswax" : options.sourceType) + "/api/analyze/" + options.databaseName + "/" + options.tableName + "/"  + (options.columnName || ""), function (data) {
      if (data.status == 0 && data.watch_url) {
        pollRefresh(data.watch_url);
      } else {
        self.assistErrorCallback(options)(data);
      }
    }).fail(self.assistErrorCallback(options));
  };

  /**
   * @param {Object} options
   * @param {string} options.sourceType
   * @param {Function} options.successCallback
   * @param {Function} [options.errorCallback]
   * @param {boolean} [options.silenceErrors]
   *
   * @param {string} options.databaseName
   * @param {string} options.tableName
   * @param {string} options.columnName
   */
  ApiHelper.prototype.fetchStats = function (options) {
    var self = this;
    $.ajax({
      url: "/" + options.sourceType + "/api/table/" + options.databaseName + "/" + options.tableName + "/stats/" + ( options.columnName || ""),
      data: {},
      beforeSend: function (xhr) {
        xhr.setRequestHeader("X-Requested-With", "Hue");
      },
      dataType: "json",
      success: function (response) {
        if (! self.successResponseIsError(response)) {
          options.successCallback(response)
        } else {
          self.assistErrorCallback(options)(response);
        }
      },
      error: self.assistErrorCallback(options)
    });
  };

  /**
   * @param {Object} options
   * @param {string} options.sourceType
   * @param {Function} options.successCallback
   * @param {Function} [options.errorCallback]
   * @param {boolean} [options.silenceErrors]
   *
   * @param {Object} [options.prefixFilter]
   * @param {string} options.databaseName
   * @param {string} options.tableName
   * @param {string} options.columnName
   */
  ApiHelper.prototype.fetchTerms = function (options) {
    var self = this;
    $.ajax({
      url: "/" + options.sourceType + "/api/table/" + options.databaseName + "/" + options.tableName + "/terms/" + options.columnName + "/" + (options.prefixFilter || ""),
      data: {},
      beforeSend: function (xhr) {
        xhr.setRequestHeader("X-Requested-With", "Hue");
      },
      dataType: "json",
      success: function (response) {
        if (! self.successResponseIsError(response)) {
          options.successCallback(response);
        } else {
          self.assistErrorCallback(options)(response);
        }
      },
      error: self.assistErrorCallback(options)
    });
  };

  /**
   * @param {Object} options
   * @param {string} options.sourceType
   * @param {Function} options.successCallback
   * @param {Function} [options.errorCallback]
   * @param {boolean} [options.silenceErrors]
   * @param {Object} [options.editor] - Ace editor
   *
   * @param {string} options.databaseName
   */
  ApiHelper.prototype.fetchTables = function (options) {
    var self = this;
    fetchAssistData.bind(self)($.extend({}, options, {
      url: AUTOCOMPLETE_API_PREFIX + options.databaseName,
      errorCallback: self.assistErrorCallback(options),
      cacheCondition: function (data) {
        return typeof data !== 'undefined' && data !== null && typeof data.tables_meta !== 'undefined' && data.tables_meta !== null && data.tables_meta.length > 0;
      }
    }));
  };

  var fieldCacheCondition = function (data) {
    if (typeof data !== 'undefined' && data !== null) {
      return (typeof data.item !== 'undefined' && data.item !== null) ||
          (typeof data.key !== 'undefined' && data.key !== null) ||
          (typeof data.tables_meta !== 'undefined' && data.tables_meta !== null && data.tables_meta.length > 0) ||
          (typeof data.extended_columns !== 'undefined' && data.extended_columns !== null && data.extended_columns.length > 0) ||
          (typeof data.columns !== 'undefined' && data.columns !== null && data.columns.length > 0) ||
          (typeof data.fields !== 'undefined' && data.fields !== null && data.fields.length > 0)
    }
    return false;
  };

  /**
   * @param {Object} options
   * @param {string} options.sourceType
   * @param {Function} options.successCallback
   * @param {Function} [options.errorCallback]
   * @param {boolean} [options.silenceErrors]
   * @param {Object} [options.editor] - Ace editor
   *
   * @param {string} options.databaseName
   * @param {string} options.tableName
   * @param {string[]} options.fields
   */
  ApiHelper.prototype.fetchFields = function (options) {
    var self = this;
    var fieldPart = options.fields.length > 0 ? "/" + options.fields.join("/") : "";
    fetchAssistData.bind(self)($.extend({}, options, {
      url: AUTOCOMPLETE_API_PREFIX + options.databaseName + "/" + options.tableName + fieldPart,
      errorCallback: self.assistErrorCallback(options),
      cacheCondition: fieldCacheCondition
    }));
  };

  /**
   * @param {Object} options
   * @param {string} options.sourceType
   * @param {Function} options.successCallback
   * @param {Function} [options.errorCallback]
   * @param {boolean} [options.silenceErrors]
   *
   * @param {string[]} options.hierarchy
   */
  ApiHelper.prototype.fetchPanelData = function (options) {
    var self = this;
    fetchAssistData.bind(self)($.extend({}, options, {
      url: AUTOCOMPLETE_API_PREFIX + options.hierarchy.join("/"),
      errorCallback: self.assistErrorCallback(options),
      cacheCondition: fieldCacheCondition
    }));
  };

  /**
   * @param {Object} options
   * @param {string} options.sourceType
   * @param {string} options.url
   * @param {Function} options.cacheCondition - Determines whether it should be cached or not
   * @param {Function} options.successCallback
   * @param {Function} options.errorCallback
   * @param {Object} [options.editor] - Ace editor
   */
  var fetchAssistData = function (options) {
    var self = this;
    if (!options.sourceType) {
      return
    }

    var cachedData = $.totalStorage("hue.assist." + self.getTotalStorageUserPrefix(options.sourceType)) || {};
    if (typeof cachedData[options.url] !== "undefined" && ! self.hasExpired(cachedData[options.url].timestamp)) {
      options.successCallback(cachedData[options.url].data);
      return;
    }
    if (typeof options.editor !== 'undefined' && options.editor !== null) {
      options.editor.showSpinner();
    }

    var queue = self.getFetchQueue('fetchAssistData', options.sourceType + '_' + options.url);
    queue.push(options);
    if (queue.length > 1) {
      return;
    }

    $.post(options.url, {
      notebook: {},
      snippet: ko.mapping.toJSON({
        type: options.sourceType
      })
    }, function (data) {
      // Safe to assume all requests in the queue have the same cacheCondition
      if (data.status === 0 && !self.successResponseIsError(data) && options.cacheCondition(data)) {
        cachedData[options.url] = {
          timestamp: (new Date()).getTime(),
          data: data
        };
        $.totalStorage("hue.assist." + self.getTotalStorageUserPrefix(options.sourceType), cachedData);
      }
      while (queue.length > 0) {
        var next = queue.shift();
        if (data.status === 0 && !self.successResponseIsError(data)) {
          next.successCallback(data);
        } else {
          next.errorCallback(data);
        }
        if (typeof next.editor !== 'undefined' && next.editor !== null) {
          next.editor.hideSpinner();
        }
      }
    }).fail(function (data) {
      while (queue.length > 0) {
        var next = queue.shift();
        next.errorCallback(data);
        if (typeof next.editor !== 'undefined' && next.editor !== null) {
          next.editor.hideSpinner();
        }
      }
    });
  };

  /**
   *
   * @param {Object} options
   * @param {string} options.sourceType
   * @param {string} options.url
   * @param {Function} options.fetchFunction
   * @param {Function} options.successCallback
   * @param {Object} [options.editor] - Ace editor
   */
  var fetchCached = function (options) {
    var self = this;
    var cachedData = $.totalStorage("hue.assist." + self.getTotalStorageUserPrefix(options.sourceType)) || {};

    if (typeof cachedData[options.url] == "undefined" || self.hasExpired(cachedData[options.url].timestamp)) {
      if (typeof options.editor !== 'undefined' && options.editor !== null) {
        options.editor.showSpinner();
      }
      options.fetchFunction(function (data) {
        cachedData[options.url] = {
          timestamp: (new Date()).getTime(),
          data: data
        };
        $.totalStorage("hue.assist." + self.getTotalStorageUserPrefix(options.sourceType), cachedData);
      });
    } else {
      options.successCallback(cachedData[options.url].data);
    }
  };

  var instance = null;

  return {

    /**
     * @param {Object} options
     * @param {Object} options.i18n
     * @param {string} options.i18n.errorLoadingDatabases
     * @param {string} options.i18n.errorLoadingTablePreview
     * @param {string} options.user
     *
     * @returns {ApiHelper}
     */
    getInstance: function (options) {
      if (instance === null) {
        instance = new ApiHelper(options.i18n, options.user);
      }
      return instance;
    }
  };
}));


The plastic bag charge in force at large shops all over Somerset is set to increase, according to reoprts.
It is thought that the price will be brought up to 10p a bag, and the law is also expected to be extended to cover all shops.
The Prime Minister is to announce the changes as part of plans to tackle plastic pollution, the Daily Mail and Telegraph have reported.
Under the existing rules, only stores employing more than 250 people have to charge at least 5p per bag.
However, under these new measures, the fee would reportedly double to 10p and include all retailers.
Disposable carrier bags issued by the seven biggest supermarket chains have declined by 86% since the charge was introduced in 2015, official figures show.
Donations from the bag levy to good causes amounted to over £58.5 million, based on figures from two-thirds of the retailers who voluntarily reported the information.
A consultation on using the tax system to combat waste is considering measures such as the "latte levy" on coffee cups.


text:
Posts Tagged: Chris Goettl
Time to Patch — 47 Comments
Microsoft Patches 'Wormable' Flaw in Windows XP, 7 and Windows 2003
Microsoft today is taking the unusual step of releasing security updates for unsupported but still widely-used Windows operating systems like XP and Windows 2003, citing the discovery of a "wormable" flaw that the company says could be used to fuel a fast-moving malware threat like the WannaCry ransomware attacks of 2017.
The May 2017 global malware epidemic WannaCry affected some 200,000 Windows systems in 150 countries. Source: Wikipedia.
The vulnerability (CVE-2019-0708) resides in the "remote desktop services" component built into supported versions of Windows, including Windows 7, Windows Server 2008 R2, and Windows Server 2008. It also is present in computers powered by Windows XP and Windows 2003, operating systems for which Microsoft long ago stopped shipping security updates.
Microsoft said the company has not yet observed any evidence of attacks against the dangerous security flaw, but that it is trying to head off a serious and imminent threat.
"While we have observed no exploitation of this vulnerability, it is highly likely that malicious actors will write an exploit for this vulnerability and incorporate it into their malware," wrote Simon Pope, director of incident response for the Microsoft Security Response Center.
"This vulnerability is pre-authentication and requires no user interaction," Pope said. "In other words, the vulnerability is 'wormable,' meaning that any future malware that exploits this vulnerability could propagate from vulnerable computer to vulnerable computer in a similar way as the WannaCry malware spread across the globe in 2017. It is important that affected systems are patched as quickly as possible to prevent such a scenario from happening."
The WannaCry ransomware threat spread quickly across the world in May 2017 using a vulnerability that was particularly prevalent among systems running Windows XP and older versions of Windows. Microsoft had already released a patch for the flaw, but many older and vulnerable OSes were never updated. Europol estimated at the time that WannaCry spread to some 200,000 computers across 150 countries. Continue reading →
Patch Tuesday Lowdown, April 2019 Edition
Microsoft today released fifteen software updates to fix more than 70 unique security vulnerabilities in various flavors of its Windows operating systems and supported software, including at least two zero-day bugs. These patches apply to Windows, Internet Explorer (IE) and Edge browsers, Office, Sharepoint and Exchange. Separately, Adobe has issued security updates for Acrobat/Reader and Flash Player.
According to security firm Rapid 7, two of the vulnerabilities — CVE-2019-0803 and CVE-2019-0859 — are already being exploited in the wild. They can result in unauthorized elevation of privilege, and affect all supported versions of Windows.
"An attacker must already have local access to an affected system to use these to gain kernel-level code execution capabilities," Rapid7 researcher Greg Wiseman observed. "However, one of the 32 Remote Code Execution (RCE) vulnerabilities patched today could potentially be used with them in an exploit chain to obtain full control of a system."
Aside from these zero-day privilege escalation flaws, Wiseman said, it's a fairly standard Patch Tuesday.
"Which of course still means that there are bugs that should be patched as soon as possible, such as the eight vulnerabilities classified as critical in the scripting engine used by Microsoft browsers, and CVE-2019-0822 (an RCE in Microsoft Office that can be exploited by convincing a user to open a malicious file)."
Adobe's Patch Tuesday includes security updates for its Flash Player and AIR software, as well as Adobe Reader and Acrobat.
Flash updates are installed along with other monthly Windows patch rollups for consumers, and auto-installed by Google Chrome, but users may need to reboot the operating system (in the case of IE/Edge) or the browser (in Chrome) for the new updates to take effect.
Adobe's actions also sound the death knell for Adobe Shockwave Player, which has at long last reached end-of-life.
That means no more security updates for Shockwave, which has always been something of an ugly stepchild to Flash. That is to say, Shockwave never really got the security attention Flash has received but nevertheless has been just as vulnerable and often lagging months or years behind Flash in terms of updates. Continue reading →
Flash, Windows Users: It's Time to Patch
Adobe and Microsoft each pushed critical security updates to their products today. Adobe's got a new version of Flash Player available, and Microsoft released 14 updates covering more than 75 vulnerabilities, two of which were publicly disclosed prior to today's patch release.
The Microsoft updates affect all supported Windows operating systems, as well as all supported versions of Internet Explorer/Edge, Office, Sharepoint and Exchange Server.
All of the critical vulnerabilities from Microsoft are in browsers and browser-related technologies, according to a post from security firm Qualys.
"It is recommended that these be prioritized for workstation-type devices," wrote Jimmy Graham, director of product management at Qualys. "Any system that accesses the Internet via a browser should be patched."
The Microsoft vulnerabilities that were publicly disclosed prior to today involve Microsoft Exchange Server 2010 through 2016 editions (CVE-2018-0940) and ASP.NET Core 2.0 (CVE-2018-0808), said Chris Goettl at Ivanti. Microsoft says it has no evidence that attackers have exploited either flaw in active attacks online.
But Goettl says public disclosure means enough information was released publicly for an attacker to get a jump start or potentially to have access to proof-of-concept code making an exploit more likely. "Both of the disclosed vulnerabilities are rated as Important, so not as severe, but the risk of exploit is higher due to the disclosure," Goettl said. Continue reading →
'Badlock' Bug Tops Microsoft Patch Batch
Microsoft released fixes on Tuesday to plug critical security holes in Windows and other software. The company issued 13 patches to tackle dozens of vulnerabilities, including a much-hyped "Badlock" file-sharing bug that appears ripe for exploitation. Also, Adobe updated its Flash Player release to address at least two-dozen flaws — in addition to the zero-day vulnerability Adobe patched last week.
Source: badlock.org
The Windows patch that seems to be getting the most attention this month remedies seven vulnerabilities in Samba, a service used to manage file and print services across networks and multiple operating systems. This may sound innocuous enough, but attackers who gain access to private or corporate network could use these flaws to intercept traffic, view or modify user passwords, or shut down critical services.
According to badlock.org, a Web site set up to disseminate information about the widespread nature of the threat that this vulnerability poses, we are likely to see active exploitation of the Samba vulnerabilities soon.
Two of the Microsoft patches address flaws that were disclosed prior to Patch Tuesday. One of them is included in a bundle of fixes for Internet Explorer. A critical update for the Microsoft Graphics Component targets four vulnerabilities, two of which have been detected already in exploits in the wild, according to Chris Goettl at security vendor Shavlik.
Just a reminder: If you use Windows and haven't yet taken advantage of the Enhanced Mitigation Experience Toolkit, a.k.a. "EMET," you should definitely consider it. I describe the basic features and benefits of running EMET in this blog post from 2014 (yes, it's time to revisit EMET in a future post), but the gist of it is that EMET helps block or blunt exploits against known and unknown Windows vulnerabilities and flaws in third-party applications that run on top of Windows. The latest version, v. 5.5, is available here. Continue reading →
Latest Warnings / Time to Patch — 57 Comments
Microsoft Releases Emergency Security Update
Microsoft today deviated from its regular pattern of releasing security updates on the second Tuesday of each month, pushing out an emergency patch to plug a security hole in all supported versions of Windows. The company urged Windows users to install the update as quickly as possible, noting that miscreants already are exploiting the weaknesses to launch targeted attacks.
The update (MS14-068) addresses a bug in a Windows component called Microsoft Windows Kerberos KDC, which handles authenticating Windows PCs on a local network. It is somewhat less of a problem for Windows home users (it is only rated critical for server versions of Windows) but it poses a serious threat to organizations. According to security vendor Shavlik, the flaw allows an attacker to elevate domain user account privileges to those of the domain administrator account.
"The attacker could forge a Kerberos Ticket and send that to the Kerberos KDC which claims the user is a domain administrator," writes Chris Goettl, product manager with Shavlik. "From there the attacker can impersonate any domain accounts, add themselves to any group, install programs, view\change\delete date, or create any new accounts they wish. This could allow the attacker to then compromise any computer in the domain, including domain controllers. If there is a silver lining in this one it is in the fact that the attacker must have a valid domain user account to exploit the vulnerability, but once they have done so, they have the keys to the kingdom."
The patch is one of two that Microsoft had expected to release on Patch Tuesday earlier this month, but unexpectedly pulled at the last moment. "This is pretty severe and definitely explains why Microsoft only delayed the release and did not pull it from the November Patch Tuesday release all together," Goettl said. Continue reading →
Adobe, Microsoft Issue Critical Security Fixes
Adobe and Microsoft today each issued security updates to fix critical vulnerabilities in their software. Microsoft pushed 14 patches to address problems in Windows, Office, Internet Explorer and .NET, among other products. Separately, Adobe issued an update for its Flash Player software that corrects at least 18 security issues.
Microsoft announced 16 bulletins, but curiously two of those are listed as pending. Topping the list of critical updates from Microsoft is a fix for a zero-day vulnerability disclosed last month that hackers have been using in targeted cyber espionage attacks. Another critical patch targets 17 weaknesses in Internet Explorer, including a remotely exploitable vulnerability in all supported versions of Windows that earned a CVSS score of 9.3 (meaning it is highly likely to be exploited in drive-by attacks, and probably soon).
That flaw is a rare "unicorn-like" bug according to IBM X-Force, which discovered and reported the issue privately to Microsoft. In a blog post published today, IBM researchers described how the vulnerability can be used to sidestep the Enhanced Protected Mode sandbox in IE11, as well as Microsoft's EMET anti-exploitation tool that Microsoft offers for free.
"In this case, the buggy code is at least 19 years old, and has been remotely exploitable for the past 18 years," writes IBM researcher Robert Freeman. "Looking at the original release code of Windows 95, the problem is present. In some respects this vulnerability has been sitting in plain sight for a long time, despite many other bugs being discovered and patched in the same Windows library (OleAut32)."
Freeman said while unpatched Internet Explorer users are most at risk from this bug, the vulnerability also could be exploited through Microsoft Office files. "The other attack vectors this vulnerability could work with are Microsoft Office with script macros, for example in Excel documents," Freeman told KrebsOnSecurity. "Most versions of Office (since about 2003) have macros disabled by default so the user would have to enable them (which can be a fairly mindless YES click at the top of the screen). Or if a user is using an old enough version of Office, the macros will be enabled by default."

redpajama_set_name: RedPajamaCommonCrawl


text:
Creative e-Support
Leadership Perspective: The Infinite Game by Simon Sinek
Leave a Comment	/ By Amina Sheikh
A marketer-turned-leadership consultant, famous for his TedX Talks, Simon Sinek, has been transforming individuals, leaders and organizations with his ideas since 2009. Author of several books, aimed at transforming mindsets, has published yet another powerful book which will change the way in which leaders conduct their businesses today.
In this new book, "The Infinite Game", published in October 2018, Simon Sinek discusses the leadership approach required to compete in today's marketplace. The central idea is that business is an infinite game which most people are playing with a dangerously finite mindset. Their focus is on the short term: Beating rivals and meeting quarterly targets; whereas they need to adopt a longer-range approach, – an infinite mindset, "that will lead us to feel inspired every morning, safe when we are at work and fulfilled at the end of each day".
Leaders need to understand that businesses do not have a finish line, the playing field is undefined, continuous and competitors change frequently, as does the business itself. The goal is to outlive your competition. Competitors drop out of the infinite game when they lose the will or resources to stop playing. Resources can be understood as capital, intellectual property, people, technology etc. Developing will-power, requires the following components:
Just cause—More than the "why" or purpose, a just cause is what motivates one to outlive the competition and helps one sustain through hardship and adversity.
Courageous leadership—Leaders need to champion the just cause above anything else. They must be willing to stand up to the pressures of the Management, Board, etc. and stay true to their cause. This may require all leaders in the organization unite to support this " just cause".
Vulnerable team— Time and energy must be invested in building a culture in an organization where people feel safe to be themselves and can safely admit that they don't know something or have made a mistake. They can take appropriate risks without fear of retaliation.
Worthy adversary— Adversaries are acknowledged and treated with respect; however, success or failure isn't measured against them. Ultimately leaders are competing against themselves, and success should be measured against the just cause. Competitors provide the impetus to improve products, services, marketing, etc.
Open playbook— Organizations pursue a variable cause with a fixed strategy, rather than pursuing a fixed cause with a variable strategy. Having an open playbook means leaders and organizations are willing to have flexible plans that change as needed to pursue their just cause and strategies are made transparent, so all team members can be on the same page.
An infinite leader builds a culture so strong, that when the leader is no longer there, the culture lives on which is committed to fulfilling the leader's just cause which lasts far beyond the time of the leader's tenure. To build such a culture, inspire trust and innovation and build a sustainable business, leaders need to transform existing products and develop products which are beneficial for the buyers, take decisions for the betterment of not only themselves but also their stakeholders, and embrace technological advancements, organizational change and uncertainty.
1. Conley, Randy. "Simon Sinek's 5 Steps for Mastering the 'Infinite' Game of Leadership." Blanchard LeaderChat, 27 Oct. 2017, leaderchat.org/2017/10/27/simon-sineks-5-steps-for-mastering-the-infinite-game-of-leadership/.
2. Hill, Andrew. "Simon Sinek: the next Generation Must Test Leaders' Finite Mindset." Financial Times, Financial Times, 5 July 2019, www.ft.com/content/2a8e0080-96a4-11e9-9573-ee5cbb98ed36.
3. Rizwan, Maryam. "3 Tips to Up Your Game From The Book, The Infinite Game by Simon Sinek." Learning Minds, 11 Sept. 2019, learningmindsgroup.com/3-tips-to-up-your-game-from-the-book-the-infinite-game-by-simon-sinek/.
– Written for LEADIN
World-class and customized leadership development interventions, and specialized consultancy on key matters facing organizational leadership to the young and growing community of business and social leaders in Saudi Arabia.
Download eBrochure
P.O. Box 5323, Riyadh 11422, Kingdom of Saudi Arabia.
+966 55 5483280 (Arabic)
+966 54 4230387 (English)
Copyright © 2022 Lead In
Designed by: HourSolution.org


Randall Bramblett DEVIL MUSIC – Making A Scene!
One of the things you can generally expect when Randall Bramblett releases a new album is that it won't be what you expect…or, at least, that it won't sound like the last one. There are consistent thematic and stylistic threads that bind his collective works together but it is his adventurousness that keeps him especially interesting to long time listeners. His latest, Devil Music, follows this tradition.
Devil Music finds Randall in a decidedly bluesy vein laden with growling, groaning guitars and stories of inhabitants on the periphery of an often indifferent world. Many of the songs seem built for the stage and his superb full band. The title cut—based on a true story of Howlin' Wolf being rejected by his "sanctified" mother when he approached her after he had achieved some success—sets the course for the album's motif of desperation and confusion with both the world at large and the rag and bone shop of the heart. He is joined by some musical luminaries such as Chuck Leavell, Mark Knopfler and Derek Trucks who augment his regular band—bassists extraordinaire Michael Steele and Michael Rhodes, guitarists Davis Causey and Nick Johnson, drummer/percussionist Seth Hendershot and drummer/producer Gerry Hansen—but, as ever, no one seems to trump the song itself. Tasteful and eclectic as ever, the supporting cast bubbles to the surface and shines and then ducks back down into the soup.
RB casts a wide net from a musical stand point—rock, blues, swing, jazz, soul, electronica—without seeming distracted. The title track starts with a keyboard line that almost brings to mind hip hop before being joined by an eerie high register bass line as he testifies in old school blues tradition until the building tension in the music breaks and the band falls into a nasty funk groove and Wolf (presumably) declares, "Mama I can't stop playing that Devil music." But rather than make the song a cartoon Randall examines the cognizant minds of the adversaries. On one hand you have the mother fighting the "mean world spinning and the wrong crowd winning" and on the other a son—though 6'3" and no shrinking violet—needing her unqualified love. The characters—real or conjured—who inhabit Randall's songs have a three dimensional quality to them that is often absent in songwriting.
Wolf seems to hover over the proceedings in a way and it is fitting as Chester Arthur Burnett was himself a complex character having performed with many of the Mt. Rushmore figures in delta blues history and yet at the same time earning an accounting degree towards the end of his life. Bramblett has often written about the unseeable world within the one before our eyes and our perceptions versus reality and in this way a person such as Wolf seems appropriate.
In "Dead in the Water" a slide imitates the famous Howlin' Wolf yodel and many of the songs grind over a lone chord with guitars, organ and distorted voices snarling and moaning back and forth with one another and then entwining. The aquatic imagery and forlorn desperation continue with "Bottom of the Ocean" and, indeed, the proceedings early on seem to be carrying forth under water in a compressed and pressurized world where people drown on dry land.
Derek Trucks delivers an immediately recognizable shimmering and shivering slide to "Angel Child" which Bramblett sings in a falsetto that is not common to his previous recordings. Towards the end Trucks twins the vocal line and once again stakes his claim as one of that rare breed of soloists whose voice one can easily recognize within a few notes. The influence of both Duane and Indian sitar music are apparent in his phrasing.
The lyrics and delivery of them are laugh out loud funny…."I'm sharp as a tack I got my degree/I'm dumb as a brick I can't see what's right in front of me." Here, again, RB speaks to the seen and the unseen with a clarity that gives one the feeling he knows something we don't but then he's always quick to note that he is, ultimately, as blind as the rest of us and riding on a horse called Hope where he is still racked by enough doubt that he has to continually pull the reins to check the animal's face and in so doing winds up on another misdirection of his own making.
Bramblett strikes the listener as an old soul overseeing an endearingly familiar pastoral landscape of saw grass, cat tails, barbed wire and muddy water and the forgotten and damaged souls that tread through and around them. In "Pride and Place"—a full blown rock number—he speaks of "Standing in the knee high grass going to blow away watching shiny cars go screaming past." In this "New South" of which he may be one of our greatest poets there seem to be two camps—the haves and the have nots—revolving around and often oblivious to one another and, in every soul, the yearning for meaning and the concurrent desire to shut down.
As within a single song the album itself gyrates in extreme directions, such as the electronic textural jazz of "Whiskey Headed Woman" or the sparse, acoustic piano driven "Ride," which reminds me of something from The Meantime, but then finds its way back to the heart of the matter. His instrumentation is always a combination of the new and the old. The musicianship of the players he attracts speaks for itself but ambient loops and the like are in the mix to thicken the broth in a way that rewards multiple and deeper listenings.
Devil Music is just the latest jewel in the crown of Bramblett's incredibly prolific career. To have such an extraordinary voice from the South who holds the past in reverence but is not trapped by it nor obsessed by the present or future is a true treat. Having a restless souled artist of such pedigree simply follow his muse and see where he winds up is a rewarding ride for the listener of serious grown folks music. So, I beg of you, Randall, don't stop playing that Devil music.


Formalin Preserved Pigs, Double Injection is rated 5.0 out of 5 by 4.
Our standard formalin pigs, shipped in Carosafe®, are available in pails or in damp-packed, vacuum-sealed bags. With these specimens, students can learn vertebrate anatomy and practice dissection skills at the same time; examine organ systems and understand the relationship between structure and function; and investigate similarities and differences between pigs and other mammals, including humans. Prices listed are for 1 specimen. Double color injection: Red latex in arterial system and blue latex in systemic veins.
Our standard formalin pigs, shipped in Carosafe®. Prices listed are for 1 specimen. Choose your preference of packaging: available in pails or in damp-packed, vacuum-sealed bags (your choice of either 1 per bag or bulk bag). Free plastic bags included with all vacuum-packed pigs. Double color injection: Red latex in arterial system and blue latex in systemic veins.
Rated 5 out of 5 by MsTonwnz from Great for my AP Bio Class Last year was my first year teaching AP Bio and after the exam I had my students dissect these and it worked perfectly. I am ordering them again this year.
Rated 5 out of 5 by LMHBioTeach from Great specimens for Anatomy Class!! I have been a biology/anatomy & physiology teacher for five years, so have purchased many specimens over that time. I purchased #228420, the Formalin Preserved 10-13" pigs, for the first time last spring. They are terrific and will be my go to specimen for anatomy from now on! My anatomy classes use the pig specimens for an entire term, as we progress through the organ systems, and these stayed the nicest of any I've tried. These specimens are a perfect size, so that students can easily see all of the components of each organ system very clearly. This made identification easy for both regular lab work and the lab practical examinations. I recommend these specimens most highly to any teacher I collaborate with, and I thank you for providing such wonderful products. Your commitment to quality, customer service, and quick order fulfillment ensure customer happiness. Wishing you and your company continued success.
Rated 5 out of 5 by Susieq90 from Preserved Pig with double injection I dissect a pig every year for my class. My normal place of purchase does not carry the pig anymore. Therefore I came to Carolina and found a pig. The pig did have a huge slice out of the neck which I have not seen on a specimen before.
Rated 5 out of 5 by Biochiton from Excellent Pigs I have used these pigs for the past 10 years in my Human Anatomy class. They are excellent for study of the internal organs and the circulatory system. The preservative is low odor and the pigs hold up well during our 3-week detailed disscetion.


text:
Call for applications: 'learning tour' to Flanders
Etxepare Basque Institute/Flanders Arts Institute/Flanders Ministry of Foreign Affairs
In November 2021, the Etxepare Basque Institute joined forces with the Flanders Ministry of Foreign Affairs and the Flanders Arts Institute to arrange a cultural visit to the Basque Country for Flemish art and culture professionals. The purpose was to spread awareness of Basque culture and create cultural networks and collaborative projects between the two countries.
We are now putting together a visit to Flanders for Basque cultural organisations and professionals can learn about Flemish culture, institutions, stakeholders and creators. These exchanges set out to foster cultural cooperation between FLANDERS – BASQUE COUNTRY in autumn 2022 and all of 2023, with the aim of creating projects with Flemish cultural and creative agents and promote the participation of Basque creators in events and festivals in Flanders.
The Basque art professionals involved in the programme will get to know the organisations and art professionals operating in Flanders, each according to their area of practice and interests.
The tour is open to 15 professionals in the area of Basque culture. The types of meetings with professionals and cultural agents in Flanders will depend on the participants' interests.
Who is the call intended for?
We are looking for cultural professionals (creators, programmers/curators, cultural agents) and arts organisations with a basic interest or knowledge of the Flemish cultural ecosystem who wish to collaborate and can undertake a cooperative project.
The call is open to both individuals and stakeholders/entities.
Applicants must be involved in visual and plastic arts, music, performing arts, audiovisual, literature or multidisciplinary arts practices.
Candidates must submit a bio (entities) or CV (individuals) explaining why they wish to participate in this initiative and the people and/or stakeholders and places they would like to meet in Flanders. They should also include and explanation of their motivation for participating in this project.
Candidates must be available for the full three days of touring plus two travel days.
Dates: outward journey - 31 May; 'learning tour' - 1-2-3 June; return journey - 4 June.
The working tour will be conducted in English. However, translation will be provided, if necessary, by the organising institutions.
The Flanders Ministry of Foreign Affairs and the Flanders Art Institute will cover the costs of the stay (4 nights), including meals and cultural agenda.
The cost of the outward and return journeys for Basque artists, professionals and institutional representatives will be covered by the Etxepare Institute.
Candidates wishing to participate in this working tour are required to complete the following application form and return it no later than 11:59 pm on Friday 31 March 2022.
Apply using the following form: https://forms.gle/VykDjzfLQDf6nTgS9
The Basque delegation will be decided on by a committee of four: two appointed by the Etxepare Basque Institute and two appointed by the Flemish Ministry of Foreign Affairs.
In summer 2022 the Flemish Government and the Presidency of the Basque Government will launch a call for proposals for specific cooperation projects. This call aims to support two-way collaboration projects, both artist exchanges, exchanges of creative projects and possible 'windows' into Basque culture.
These learning tours and the call for projects are part of the Memorandum of Collaboration, which also includes cultural exchange, signed in November 2021 by the governments of Flanders and the Basque Country.
For further information, contact the Etxepare Basque Institute (a-aginagaldelopez@etxepare.eus) or the Flanders Arts Institute (sarah.rombouts@kunsten.be).
Receive alerts in your inbox when calls for proposals of interest to you are launched.


Georges Ugeux is a global financier by trade and at heart. He is the former head of the international group at the New York Stock Exchange and the founder of Galileo Global Advisors. He is a frequent blogger for The Huffington Post and Le Monde in Paris, and teaches financial regulation courses at Columbia Law School.
Mayra Calvani: Please tell us about The Flying Dragon and what compelled you to write it.
Georges Ugeux: I spent my entire life in international finance and was deeply shocked by the financial crisis. I wrote several "serious" non-fiction books on finance. Now is the time to expose the dark side of finance in a crime case. The novel was another way for me to express my feelings about the dark side of finance and I chose a young, Chinese woman as the leading detective (Instead of the men that usually dominate the world of finance).
G.U.: It is a mystery novel set in Hong Kong in the middle of the banking world. The head of derivatives of a large bank falls from a trading room window on the 22nd floor. The detective heading the investigation is a young, beautiful and determined woman, Victoria Leung. She is a Chinese women working for a UK firm and understands the world finance very well. Ramifications from mainland China add some spice to the plot.
M.C.: What themes do you explore in The Flying Dragon?
G.U.: Greed and arrogance in the financial world, passion, sexuality, power, politics and above all the value of people and their emotions. I look at the role of trading in China, homosexuality in the Chinese culture, Chinese relations with Hong Kong, the dark side of banking in general and the strength and vulnerability of Chinese women.
G.U.: I have written several non-fiction books on finance and really wanted to write fiction – so I could create and use my imagination. I let my mind drive the story and was able to share it with readers. It has been very gratifying and fun.
G.U.: When I am at home looking at our gorgeous view of New York City…or on a plane. It is an amazing feeling to really want to be in front of your computer to write.
G.U.: The reason I did not publish a novel earlier is because it is a very different way of writing. A novel is about feelings, people, imagination and memories. Writing correctly and elegantly is critical in order to properly express it with the reader.
G.U.: Sometimes, in the sense that personal experiences play an undeniable role in a novel and the plot and/or characters can be dictated by childhood memories or "remote control" characters. However, those who know me recognize my "voice" in the novel – so I guess I did manage to remain myself.
G.U. : The rereading and the editing process are fairly disciplined, tedious and precise. It is not always fun, but is critical to the reality of the story.
G.U. : The moment I decided on the outcome of the plot. I did not begin writing knowing the ending – it was a discovery!
G.U. : I am currently writing a non-fiction book on central banking and am already thinking about the next adventure of Victoria Leung. So, I guess, I am on a roll!
G.U.: When I receive the first printed copy and started reading it…I was thrilled…It was so real.
G.U.: It is a journey I enjoy very much. Writing has now become a way of expressing myself and since I am a blogger at LeMonde.fr (Paris) and Huffington Post, I write every week. That does not make it an obsession.
G.U. : Yes, there are definitely some chapters in which the inspiration comes from personal experience. The most moving example was a conversation with the parents of the victim. I lost a child understand how it feels. I absolutely drew from that experience.
G.U. : I only drink French and Italian wine with a meal. Never while writing!!!
G.U. : In preparation for this book, I decided it was time to have a personal website. I have included a lot of information, both professional and personal.
My blog in The Huffington post can be found here.