LuaCASC is an implementation of the CASC file system in Lua, capable of reading from local installations and/or CDN-hosted data.

Dependencies

You should additionally install the following Lua modules, which enable certain LuaCASC functionality and improve performance:

On Windows, you may use the following binaries, which require only the VS2013 run-time components to be installed:

Installation

The casc/ directory should go somewhere matched by Lua's package.path. This might be the current working directory, /usr/local/share/lua/5.1/, or the lua subdirectory in the directory containing your Lua executable.

The included casc/bin.c file can optionally be compiled as a shared library (as casc/binc.{so,dll}), placed into a path searched via package.cpath.

Using LuaCASC

You can use LuaCASC to read information from locally-stored Data directories, from CDNs, or both at the same time, using local data when it has already been downloaded.

local casc = require("casc")
local handle, err = casc.open("./World of Warcraft/", {verifyHashes=false})
if not handle then
   -- Could not select a local build; query the patch server instead
   handle, err = casc.open("http://us.patch.battle.net:1119/wow/#eu")
end
local content = assert(handle:readFile("Interface/Icons/Temp.blp"))
local h = io.open("Temp.blp", "w")
h:write(content)
h:close()

Additional examples are included in examples/ directory of the ZIP file.

API Functions

casc = require("casc")
Loads the LuaCASC module.
handle = casc.open(conf)
Returns a new handle to a CASC data store specified by the conf table, or, in case of errors, nil and an error message. The following keys can be set in conf:
bkey (string)
MD5 hash of the build configuration file, 32-character hexadecimal string.
base (string, optional)
Path to the local Data directory to load local content from.
cdn (string/table, optional)
CDN base URL(s) to download data from. If a table containing multiple base URLs is passed, LuaCASC will automatically switch CDN hosts when a download fails and try again.
ckey (string, required with cdn)
MD5 hash of the CDN configuration file, 32-character hexadecimal string.
cache (string or boolean, default: true)
Path to a directory that will be used to cache metadata downloaded from the CDN, or false to disable local caching. If true, the value of the LUACASC_CACHE environment variable is used as the cache path.
cacheFiles (boolean, optional)
Boolean value indicating whether file content retrieved from the CDN (using the readFile* functions on the CASC handle) should also be cached locally.
verifyHashes (boolean, default: true)
Boolean value indicating whether LuaCASC should verify MD5 hashes prior to returning file content.
locale (function or string, optional)
Specifies the ranking function used when looking up file data based on a file name or ID. Pass one of the keys in casc.locale (BR, CN, DE, ES, FR, GB, IT, KR, MX, PT, RU, TW, US) to prefer that locale; alternatively, pass a function which, given a candidate variant's (localeFlags, typeFlags, isRemote), returns either a number indicating preference for that variant (greater values indicate more preferable variants), or a falsy value indicating that the variant is unaceptable, and should not be returned.
If not specified, a default ranking function is used, preferring locally available, British English files, in that order.
mergeInstall (boolean/string, default: false)
If truthy, files installed outside the CASC store will be made available through the handle:read* methods using the CDN. If a string is specified, it is interpreted as a semicolon-delimited list of file tags; only files matching all specified tags will be made accessible.
Common file tags are: x86_32, x86_64, OSX, Windows.
usePatchEntries (boolean, default: true)
If true, prefers applying CASC-provided patches to locally-available files when possible, avoiding downloading a full-size updated version from the CDN. This may reduce the amount of network traffic required.
requireRootFile (boolean, default: true)
If set to false, LuaCASC will create a CASC handle even if it fails to parse the root file. This allows retrieving content using content or encoding hashes, but not file names or IDs.
keys (table, default: nil)
An optional table mapping encryption key names to keys, both expressed as hexadecimal strings. Entries in this table override those returned by the user-provided casc.keys module, which is automatically loaded if it exists.
zerofillEncryptedChunks (boolean, default: false)
If true, BLTE chunks encrypted using unknown keys will be replaced by a block of zero bytes, disabling content hash verification for the file. If false, attempting to read a file with such a chunk will fail.
pathFileIDLookup (function, default: nil)
If provided, this function is called when the root file does not provide a mapping for a file path passed to various handle methods. The function is passed (path, pathHash) as arguments, and should return the file ID corresponding to the path (a number value).
At least one of conf.base and (conf.cdn, conf.ckey) must be provided.
handle = casc.open("localRoot"[, conf])
handle = casc.open("patchURL"[, conf])
Returns a new handle to a CASC data store, or nil and an error message if an error occurs. Equivalent to calling casc.open(casc.conf(...)).
conf = casc.conf("localRoot"[, conf])
Returns a CASC configuration table based on a local installation.localRoot specifies a path:
  • To a directory containing a Data directory and a .build.info file. Build and CDN configuration will be derived from the .build.info file, selecting a build marked active.
  • To a directory containing a .flavor.info file, and, with the last component removed, to a directory containing the a Data directory and a .build.info file. Build and CDN configuration will be derived from the .build.info file, selecting a build of the appropriate flavor, and preferring builds marked active.
