text:
"""Registry for filters and abstract classes for basic filter functionality."""
import collections
import glob
import itertools
import os

import yaml

import logging

from grr.lib import config_lib
from grr.lib import registry
from grr.lib.aff4_objects import collects as collections_aff4
from grr.lib.checks import filters
from grr.lib.checks import hints
from grr.lib.checks import triggers
from grr.lib.rdfvalues import anomaly as rdf_anomaly
from grr.lib.rdfvalues import protodict as rdf_protodict
from grr.lib.rdfvalues import structs as rdf_structs
from grr.proto import anomaly_pb2
from grr.proto import checks_pb2

class Error(Exception):
  """Base error class."""

class DefinitionError(Error):
  """A check was defined badly."""

class ProcessingError(Error):
  """A check generated bad results."""

def ValidateMultiple(component, hint):
  errors = []
  for item in component:
    try:
      item.Validate()
    except (DefinitionError) as e:
      errors.append(str(e))
  if errors:
    raise DefinitionError("%s:\n  %s" % (hint, "\n  ".join(errors)))

def MatchStrToList(match=None):
  # Set a default match type of ANY, if unset.
  # Allow multiple match types, either as a list or as a string.
  if match is None:
    match = ["ANY"]
  elif isinstance(match, basestring):
    match = match.split()
  return match

class CheckResult(rdf_structs.RDFProtoStruct):
  """Results of a single check performed on a host."""
  protobuf = checks_pb2.CheckResult

  def __nonzero__(self):
    return bool(self.anomaly)

  def ExtendAnomalies(self, other):
    """Merge anomalies from another CheckResult."""
    for o in other:
      if o is not None:
        self.anomaly.Extend(list(o.anomaly))

class CheckResultsCollection(collections_aff4.RDFValueCollection):
  """A collection of check results."""
  _rdf_type = CheckResult

class CheckResults(rdf_structs.RDFProtoStruct):
  """All results for a single host."""
  protobuf = checks_pb2.CheckResults

  def __nonzero__(self):
    return bool(self.result)

class Check(rdf_structs.RDFProtoStruct):
  """A definition of a problem, and ways to detect it.

  Checks contain an identifier of a problem (check_id) that is a reference to an
  externally or internally defined vulnerability.

  Checks use one or more Methods to determine if an issue exists. Methods define
  data collection and processing, and return an Anomaly if the conditions tested
  by the method weren't met.

  Checks can define a default platform, OS or environment to target. This
  is passed to each Method, but can be overridden by more specific definitions.
  """
  protobuf = checks_pb2.Check

  def __init__(self,
               initializer=None,
               age=None,
               check_id=None,
               target=None,
               match=None,
               method=None,
               hint=None):
    super(Check, self).__init__(initializer=initializer, age=age)
    self.check_id = check_id
    self.match = MatchStrToList(match)
    self.hint = Hint(hint, reformat=False)
    self.target = target
    if method is None:
      method = []
    self.triggers = triggers.Triggers()
    self.matcher = Matcher(self.match, self.hint)
    for cfg in method:
      # Use the value of "target" as a default for each method, if defined.
      # Targets defined in methods or probes override this default value.
      if hint:
        cfg["hint"] = hints.Overlay(child=cfg.get("hint", {}), parent=hint)
      if target:
        cfg.setdefault("target", target)
      # Create the method and add its triggers to the check.
      m = Method(**cfg)
      self.method.append(m)
      self.triggers.Update(m.triggers, callback=m)
    self.artifacts = set([t.artifact for t in self.triggers.conditions])

  def SelectChecks(self, conditions):
    """Identifies which check methods to use based on host attributes.

    Queries the trigger map for any check methods that apply to a combination of
    OS, CPE and/or label.

    Args:
      conditions: A list of Condition objects.

    Returns:
      A list of method callbacks that should perform checks.
    """
    return self.triggers.Calls(conditions)

  def UsesArtifact(self, artifacts):
    """Determines if the check uses the specified artifact.

    Args:
      artifacts: Either a single artifact name, or a list of artifact names

    Returns:
      True if the check uses a specific artifact.
    """
    # If artifact is a single string, see if it is in the list of artifacts
    # as-is. Otherwise, test whether any of the artifacts passed in to this
    # function exist in the list of artifacts.
    if isinstance(artifacts, basestring):
      return artifacts in self.artifacts
    else:
      return any(True for artifact in artifacts if artifact in self.artifacts)

  def Parse(self, conditions, host_data):
    """Runs methods that evaluate whether collected host_data has an issue.

    Args:
      conditions: A list of conditions to determine which Methods to trigger.
      host_data: A map of artifacts and rdf data.

    Returns:
      A CheckResult populated with Anomalies if an issue exists.
    """
    result = CheckResult(check_id=self.check_id)
    methods = self.SelectChecks(conditions)
    result.ExtendAnomalies([m.Parse(conditions, host_data) for m in methods])
    return result

  def Validate(self):
    """Check the method is well constructed."""
    if not self.check_id:
      raise DefinitionError("Check has missing check_id value")
    cls_name = self.check_id
    if not self.method:
      raise DefinitionError("Check %s has no methods" % cls_name)
    ValidateMultiple(self.method,
                     "Check %s has invalid method definitions" % cls_name)

