Browse Source

added software update history retrieval

master
boB Rudis 6 years ago
parent
commit
68fe180879
No known key found for this signature in database GPG Key ID: 1D7529BE14E2BBA9
  1. 5
      DESCRIPTION
  2. 5
      NAMESPACE
  3. 4
      R/mactheknife-package.R
  4. 61
      R/su-hist-file.R
  5. 11
      R/utils.R
  6. 19
      README.Rmd
  7. 36
      README.md
  8. 21
      man/software_update_history.Rd

5
DESCRIPTION

@ -23,4 +23,9 @@ Suggests:
Depends:
R (>= 3.2.0),
reticulate
Imports:
sys,
xml2,
purrr,
anytime
RoxygenNote: 6.0.1.9000

5
NAMESPACE

@ -1,4 +1,9 @@
# Generated by roxygen2: do not edit by hand
export(read_dsstore)
export(software_update_history)
import(reticulate)
import(sys)
import(xml2)
importFrom(anytime,anytime)
importFrom(purrr,map_df)

4
R/mactheknife-package.R

@ -6,5 +6,7 @@
#' @name mactheknife
#' @docType package
#' @author Bob Rudis (bob@@rud.is)
#' @import reticulate
#' @import reticulate sys xml2
#' @importFrom purrr map_df
#' @importFrom anytime anytime
NULL

61
R/su-hist-file.R

@ -0,0 +1,61 @@
#' Retrieve Software Update history
#'
#' Modern macOS "Software Update" history is preserved in the
#' `/Library/Receipts/InstallHistory.plist` proeprty list file. The default
#' behaviour is to use this file as a source and parse the property list into
#' a data frame (tibble). The caller can also provide a path to a valid
#' property list "Software Update" history file (i.e. a systems administrator
#' may want to analyze a collected inventory of "Software Update" history files
#' from all the macOS systems on her network).
#'
#' @md
#' @param su_hist_file path to "Software Update" history file
#' @export
software_update_history <- function(su_hist_file = "/Library/Receipts/InstallHistory.plist") {
su_hist_file <- path.expand(su_hist_file)
su_hist_file <- normalizePath(su_hist_file)
if (!file.exists(su_hist_file)) stop("'hist_file' not found.", call.=FALSE)
doc <- xml2::read_xml(su_hist_file)
kids <- xml2::as_list(xml2::xml_children(doc))
shld_be_dict <- unique(names(kids[[1]]))
if (!((length(shld_be_dict) == 1) & (shld_be_dict[1] == "dict"))) {
stop("Not a valid plist file.", call.=FALSE)
}
purrr::map_df(1:length(kids[[1]]), function(.j) {
grandkids <- kids[[1]][[.j]]
nm <- names(grandkids)
keys <- which(nm == "key")
dat <- vector("list", length(keys))
keynms <- vector("character", length(keys))
j <- 1
for (i in keys) {
key_name <- grandkids[[i]][[1]]
keynms[j] <- key_name
val_type <- names(grandkids[i+1])
val <- switch(
val_type,
"string" = unlist(grandkids[[i+1]]),
"date" = anytime::anytime(unlist(grandkids[[i+1]])),
"integer" = as.integer(unlist(grandkids[[i+1]])),
"real" = as.numeric(unlist(grandkids[[i+1]])),
"true" = TRUE,
"false" = FALSE,
"array" = list(setNames(list(unlist(grandkids[[i+1]], use.names=FALSE)), key_name)),
"data" = "TODO",
"UNKNOWN - TODO"
)
if (length(val) == 0) val <- NA
dat[j] <- as.list(val)
j <- j + 1
}
setNames(dat, keynms)
}) -> xdf
xdf[,c("displayName", "displayVersion", "date", "packageIdentifiers", "processName", "contentType")]
}

11
R/utils.R

@ -1,3 +1,12 @@
is_url <- function(path) {
grepl("^(http|ftp)s?://", path)
}
}
mlga <- function(x) {
x <- tolower(x)
x <- gsub("[[:punct:][:space:]]+", "_", x)
x <- gsub("_+", "_", x)
x <- gsub("(^_|_$)", "", x)
x <- make.unique(x, sep = "_")
x
}

19
README.Rmd

