# DeviceAtlas Device Detection for Web #
The DeviceAtlas Device Detection API for Web provides a way to detect devices based on
the HTTP headers. Using the headers, the API returns device information such as
screen width, screen height, is mobile, vendor, model etc.
To see a full list of properties in DeviceAtlas please visit:
https://deviceatlas.com/resources/available-properties .
### Data File ###
The DeviceAtlas API relies on a device data file to function. DeviceAtlas
provides daily data file updates so it is recommended to download the data file
on a regular basis. This can be done manually from your account page or
automated via the https://deviceatlas.com/getJSON page.
For more information please see:
https://deviceatlas.com/resources/getting-the-data
### Dependencies ###
This library does not depend on any third party libraries.
### Library ###
The DeviceAtlas API is a single package that contains a single module for the Device Detection API.
#### DeviceApi ####
The main library that loads the Device data and detects and returns the properties for a set of request headers or a user-agent.
Client-side properties can be optionally passed to this library to get more accurate results.
### Sample applications ###
There are multiple examples in the Examples folder to run the API.
Check README in respective example directory to view compile and run instructions.
### Basic Usage ###
The API can be used as follows:
To lookup the properties by manually passing the Hash of headers to the API:
```c
#include
// Optional
// By default the API sets a sane memory threshold for the JSON parsing
// and mapping to memory however it is possible to override the value
// if it needs to fit specific constraints. The value is to be
// a multiple of DA_MEMORY_MUL and to avoid unnecessary numerous
// I/O operations, being rounded up slighty.
size_t da_user_hint = 3 * DA_MEMORY_MUL;
// The 2 functions below are necessary for da_atlas_compile
// as it needs 2 function pointers for reading and seeking in the data file
static size_t
filereader(void *ctx, size_t count, char *buf)
{
return fread(buf, 1, count, ctx);
}
static da_status_t
fileseeker(void *ctx, off_t pos)
{
return fseek(ctx, pos, SEEK_SET) != -1 ? DA_OK : DA_SYS;
}
...
da_atlas_t atlas;
da_status_t status;
void *ptr;
size_t size;
/**
* When the JSON file is supplied
*/
const char *jsonpath = argv[1];
...
// Json file reading
FILE *json = fopen(jsonpath, "r");
if (!json) {
fprintf(stderr, "fread failed: %s\n", jsonpath);
exit(EXIT_FAILURE);
}
da_init();
if ((status = da_atlas_compile(json, filereader, fileseeker, &ptr, &size)) != DA_OK)
{
fprintf(stderr, "da_atlas_compile failed\n");
goto dafini;
}
/**
* Or when the binary file dumped previously by da_atlas_dump_mapped
* or from in RAM data
*/
...
const char *binarypath = "data.bin";
void *m;
if ((status = da_atlas_read_mapped(binarypath, m, &ptr, &size)) != DA_OK)
{
fprintf(stderr, "da_atlas_read_mapped failed\n");
goto daclose;
}
...
da_property_decl_t extraprops[] = {{ 0, 0 }};
if ((status = da_atlas_open(&atlas, extraprops, ptr, size)) != DA_OK)
{
fprintf(stderr, "da_atlas_open failed\n");
goto daclose;
}
/**
* Optional: dumping the API memory state into a binary file
*/
...
const char *binaryPath = "./data.bin";
void *bin;
size_t binlen;
if ((status = da_atlas_dump_mapped(binarypath, &bin, &binlen, ptr, size)) != DA_OK)
{
fprintf(stderr, "da_atlas_dump_mapped failed\n");
goto daclose;
}
...
da_evidence_id_t mainid = da_atlas_evidence_id(&atlas, "user-agent");
da_evidence_id_t extraid = da_atlas_evidence_id(&atlas, extraheader);
da_evidence_t headers[] = {{ mainid, useragent, extraid, extraval ... }};
da_deviceinfo_t device;
if ((status = da_searchv(&atlas, &device, headers, 2)) != DA_OK)
{
fprintf(stderr, "da_search failed\n");
goto daclose;
}
da_propid_t *mprop;
da_propid_t *dprop;
da_propid_t *vprop;
da_propid_t *jprop;
da_propid_t *tprop;
bool mobiledevice;
bool touchscreen;
bool jsgetlocation;
long displaywidth;
const char *vendor;
da_atlas_getpropid(&atlas, "mobileDevice", mprop);
da_atlas_getpropid(&atlas, "touchScreen", tprop);
da_atlas_getpropid(&atlas, "js.geoLocation", jprop);
da_atlas_getpropid(&atlas, "displayWidth", dprop);
da_atlas_getpropid(&atlas, "vendor", vprop);
if (da_getpropboolean(&device, *mprop, &mobiledevice) != DA_OK)
mobiledevice = false;
if (da_getpropboolean(&device, *tprop, &touchscreen) != DA_OK)
touchscreen = false;
if (da_getpropboolean(&device, *jprop, &jsgeolocation) != DA_OK)
jsgeolocation = false;
if (da_getpropinteger(&device, *dprop, &displaywidth) != DA_OK)
displaywidth = 100;
if (da_getpropstring(&device, *vprop, &vendor) != DA_OK)
vendor = "";
da_close(&device);
daclose:
da_atlas_close(&atlas);
free(ptr);
dafini:
da_fini();
```
### Downloading and loading the data file ###
The following example download the data file, save it to the file system,
load it into the DeviceAtlas API and schedule a background task to download
and load a fresh data file at a configured time in the future.
```c
// A default CURL backend is provided.
// However, it is possible to implement the download's task
// callbacks, possibly initializing globals states beforehand
// Similarly, a default data file archive extraction's task
// is also provided.
dw_df_dainit_fn = curldwinit;
dw_df_dacleanup_fn = curldwcleanup;
struct tm *tm;
if (da_init() != DA_OK) {
exit(-1);
}
da_dwatlas oatlas;
memset(&atlas, 0, sizeof(atlas));
atlas.dcfg.info.url = strdup();
atlas.dcfg.info.chksum = 1;
atlas.dcfg.info.reload = 0;
atlas.dcfg.info.datatm = 1;
...
atlas.dcfg.dwproc = curldwproc;
atlas.dcfg.dwextract = dadwextract;
...
atlas.dcfg.info.rtm = *tm;
...
if (da_atlas_open_schedule(&oatlas) == DA_OK) {
while (!atlas.set);
da_evidence_id_t mainid = da_atlas_evidence_id(&atlas, "user-agent");
...
if ((status = da_searchv(&atlas, &device, headers, 2)) == DA_OK) {
}
...
da_close(&device);
...
dw_daatlas_close(&oatlas);
/// da_atlas_close call is not necessary in the scheduler mode.
}
da_fini();
```
### Client Side Component ###
In addition to the properties from the data file, properties can be gathered from
the client's browser and used both on the client side and on the server side.
It is strongly recommended to use the Client-side component when using the DeviceAtlas
API within a web application in order to correctly identify iOS devices.
The client side resource (https://cs.deviceatlas-cdn.com/dacs.js)
must be included on your webpage in order for it to detect the client side properties.
The contents of this cookie are automatically detected by the API.
Please click [here](https://docs.deviceatlas.com/apis/clientside/latest/README.ClientSide.html) for
more information.
```
```
#### Inside a Web application context ####
To lookup the properties of the device which sent the request:
The API analyses the request object and will use the client-side properties
if they exist in the cookies.
```c
#include
...
da_atlas_t atlas;
da_status_t status;
void *ptr;
size_t size;
const char *jsonpath = argv[1];
...
// Json file reading
FILE *json = fopen(jsonpath, "r");
if (!json) {
fprintf(stderr, "fread failed: %s\n", jsonpath);
exit(EXIT_FAILURE);
}
da_init();
if ((status = da_atlas_compile(json, filereader, fileseeker, &ptr, &size)) != DA_OK)
{
fprintf(stderr, "da_atlas_compile failed\n");
goto dafini;
}
da_property_decl_t extraprops[] = {{ 0, 0 }};
if ((status = da_atlas_open(&atlas, extraprops, ptr, size)) != DA_OK)
{
fprintf(stderr, "da_atlas_open failed\n");
goto daclose;
}
da_evidence_id_t mainid = da_atlas_evidence_id(&atlas, "user-agent");
da_evidence_id_t clientid = da_atlas_header_evidence_id(&atlas);
da_evidence_t headers[] = {{ mainid, useragent, clientid, daprops }};
da_deviceinfo_t device;
if ((status = da_searchv(&atlas, &device, headers, 2)) != DA_OK)
{
fprintf(stderr, "da_search failed\n");
goto daclose;
}
if (da_getpropboolean(&device, *mprop, &mobiledevice) != DA_OK)
mobiledevice = false;
if (da_getpropboolean(&device, *tprop, &touchscreen) != DA_OK)
touchscreen = false;
if (da_getpropboolean(&device, *jprop, &jsgeolocation) != DA_OK)
jsgeolocation = false;
if (da_getpropinteger(&device, *dprop, &displaywidth) != DA_OK)
displaywidth = 100;
if (da_getpropstring(&device, *vprop, &vendor) != DA_OK)
vendor = "";
da_close(&device);
daclose:
da_atlas_close(&atlas);
free(ptr);
```
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_ Copyright (c) DeviceAtlas Limited 2021. All Rights Reserved. _
_ https://deviceatlas.com _