class Method(rdf_structs.RDFProtoStruct):
  """A specific test method using 0 or more filters to process data."""

  protobuf = checks_pb2.Method

  def __init__(self, initializer=None, age=None, **kwargs):
    if isinstance(initializer, dict):
      conf = initializer
      initializer = None
    else:
      conf = kwargs
    super(Method, self).__init__(initializer=initializer, age=age)
    probe = conf.get("probe", {})
    resource = conf.get("resource", {})
    hint = conf.get("hint", {})
    target = conf.get("target", {})
    if hint:
      # Add the hint to children.
      for cfg in probe:
        cfg["hint"] = hints.Overlay(child=cfg.get("hint", {}), parent=hint)
    self.probe = [Probe(**cfg) for cfg in probe]
    self.hint = Hint(hint, reformat=False)
    self.match = MatchStrToList(kwargs.get("match"))
    self.matcher = Matcher(self.match, self.hint)
    self.resource = [rdf_protodict.Dict(**r) for r in resource]
    self.target = triggers.Target(**target)
    self.triggers = triggers.Triggers()
    for p in self.probe:
      # If the probe has a target, use it. Otherwise, use the method's target.
      target = p.target or self.target
      self.triggers.Add(p.artifact, target, p)

  def Parse(self, conditions, host_data):
    """Runs probes that evaluate whether collected data has an issue.

    Args:
      conditions: The trigger conditions.
      host_data: A map of artifacts and rdf data.

    Returns:
      Anomalies if an issue exists.
    """
    processed = []
    probes = self.triggers.Calls(conditions)
    for p in probes:
      # Get the data required for the probe. A probe can use a result_context
      # (e.g. Parsers, Anomalies, Raw), to identify the data that is needed
      # from the artifact collection results.
      artifact_data = host_data.get(p.artifact)
      if not p.result_context:
        rdf_data = artifact_data["PARSER"]
      else:
        rdf_data = artifact_data.get(str(p.result_context))
      try:
        result = p.Parse(rdf_data)
      except ProcessingError as e:
        raise ProcessingError("Bad artifact %s: %s" % (p.artifact, e))
      if result:
        processed.append(result)
    # Matcher compares the number of probes that triggered with results.
    return self.matcher.Detect(probes, processed)

  def Validate(self):
    """Check the Method is well constructed."""
    ValidateMultiple(self.probe, "Method has invalid probes")
    ValidateMultiple(self.target, "Method has invalid target")
    ValidateMultiple(self.hint, "Method has invalid hint")

class Probe(rdf_structs.RDFProtoStruct):
  """The suite of filters applied to host data."""

  protobuf = checks_pb2.Probe

  def __init__(self, initializer=None, age=None, **kwargs):
    if isinstance(initializer, dict):
      conf = initializer
      initializer = None
    else:
      conf = kwargs
    conf["match"] = MatchStrToList(kwargs.get("match"))
    super(Probe, self).__init__(initializer=initializer, age=age, **conf)
    if self.filters:
      handler = filters.GetHandler(mode=self.mode)
    else:
      handler = filters.GetHandler()
    self.baseliner = handler(artifact=self.artifact, filters=self.baseline)
    self.handler = handler(artifact=self.artifact, filters=self.filters)
    hinter = Hint(conf.get("hint", {}), reformat=False)
    self.matcher = Matcher(conf["match"], hinter)

  def Parse(self, rdf_data):
    """Process rdf data through filters. Test if results match expectations.

    Processing of rdf data is staged by a filter handler, which manages the
    processing of host data. The output of the filters are compared against
    expected results.

    Args:
      rdf_data: An list containing 0 or more rdf values.

    Returns:
      An anomaly if data didn't match expectations.

    Raises:
      ProcessingError: If rdf_data is not a handled type.

    """
    if not isinstance(rdf_data, (list, set)):
      raise ProcessingError("Bad host data format: %s" % type(rdf_data))
    if self.baseline:
      comparison = self.baseliner.Parse(rdf_data)
    else:
      comparison = rdf_data
    found = self.handler.Parse(comparison)
    results = self.hint.Render(found)
    return self.matcher.Detect(comparison, results)

  def Validate(self):
    """Check the test set is well constructed."""
    ValidateMultiple(self.target, "Probe has invalid target")
    self.baseliner.Validate()
    self.handler.Validate()
    self.hint.Validate()

class Filter(rdf_structs.RDFProtoStruct):
  """Generic filter to provide an interface for different types of filter."""

  protobuf = checks_pb2.Filter

  def __init__(self, initializer=None, age=None, **kwargs):
    # FIXME(sebastianw): Probe seems to pass in the configuration for filters
    # as a dict in initializer, rather than as kwargs.
    if isinstance(initializer, dict):
      conf = initializer
      initializer = None
    else:
      conf = kwargs
    super(Filter, self).__init__(initializer=initializer, age=age, **conf)
    filter_name = self.type or "Filter"
    self._filter = filters.Filter.GetFilter(filter_name)

  def Parse(self, rdf_data):
    """Process rdf data through the filter.

    Filters sift data according to filter rules. Data that passes the filter
    rule is kept, other data is dropped.

    If no filter method is provided, the data is returned as a list.
    Otherwise, a items that meet filter conditions are returned in a list.

    Args:
      rdf_data: Host data that has already been processed by a Parser into RDF.

    Returns:
      A list containing data items that matched the filter rules.
    """
    if self._filter:
      return list(self._filter.Parse(rdf_data, self.expression))
    return rdf_data

  def Validate(self):
    """The filter exists, and has valid filter and hint expressions."""
    if self.type not in filters.Filter.classes:
      raise DefinitionError("Undefined filter type %s" % self.type)
    self._filter.Validate(self.expression)
    ValidateMultiple(self.hint, "Filter has invalid hint")