If the conf table is provided, its keys override those derived from the .build.info file. Note that .build.info includes CDN configuration, allowing files not available locally to be retrieved from the CDN. To only use local files, set conf.cdn = false.
conf = casc.conf("patchURL"[, conf])
Returns a CASC configuration table based on values retrieved from a remote patch server. patchURL specifies the patch server to query; http and ribbit protocols are supported. The URL should contain the server address, port number (optional), a path component specifying the product, and a fragment identifier specifying the desired region. For HTTP patch servers, the path component specifies the path to the directory containing versions and cdns files on the CDN. If the conf table is provided, its keys override those derived from the patch server.
"bkey", cdn, "ckey", "version", build = casc.cdnbuild("patchBase", "region")
Returns information about the build offered by the patch server for a particular region:
patchBase
URL specifying the patch server to query, terminating with the directory containing the versions and cdns files.
region
Region name to return current build information for, e.g. eu.
bkey
MD5 hash of the build configuration file; 32-character hexadecimal string.
cdn
Base URL(s) for a CDN host serving the build.
ckey
MD5 hash of the CDN configuration file; 32-character hexadecimal string.
version
Version string.
build
Build number.
If an error occurs, this function returns nil and an error message.
"bkey", cdn, "ckey", "version" = casc.localbuild("buildInfoPath", selectBuild)
Parses the .build.info file specified by buildInfoPath, and calls selectBuild to determine which build to return information about. You may use casc.selectActiveBuild to select the build marked Active in the local installation.
If an error occurs, this function returns nil and an error message.
regions, versions, cdns = casc.cdnbuild("patchURL")
Returns information about all regions and CDNs listed at the specified CDN root.
branches, buildInfo = casc.localbuild("buildInfoPath")
Returns information about all locally-available builds.
handle:setLocale("localeKey" or rankFunc or nil)
Changes the handle's locale, determining which file variant is retrieved by handle:readFile("path"); see conf.locale for possible values.
variants = handle:getFileVariants("path" or fileID)
For a given file, identified by a virtual path (e.g. Interface/FrameXML/FrameXML.toc) or file ID (e.g. 841788), returns a table mapping available content hashes to an array of locale idenfiers (e.g. GB) the variant is flagged for. The path is case insensitive; \ and / are interchangeable.
If an error occurs, returns nil and an error message.
"hash" = handle:getFileContentHash("path" or fileID[, locale])
Returns the content hash of a file identified by a virtual path (e.g. Interface/FrameXML/FrameXML.toc) or file ID (e.g. 841788). If locale is specified, it overrides the handle's current locale. The path is case insensitive; \ and / are interchangeable.
If an error occurs, returns nil and an error message.
"content" = handle:readFile("path" or fileID[, locale[, cache]])
Returns content of the file specified by a virtual path (e.g. Interface/FrameXML/FrameXML.toc) or file ID (e.g. 841788). If specified, cache overrides conf.cacheFiles for this operation.
Equivalent to handle:readFileByContentHash(handle:getFileContentHash(path, locale), cache).
If an error occurs, returns nil and an error message.
"content" = handle:readFileByEncodingHash("hash"[, cache])
Returns file content by the MD5 hash derived from its BLTE encoding (either a 32-character hexadecimal string, or a 9/16-byte string). If specified, cache overrides conf.cacheFiles for this operation.
If an error occurs, returns nil and an error message.
"content" = handle:readFileByContentHash("hash"[, cache])
Returns file content by its MD5 hash (either a 32-character hexadecimal string, or a 16-byte string). If specified, cache overrides conf.cacheFiles for this operation.
If an error occurs, returns nil and an error message.
fileID = handle.root:getFileID("path")
Returns the fileID corresponding to the specified path. Negative return values are not valid file IDs. This function is only available for handles using WoW root files.
handle.root:addFileIDPaths(map[, pathsArePrehashed])
Associates additional file paths with file IDs. This function is only available for handles using WoW root files.
map (table)
A mapping of file paths (or path hashes, if pathsArePrehashed is truthy) to file IDs (or vice versa).
pathsArePrehashed (boolean, optional, default: false)
If true, strings in map are interpreted as pre-hashed paths (specified using either 8-byte strings or 16-character hexadecimal strings) rather than literal paths.