@ -17,6 +17,7 @@ A set of tools/methods and data that are geared towards the 'macOS' ecosystem.
## What's Inside The Tin
- `read_dsstore`: Read a '.DS_Store' from a file/URL
- `software_update_history`: Retrieve Software Update history
The following functions are implemented:
@ -40,7 +41,9 @@ packageVersion("mactheknife")
```
## `.DS_Store` example using built-in data
### `.DS_Store` example
Using built-in data
```{r}
read_dsstore(
@ -48,13 +51,17 @@ read_dsstore(
)
```
## A URL I should not have let a `.DS_Store` file lying around in
### From a URL
A URL I should not have let a `.DS_Store` file lying around in
```{r}
read_dsstore("https://rud.is/books/21-recipes/.DS_Store")
```
## `.DS_Store` larger example using my "~/projects" folder (use your own dir as an example)
### A Directory of`.DS_Store`s
A larger example using my "~/projects" folder (use your own dir as an example).
```{r}
library(magrittr)
@ -67,3 +74,9 @@ list.files(
str(x)
```
### "Software Update" History
```{r}
software_update_history()
```

36
README.md

@ -15,6 +15,7 @@ ecosystem.
## What’s Inside The Tin
- `read_dsstore`: Read a ‘.DS\_Store’ from a file/URL
- `software_update_history`: Retrieve Software Update history
The following functions are implemented:
@ -35,7 +36,9 @@ packageVersion("mactheknife")
## [1] '0.1.0'
## `.DS_Store` example using built-in data
### `.DS_Store` example
Using built-in data
``` r
read_dsstore(
@ -45,7 +48,10 @@ read_dsstore(
## [1] "favicon.ico" "flag" "static" "templates" "vulnerable.py" "vulnerable.wsgi"
## A URL I should not have let a `.DS_Store` file lying around in
### From a URL
A URL I should not have let a `.DS_Store` file lying around
in
``` r
read_dsstore("https://rud.is/books/21-recipes/.DS_Store")
@ -54,7 +60,10 @@ read_dsstore("https://rud.is/books/21-recipes/.DS_Store")
## [1] "06-Creating-a-Graph-of-Retweet-Relationships_files" "07-Visualizing-a-Graph-of-Retweet-Relationships_files"
## [3] "20-Visualizing-Geodata-with-a-Dorling-Cartogram_files" "libs"
## `.DS_Store` larger example using my “~/projects” folder (use your own dir as an example)
### A Directory of`.DS_Store`s
A larger example using my “~/projects” folder (use your own dir as an
example).
``` r
library(magrittr)
@ -90,3 +99,24 @@ str(x)
## $ : chr "plots"
## $ : chr [1:2] "top-1m.csv" "top-1m.csv.zip"
## $ : chr(0)
### “Software Update” History
``` r
software_update_history()
```
## # A tibble: 590 x 6
## displayName displayVersion date packageIdentifiers processName contentType
## <chr> <chr> <dttm> <list> <chr> <chr>
## 1 Chinese Word List Update 5.7 2017-01-23 16:01:55 <chr [1]> softwareupdated config-data
## 2 MRT Configuration Data 1.14 2017-01-23 16:02:53 <chr [1]> softwareupdated config-data
## 3 Gatekeeper Configuration Data 107 2017-01-23 16:02:55 <chr [1]> softwareupdated config-data
## 4 XProtectPlistConfigData 1.0 2017-01-23 16:03:16 <chr [1]> softwareupdated config-data
## 5 iTunes 12.5.4 2017-01-23 16:04:43 <chr [5]> softwareupdated <NA>
## 6 GarageBand 10.1.3 2017-01-23 16:06:48 <chr [1]> storedownloadd <NA>
## 7 OneDrive 17.3.6725 2017-01-23 16:06:54 <chr [1]> storedownloadd <NA>
## 8 Table Tool 1.1.2 2017-01-23 16:06:55 <chr [1]> storedownloadd <NA>
## 9 Degrees Pro 4.2.1 2017-01-23 16:06:56 <chr [1]> storedownloadd <NA>
## 10 WordService 2.8.1 2017-01-23 16:06:57 <chr [1]> storedownloadd <NA>
## # ... with 580 more rows

21
man/software_update_history.Rd

@ -0,0 +1,21 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/su-hist-file.R
\name{software_update_history}
\alias{software_update_history}
\title{Retrieve Software Update history}
\usage{
software_update_history(su_hist_file = "/Library/Receipts/InstallHistory.plist")
}
\arguments{
\item{su_hist_file}{path to "Software Update" history file}
}
\description{
Modern macOS "Software Update" history is preserved in the
\code{/Library/Receipts/InstallHistory.plist} proeprty list file. The default
behaviour is to use this file as a source and parse the property list into
a data frame (tibble). The caller can also provide a path to a valid
property list "Software Update" history file (i.e. a systems administrator
may want to analyze a collected inventory of "Software Update" history files
from all the macOS systems on her network).
}
Loading…
Cancel
Save