class Hint(rdf_structs.RDFProtoStruct):
  """Human-formatted descriptions of problems, fixes and findings."""

  protobuf = checks_pb2.Hint

  def __init__(self, initializer=None, age=None, reformat=True, **kwargs):
    if isinstance(initializer, dict):
      conf = initializer
      initializer = None
    else:
      conf = kwargs
    super(Hint, self).__init__(initializer=initializer, age=age, **conf)
    if not self.max_results:
      self.max_results = config_lib.CONFIG.Get("Checks.max_results")
    if reformat:
      self.hinter = hints.Hinter(self.format)
    else:
      self.hinter = hints.Hinter()

  def Render(self, rdf_data):
    """Processes data according to formatting rules."""
    report_data = rdf_data[:self.max_results]
    results = [self.hinter.Render(rdf) for rdf in report_data]
    extra = len(rdf_data) - len(report_data)
    if extra > 0:
      results.append("...plus another %d issues." % extra)
    return results

  def Problem(self, state):
    """Creates an anomaly symptom/problem string."""
    if self.problem:
      return "%s: %s" % (state, self.problem.strip())

  def Fix(self):
    """Creates an anomaly explanation/fix string."""
    if self.fix:
      return self.fix.strip()

  def Validate(self):
    """Ensures that required values are set and formatting rules compile."""
    # TODO(user): Default format string.
    if self.problem:
      pass

class Matcher(object):
  """Performs comparisons between baseline and result data."""

  def __init__(self, matches, hint):
    method_map = {
        "NONE": self.GotNone,
        "ONE": self.GotSingle,
        "SOME": self.GotMultiple,
        "ANY": self.GotAny,
        "ALL": self.GotAll
    }
    try:
      self.detectors = [method_map.get(str(match)) for match in matches]
    except KeyError:
      raise DefinitionError("Match uses undefined check condition: %s" % match)
    self.hint = hint

  def Detect(self, baseline, host_data):
    """Run host_data through detectors and return them if a detector triggers.

    Args:
      baseline: The base set of rdf values used to evaluate whether an issue
        exists.
      host_data: The rdf values passed back by the filters.

    Returns:
      A CheckResult message containing anomalies if any detectors identified an
      issue, None otherwise.
    """
    result = CheckResult()
    for detector in self.detectors:
      for finding in detector(baseline, host_data):
        if finding:
          result.ExtendAnomalies(finding)
    if result:
      return result

  def Issue(self, state, results):
    """Collect anomalous findings into a CheckResult.

    Comparisons with anomalous conditions collect anomalies into a single
    CheckResult message. The contents of the result varies depending on whether
    the method making the comparison is a Check, Method or Probe.
    - Probes evaluate raw host data and generate Anomalies. These are condensed
      into a new CheckResult.
    - Checks and Methods evaluate the results of probes (i.e. CheckResults). If
      there are multiple probe results, all probe anomalies are aggregated into
      a single new CheckResult for the Check or Method.

    Args:
      state: A text description of what combination of results were anomalous
        (e.g. some condition was missing or present.)
      results: Anomalies or CheckResult messages.

    Returns:
      A CheckResult message.
    """
    result = CheckResult()
    # If there are CheckResults we're aggregating methods or probes.
    # Merge all current results into one CheckResult.
    # Otherwise, the results are raw host data.
    # Generate a new CheckResult and add the specific findings.
    if results and all(isinstance(r, CheckResult) for r in results):
      result.ExtendAnomalies(results)
    else:
      result.anomaly = rdf_anomaly.Anomaly(
          type=anomaly_pb2.Anomaly.AnomalyType.Name(
              anomaly_pb2.Anomaly.ANALYSIS_ANOMALY),
          symptom=self.hint.Problem(state),
          finding=self.hint.Render(results),
          explanation=self.hint.Fix())
    return result

  def GotNone(self, _, results):
    """Anomaly for no results, an empty list otherwise."""
    if not results:
      return self.Issue("Missing attribute", ["Expected state was not found"])
    return []

  def GotSingle(self, _, results):
    """Anomaly for exactly one result, an empty list otherwise."""
    if len(results) == 1:
      return self.Issue("Found one", results)
    return []

  def GotMultiple(self, _, results):
    """Anomaly for >1 result, an empty list otherwise."""
    if len(results) > 1:
      return self.Issue("Found multiple", results)
    return []

  def GotAny(self, _, results):
    """Anomaly for 1+ results, an empty list otherwise."""
    if results:
      return self.Issue("Found", results)
    return []

  def GotAll(self, baseline, results):
    """Anomaly if baseline vs result counts differ, an empty list otherwise."""
    num_base = len(baseline)
    num_rslt = len(results)
    if num_rslt > num_base:
      raise ProcessingError("Filter generated more results than base data: "
                            "%s > %s" % (num_rslt, num_base))
    if num_rslt == num_base and num_base > 0:
      return self.Issue("Found all", results)
    return []

class CheckRegistry(object):
  """A class to register the mapping between checks and host data.

  This is used to trigger all relevant checks when we collect the data.
  The method registry maps the combination of platform, environment and host
  data required by a given method.
  """
  checks = {}

  triggers = triggers.Triggers()

  @classmethod
  def Clear(cls):
    """Remove all checks and triggers from the registry."""
    cls.checks = {}
    cls.triggers = triggers.Triggers()

  @classmethod
  def RegisterCheck(cls, check, source="unknown", overwrite_if_exists=False):
    """Adds a check to the registry, refresh the trigger to check map."""
    if not overwrite_if_exists and check.check_id in cls.checks:
      raise DefinitionError("Check named %s already exists and "
                            "overwrite_if_exists is set to False." %
                            check.check_id)
    check.loaded_from = source
    cls.checks[check.check_id] = check
    cls.triggers.Update(check.triggers, check)

  @staticmethod
  def _AsList(arg):
    """Encapsulates an argument in a list, if it's not already iterable."""
    if isinstance(arg, basestring) or not isinstance(arg, collections.Iterable):
      return [arg]
    else:
      return list(arg)

  @classmethod
  def Conditions(cls, artifact=None, os_name=None, cpe=None, labels=None):
    """Provide a series of condition tuples.

    A Target can specify multiple artifact, os_name, cpe or label entries. These
    are expanded to all distinct tuples. When an entry is undefined or None, it
    is treated as a single definition of None, meaning that the condition does
    not apply.

    Args:
      artifact: Names of artifacts that should trigger an action.
      os_name: Names of OS' that should trigger an action.
      cpe: CPE strings that should trigger an action.
      labels: Host labels that should trigger an action.

    Yields:
      a permuted series of (artifact, os_name, cpe, label) tuples.
    """
    artifact = cls._AsList(artifact)
    os_name = cls._AsList(os_name)
    cpe = cls._AsList(cpe)
    labels = cls._AsList(labels)
    for condition in itertools.product(artifact, os_name, cpe, labels):
      yield condition

  @classmethod
  def FindChecks(cls,
                 artifact=None,
                 os_name=None,
                 cpe=None,
                 labels=None,
                 restrict_checks=None):
    """Takes targeting info, identifies relevant checks.

    FindChecks will return results when a host has the conditions necessary for
    a check to occur. Conditions with partial results are not returned. For
    example, FindChecks will not return checks that if a check targets
    os_name=["Linux"], labels=["foo"] and a host only has the os_name=["Linux"]
    attribute.

    Args:
      artifact: 0+ artifact names.
      os_name: 0+ OS names.
      cpe: 0+ CPE identifiers.
      labels: 0+ GRR labels.
      restrict_checks: A list of check ids to restrict check processing to.

    Returns:
      the check_ids that apply.
    """
    check_ids = set()
    conditions = list(cls.Conditions(artifact, os_name, cpe, labels))
    for chk_id, chk in cls.checks.iteritems():
      if restrict_checks and chk_id not in restrict_checks:
        continue
      for condition in conditions:
        if chk.triggers.Match(*condition):
          check_ids.add(chk_id)
          break  # No need to keep checking other conditions.
    return check_ids

  @classmethod
  def SelectArtifacts(cls,
                      os_name=None,
                      cpe=None,
                      labels=None,
                      restrict_checks=None):
    """Takes targeting info, identifies artifacts to fetch.

    Args:
      os_name: 0+ OS names.
      cpe: 0+ CPE identifiers.
      labels: 0+ GRR labels.
      restrict_checks: A list of check ids whose artifacts should be fetched.

    Returns:
      the artifacts that should be collected.
    """
    results = set()
    for condition in cls.Conditions(None, os_name, cpe, labels):
      trigger = condition[1:]
      for chk in cls.checks.values():
        if restrict_checks and chk.check_id not in restrict_checks:
          continue
        results.update(chk.triggers.Artifacts(*trigger))
    return results

  @classmethod
  def Process(cls,
              host_data,
              os_name=None,
              cpe=None,
              labels=None,
              exclude_checks=None,
              restrict_checks=None):
    """Runs checks over all host data.

    Args:
      host_data: The data collected from a host, mapped to artifact name.
      os_name: 0+ OS names.
      cpe: 0+ CPE identifiers.
      labels: 0+ GRR labels.
      exclude_checks: A list of check ids not to run. A check id in this list
                      will not get run even if included in restrict_checks.
      restrict_checks: A list of check ids that may be run, if appropriate.

    Yields:
      A CheckResult message for each check that was performed.
    """
    # All the conditions that apply to this host.
    artifacts = host_data.keys()
    check_ids = cls.FindChecks(artifacts, os_name, cpe, labels)
    conditions = list(cls.Conditions(artifacts, os_name, cpe, labels))
    for check_id in check_ids:
      # skip if check in list of excluded checks
      if exclude_checks and check_id in exclude_checks:
        continue
      if restrict_checks and check_id not in restrict_checks:
        continue
      try:
        chk = cls.checks[check_id]
        yield chk.Parse(conditions, host_data)
      except ProcessingError as e:
        logging.warn("Check ID %s raised: %s", check_id, e)

def CheckHost(host_data,
              os_name=None,
              cpe=None,
              labels=None,
              exclude_checks=None,
              restrict_checks=None):
  """Perform all checks on a host using acquired artifacts.

  Checks are selected based on the artifacts available and the host attributes
  (e.g. os_name/cpe/labels) provided as either parameters, or in the
  knowledgebase artifact.

  A KnowledgeBase artifact should be provided that contains, at a minimum:
  - OS
  - Hostname or IP
  Other knowldegebase attributes may be required for specific checks.

  CPE is currently unused, pending addition of a CPE module in the GRR client.

  Labels are arbitrary string labels attached to a client.

  Args:
    host_data: A dictionary with artifact names as keys, and rdf data as values.
    os_name: An OS name (optional).
    cpe: A CPE string (optional).
    labels: An iterable of labels (optional).
    exclude_checks: A list of check ids not to run. A check id in this list
                    will not get run even if included in restrict_checks.
    restrict_checks: A list of check ids that may be run, if appropriate.

  Returns:
    A CheckResults object that contains results for all checks that were
      performed on the host.
  """
  # Get knowledgebase, os_name from hostdata
  kb = host_data.get("KnowledgeBase")
  if os_name is None:
    os_name = kb.os
  if cpe is None:
    # TODO(user): Get CPE (requires new artifact/parser)
    pass
  if labels is None:
    # TODO(user): Get labels (see grr/lib/export.py for acquisition
    # from client)
    pass
  return CheckRegistry.Process(
      host_data,
      os_name=os_name,
      cpe=cpe,
      labels=labels,
      restrict_checks=restrict_checks,
      exclude_checks=exclude_checks)

def LoadConfigsFromFile(file_path):
  """Loads check definitions from a file."""
  with open(file_path) as data:
    return {d["check_id"]: d for d in yaml.safe_load_all(data)}

def LoadCheckFromFile(file_path, check_id, overwrite_if_exists=True):
  """Load a single check from a file."""
  configs = LoadConfigsFromFile(file_path)
  conf = configs.get(check_id)
  check = Check(**conf)
  check.Validate()
  CheckRegistry.RegisterCheck(
      check,
      source="file:%s" % file_path,
      overwrite_if_exists=overwrite_if_exists)
  logging.debug("Loaded check %s from %s", check.check_id, file_path)
  return check

def LoadChecksFromFiles(file_paths, overwrite_if_exists=True):
  """Load the checks defined in the specified files."""
  loaded = []
  for file_path in file_paths:
    configs = LoadConfigsFromFile(file_path)
    for conf in configs.values():
      check = Check(**conf)
      # Validate will raise if the check doesn't load.
      check.Validate()
      loaded.append(check)
      CheckRegistry.RegisterCheck(
          check,
          source="file:%s" % file_path,
          overwrite_if_exists=overwrite_if_exists)
      logging.debug("Loaded check %s from %s", check.check_id, file_path)
  return loaded

def LoadChecksFromDirs(dir_paths, overwrite_if_exists=True):
  """Load checks from all yaml files in the specified directories."""
  loaded = []
  for dir_path in dir_paths:
    cfg_files = glob.glob(os.path.join(dir_path, "*.yaml"))
    loaded.extend(LoadChecksFromFiles(cfg_files, overwrite_if_exists))
  return loaded

class CheckLoader(registry.InitHook):
  """Loads checks from the filesystem."""

  # TODO(user): Add check loading from datastore.

  def RunOnce(self):
    LoadChecksFromDirs(config_lib.CONFIG["Checks.config_dir"])
    LoadChecksFromFiles(config_lib.CONFIG["Checks.config_files"])
    logging.debug("Loaded checks: %s", ",".join(sorted(CheckRegistry.checks)))

redpajama_set_name: RedPajamaGithub


text:
Q: How can I use two NotifyIcons in C# without the second one disappearing when i hover the mouse over? I Have a VS2008 app that needs to display two notifyIcons in the System tray. One is the main application icon, which allows quick access to the GUI. The second is a "new message" icon, which is displayed when a new message arrives, and hidden when the user double-clicks on it, much like the new Outlook mail message icon.
The problem i am having is the second message icon is hidden whenever the mouse is moved over the system tray. The first icon behaves as expected, and remains in the system tray while the application is running.
Any ideas?

A: Thanks - this was partly due to windows glitch and a bug in my code.
Seems the icon will not stay visible when showing a baloon tip - it must be forced visible before showing the baloon tip. The icon did not refresh until i moved my mouse over the tray.

redpajama_set_name: RedPajamaStackExchange


text:
William L. McGee & Sandra V. McGee, Authors
"Bill McGee is no armchair historian…He's lived what he writes about whether it's joining the Navy in '42 at age seventeen simply to get into the fight, or cowboying in the West in the postwar '40s, or working in broadcasting in the early days of 1950s and '60s television." — Barnaby Conrad, founder of the Santa Barbara Writers Conference and author of Matador
Books by
The Amphibians Are Coming!
The Solomons Campaigns, 1942-1943: From Guadalcanal to Bougainville
Pacific Express: The Critical Role of Military Logistics in WWII
Bluejacket Odyssey, 1942-1946: Guadalcanal to Bikini
Operation Crossroads, Lest We Forget! 1946
Montana Memoir: The Hardscrabble Years, 1925-1942
The Divorce Seekers: A Photo Memoir of a Nevada Dude Wrangler, 1947-1949
How I Learned to Sell and Make Deals, 1950-1958
The Broadcasting Years, 1958-1989
Learning To Cope with Sight Loss
Be in touch!
Free Download: How To Research/Write Your Military Memoirs
Sandra's "Divorce Nevada Style" site
Bill's Reading Room
Review – Broadcasting & Cable
William L. McGee and Sandra V. McGee / December 13, 2018
Thank you to Michael Malone for his book review in Broadcasting & Cable (see below)…
When I started in the broadcasting industry in 1958, Broadcasting (as the magazine was then called) was the go-to trade publication for people in the business. Glad to see it's still going strong today. -Bill McGee
BOOK REVIEW by Michael Malone
William L. McGee has authored The Broadcasting Years, 1958-1989: Memoir of a Television Pioneer. As the title suggests, McGee spent three-plus decades in the broadcasting business, initially selling syndicated shows, then helping launch KBHK in San Francisco, managing stations, and finally launching his own ad sales outfit, Broadcast Marketing Company.
A cowboy before he worked in television, McGee is a prolific memoirist. He's written books about several chapters of his life, including Montana Memoir: The Hardscrabble Years, 1925-1942; Bluejacket Odyssey, 1942-1946, Guadalcanal to Bikini; Operation Crossroads, Lest We Forget! An Eyewitness Account, Bikini Atomic Bomb Tests 1946; and The Divorce Seekers: A Photo Memoir of a Nevada Dude Wrangler, 1947-1949.
McGee, who is 93, publishes his books through BMC Publications. His wife Sandra is his co-author. . . .
The Broadcasting Years begins with McGee toiling at a dude ranch in Reno, and shifting to television sales after meeting director Norman Tokar. Much of The Broadcasting Years reads a bit dry, though McGee does offer a somewhat compelling glimpse at another era in television, when the martinis flowed during lunch, and the local newspaper was viewed as the enemy of television.
McGee took painstaking notes from his time in television. . . . but he never completely breaks from his cowboy past, leavening the boardroom anecdotes with climbs of Mount Everest and Mount McKinley, hikes through the wilds of Hawaii, and river rafting in Colorado.
A natural raconteur, McGee comes across as a likable chap, with some hard-earned business lessons to pass along. It's a little hard to imagine the book's readership extending beyond those who work in local TV sales–or those who know McGee. But his writing is engaging, and the book moves quickly.
December 13, 2018 in Memoirs. Tags: B&C, Broadcasting & Cable Magazine, Michael Malone, Station to Station blog
Review – Howard "Howie" Reed
COMING SOON … "The Broadcasting Years, 1958-1989: Memoir of a Television Pioneer"
OFF TO THE EDITOR FOR CRITIQUE & REVIEW… Manuscript for "The Broadcasting Years, 1958-1989"
← Scripts for "The Tony Kilgallin Show"
Review – Howard "Howie" Reed →
Be in touch! mcgeebmc@aol.com
Stay posted...click to follow our Blog
75th Anniversary of D-Day (8)
Countdown at Crossroads: A Timeline for 23 Jun – 1 Aug 1946 (18)
Memoirs (21)
Military Histories (16)
More Posts for Operation Crossroads, Bikini Atomic Bomb Tests, 1946 (31)
This & That (30)

redpajama_set_name: RedPajamaCommonCrawl


text:
Home » Sports » Blue Bombers Prospects Lay It All On the Field at Mini-Camp
Blue Bombers Prospects Lay It All On the Field at Mini-Camp
April 28, 2017 3:53 PM | Sports
By Darrin Bauming (@DarrinBauming)
WINNIPEG — Five workouts over three days wrapped up on Friday as the Winnipeg Blue Bombers completed their annual mini-camp at Investors Group Field. Team management, including head coach Mike O'Shea, have a busy weekend ahead, reviewing practice film and notes as the club needs to reduce their overall roster by at least 12 by May 1.
33 young hopefuls — as well as three veteran quarterbacks and free agent signing Kenny Stafford — took part in the camp that the head coach defined as purely for evaluation purposes.
RELATED: Blue Bombers Hopefuls Look to Make an Impression at Mini-Camp
"It's not easy. You've got a bunch of guys who've never been on this size of field, and asking them to not only learn quite a bit of information… but we had the group we wanted to see so that taxes them physically," said O'Shea. "But once camp rolls around it's going to be even harder for them."
Main training camp still a month away. Following a brief rookie camp for first-year CFLers, main camp begins May 28 and runs through, essentially, the entire month of June as the Bombers have a bye in Week 1 of the CFL season following their preseason games June 10 and 15. But all of that time doesn't make the job any easier for general manager Kyle Walters and O'Shea.
"I think there's some guys who stood out out there, and there's some guys that have to keep working," said O'Shea. "It's never easy, but I think some of the decisions at this point, going from 80 — wherever we're at — to 75 is maybe a little easier than going to the final 46."
Generally speaking, the main camp competition resides at three positions on the Bombers depth chart; receiver, defensive back, and middle linebacker. The latter remains at the forefront following the offseason departure of linebacker Khalil Bass who signed as a free agent with the Ottawa RedBlacks following a 2016 season where he lead the Bombers in tackles.
"I think the group we have out there, I don't know what the numbers might be, but there's a lot of good competition," said defensive coordinator Richie Hall. "I'm very impressed by the group of guys we have, even though it's only been a few practices. They're a lot farther along than I thought they'd be."
While depth of talent plays a crucial role in fielding a successful team in pro football, it still all starts and finishes with the lynchpin position — quarterback. After signing the richest contract in team history, it is 100 per cent clear Matt Nichols will be Winnipeg's starting quarterback come the regular season. But who will be the No. 2?
"I'm hungry to play," said five-year veteran Dan LeFevour, who signed with Winnipeg in February. "Any quarterback up here (in the CFL) wants to play, and if you don't, get out of here. Do something else. My goal is to play just like the other three (quarterbacks) that are in the room right now."
"This year I'm even more confident that I can dominate a game rather than just trying to win it or trying to not lose it," said Dominique Davis, who returns for a third season with the Blue Bombers. "This year I feel like if I go in I can really dominate and show that I'm a pretty good quarterback in this league."
Final address from head coach Mike O'Shea as three days of #Bombers minicamp wraps up this afternoon at IGF. pic.twitter.com/z47mOmKxDV
— Darrin Bauming (@DarrinBauming) April 28, 2017
← Previous: Drivers Injured in Two-Vehicle Crash Near Carberry Next: Grab Your Sticks and Play Shinny with Blue Bomber Alumni →
Tags: CFL | Football | Investors Group Field | Winnipeg Blue Bombers


Oh, The Thinks You Can Think! is a wonderful Seuss tribute to the endless possibilities of our imaginations. It was first published in print in 1975 and is filled with make-believe places, animals and past-times, all rhyming, of course. As a digital offering, this one is refreshing, with the addition of meaningful interactivity and light animation to enhance the storyline.
Each page has dozens of question marks that invite little fingers to tap. After tapping the "?" the picture changes, moving the storyline along in a delightful way that reinforces reading comprehension. Sometimes images appear or disappear, move slightly and even change colors. Like the other Seuss titles by Oceanhouse Media, this one also has lovely narration with highlighting, as well as lots of tappable images (for instance, if you tap the sky, the word 'sky' appears and is spoken aloud).
Overall this is a great way to enjoy Dr. Seuss no matter what your age. It is also a great example of an app book with just the right amount of interactive enhancement to enrich the storytelling without overshadowing it. And thanks to Seuss, the storyline is one that is filled with whimsy and encouragement to enjoy our own creativity.
In rhyming verse, this book suggests lots of things an imagination can conjure. There are things like animals, colors, buildings and even whole worlds of make-believe with funny made-up names like "Schlopp" and "snuvs". A flying balloon swimming pool isn't hard to imagine, even. Or flying 'bloogs' that look like fish in the air. It's all possible if you let your mind wander!
For more information on how to use this book for teaching children about philosophy: http://www.teachingchildrenphilosophy.org/wiki/Oh,_the_Thinks_You_Can_Think!


text:
<!DOCTYPE html>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Sphinx Dashboard</title>

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css">
    <link rel="stylesheet" href="{{ url('/css/main.css') }}">

    @yield('head')

                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
                    Toggle navigation

                </button>
                Sphinx Dashboard

                    @if(!(isset($simple_navbar) && $simple_navbar) )

Home

Realms

Users

Logout

                    @endif

        @yield('content')


text:
Introducing Jeremy Chiaroscuro by MacMillan Ross
by FF · Published May 9, 2020 · Updated May 9, 2020
Last night I drank one Martini too many, and I fell asleep watching The Manchurian Candidate--or was it a Gene Autry movie? I woke up near the end of a very lucid dream, and this is the beginning of what I remembered. In the dream I am or was an unemployed French scholar who wanted to meet a very important man. He is writing in his diary...
Jeremy Chiaroscuro is one of the most important men in American politics. Not that he is a politician. Jeremy wants to be a puppet master and not one of the puppets whose only qualification is an insipid face and a case of hairspray. Like his one-time rival Carl Rogue, he was a protégé of the legendary Grant Blackpool, who until his premature death pioneered the science of hardball politicking.
Blackpool had died of a brain cancer, which surprised no one, because he had a very big brain that was filled with enough venom to poison several Midwestern states. Now, if he'd died of a heart attack, that would have amazed anyone who knew him....He was as wily and as mean as a snake, and if Jeremy inherited his wiliness, Rogue got the meanness. "Why waste time being clever," Carl used to ask, "when an anonymous slander or blackmail threat can get the job done?"
Jeremy viewed electioneering as an art in itself. Results were only secondary. He was like the professional gambler who would never win honestly—a sucker's game—so long as he could cheat. It is a question of pride. He devised an approach to campaign commercials that he described as "Subtextualizing." Friendly critics called the method "subliminal implants." His legion of enemies preferred "voodoo."
As these terms suggest, Jeremy designed commercials that won over viewers not by the explicit message but by indirectly planted suggestions. Now, as a campaign technique or legal trick, the method can be traced back at least to Cicero, who famously referred to Clodia's brother as her husband, then corrected himself, saying "I always make that mistake." This generated a big laugh from a jury convinced that the pair had an incestuous liaison. He may have learned it from the famous Willie Horton commercials that suggested, and none too subtly, that Mike Dukakis would give carte blanche to Negro murderers.
Willie Horton was a sledgehammer, so obvious it could eventually be used against Republicans. Jeremy was much harder to pin down. Sometimes he was absolutely Byzantine in the way he played the angles. It was he, as a young Turk in the PR game, who suggested the Viagra commercials to Bob Dole. Older Republican strategists were aghast. Carl Rogue told him that Dole would make himself and the party a laughing-stock. Chiaroscuro observed that Dole and the party had done about all that could be done in that direction. What could have been worse than the Doleman's '96 campaign? The point, he insisted, was to rescue both the candidate and the party by suggesting indirectly that they were not a bunch of desiccated Kansas rubes but obsessive sex machines that would go on fornicating all the way to the grave.
"Look at Clinton, he exclaimed. "Apart from a few old Republican garden-party hags, people love him, women as much as men. Even the rape charges did not put off the lesbian femininists who will adore him forever!" Years later, during the #metoo hysteria, and older and tamer Jeremy liked to point out the accuracy of his prediction.
Jeremy, it hardly needs saying, thought Newt Gingrich was crazy to attack Bill Clinton, and not just because Newt's own private life was hardly more creditable than the President's. Great men are often scoundrels. "Look at Julius Caesar and Napoleon, look at Jack Kennedy for Chrissake. They lied, cheated, and stole; they murdered and they whored, but the people loved them. Nixon, on the other hand, was a faithful husband, and look where that gets him."
Over the years, I had heard a great deal about the Chiaroscuro touch and wanted to meet him. I was working on a book—a sort of new take on La Bruyère's Characters—and I thought a portrait of a modern king-maker would be just the thing for a book with a working title: Frauds, Conmen. and Assorted Jerks. Circumstances had made it neceessary to earn a few dollars, and I had lots of time on my hands.
Fortunately, I had a few friends who had known Grant Blackpool back in C----, and they assured the genius that I was a harmless crank, the kind of highbrow philosopher-type who could be an eyewitness to murder and the murderer would get off, because I'd be so busy picking logical nits and looking for the big picture that I'd never make sense of the obvious facts. Besides, even if I were to attack Chiaroscuro, they added, no one would pay any attention to a failed scholar who let a confederacy of dunces bounce him out of the research foundation he'd devoted half his life to.
"So, I'm convinced. He's harmless. That doesn't mean I should let him in the door. What's in it for me? Why should I waste my time talking to a loser?"
That was certainly the correct question, but fortunately my old friend Andy Vaught, knew the right thing to say. Andy's a long-time journalist, which means he is an inveterate liar, who can only be taken seriously when he is joking or pretending to lie. Andy reassured the great man.
"These geeks sometimes give you a different perspective on things, you know, new material from other times. Someone once called this guy, 'a breath of musty air.' He's an expert on 17th century France."
"Those French guys are all dead. They can't do me any good today, can they?"
"Maybe not, but back then, they had angles too. You'd be surprised. They put over some brilliant deals nobody knows about any more. Just to stay alive back then, you had to be damn clever. What have you got to lose, Jerry? You're on lockdown with the third wife you can't stand. This'll give you a little variety. If the guy starts to bother you, you can always throw him out."
Prompted by such recommendations, the great man agreed to see me on a Saturday evening he was going to spend, as he always does, watching television……
The Fleming Foundation
Robert Reavis says:
This is hilarious and I enjoyed it very much before I realized unfortunately it is also based on true events and characters such as Carl Rogue who once famously said "those French guys are all dead and old Europe can't do any of us any good any more (if it ever really did) and that's a good thing so get over it!"
Brent says:
I really appreciate the names. Not Lee, but Grant, and "at" becomes "black" (ater in Latin), "water" becomes pool. Lots of fun. Looking forward to the next installment…
Thomas Fleming says:
Shhhh! None of this has any relation to real events. Brent is as mad as my friend Anterus Smith, who, when the Shakespearean question "What's in a name?" was put to him answered, ""A lot, maybe everything." My good friend Mac Ross, who recently survived a near-fatal boating "accident" had this nightmare ten years ago. I came across it just today in primitive form. To my knowledge he never published his early draft, and I have persuaded him to disclose all his conversations–which continue up to the present–with Jeremy Chiaroscuro.
Next story Cracks in the Quarantine
Previous story Wednesday's Child: Fringe Benefits
The Fleming Foundation > Access > Free Content > Introducing Jeremy Chiaroscuro by MacMillan Ross


text:
Order from the powerHouse Arena Shop
Introduction by Maira Kalman
Contribution by Dita Von Teese
Fashion / Design / The Art of Aging Hardcover
240 pages, over 200 full-color photographs
$35 US
Advanced Style is Ari Seth Cohen's blog-based-ode to the confidence, beauty, and fashion that can only be achieved through the experience of a life lived glamorously. It is a collection of street fashion unlike any seen before—focused on the over-60 set in the world's most stylish locales. The (mostly) ladies of Advanced Style are enjoying their later years with grace and panache, marching to the beat of their own drummer. These timeless images and words of wisdom provide fashion inspiration for all ages and prove that age is nothing but a state of mind.
Ari Seth Cohen started his blog inspired by his own grandmother's unique personal style and his lifelong interest in the put-together fashion of vibrant seniors. Each of his subjects sparkles like a diamond after long years spent refining and perfecting their individual look and approach to life. The Advanced Style book will showcase, in luscious full-color, the best of the blog, but will also act as a true guidebook with all-new material featuring the full wardrobes, interviews, stories, and advice of a cadre of his most chic subjects, along with a large selection of never-before-seen photography—fresh off of sidewalk catwalks around the world! Ari Seth Cohen is a freelance writer, photographer, and blogger based in New York City. He is the creator of Advanced Style, a blog devoted "to capturing the sartorial savvy of the senior set." Advanced Style has appeared in national media such as The New York Times, The New Yorker, Los Angeles Times, The Huffington Post, Vice Magazine, New York Magazine, The Fader, Vogue Japan, Vogue Italia, Elle, Elle UK, The UK Telegraph, Forbes.com, and internationally broadcast news and fashion programs.
Maira Kalman is an author and illustrator of over a dozen children's books. Additionally, her two-year-long, illustrated columns for The New York Times online have been published as the books The Principles of Uncertainty (Penguin, 2007), and And the Pursuit of Happiness (Penguin, 2010). In 2011 a retrospective of her work was mounted at the Jewish Museum in NYC. She is represented by the Julie Saul Gallery, and lives and works in New York City.
Dita Von Teese is a world-famous burlesque artist and lingerie model. Best known for her Cocktail Glass show in which she performs an old fashioned striptease that culminates with her bathing herself in an oversized champagne or martini glass. This "Burlesque Superheroine" (Vanity Fair) is credited by many for sparking a revival of traditional burlesque, and has appeared in a number of films, music videos, and television shows. Von Teese has released DVDs of her own performances and is the author of Dita: Stripteese (It Books, 2009).