# DeviceAtlas Device Detection API #
The DeviceAtlas Device Detection API provides a way to detect devices based on
the data found in HTTP headers. Using these 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
### Requirements ###
- A C compiler
- CMake 2.6 (or above)
- PCRE 6.x (or above). For best performance v8.21 (or above) is recommended.
**Important** - There are two major versions of the PCRE library: PCRE and
PCRE2. PCRE2 is not compatible and should not be used.
The following compilers have been tested and are able to compile all
components:
- GCC (3.4 or above (4.x versions are recommended))
- Clang/LLVM (3.0 or above)
- Sun Pro family (12.x or above)
### CMake ###
By default CMake should find all necessary components if they are installed
with a package manager. This section describes setting cmake variables to
handle components installed in custom locations.
** PCRE library and headers **
If the PCRE library and headers are located in a custom location, the
following cmake environment variables may be set:
- PCRELIB=<path to the pcre library>
- PCRE_INCLUDE_DIR=<path to the pcre headers folder>
(For Red Hat based operating systems, the required packages are pcre-devel;
for Debian, the names are libpcre3-dev; otherwise, please check pcre and
zlib development packages with your package manager).
For example:
```shell
cmake -DPCRELIB=/home/test/pcre/lib/libpcre.so -DPCRE_INCLUDE_DIR=/home/test/pcre/include
```
Compatibility: For older PCRE versions it is possible to disable PCRE Study
feature with cmake -DPCRE_STUDY=0. It is highly recommended to do NOT disable
PCRE Study for better performance.
** Custom compiler location **
- CMAKE_C_COMPILER=<full path to the C compiler executable>
For example:
```shell
cmake -DCMAKE_C_COMPILER=/home/test/gcc-4.8.3/bin/gcc -DCMAKE_CXX_COMPILER=/home/test/gcc-4.8.3/bin/g++
```
NB: For a static API version used with another shared library it is possible to
use CFLAGS/CXXFLAGS with -fPIC/fpic compilation flag.
### Building the API ###
1. Unpack the API
2. Change to the API directory
3. Run cmake command
4. Run make
```shell
% cmake .
% make
```
### Basic Usage ###
#### Example 1 ####
The following example code shows the API loading the data file and using a
property name to find a certain value for a given User-Agent.
```c
#include
// 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;
const char *jsonpath = argv[1];
const char *useragent = argv[2];
// 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 useragentid = da_atlas_evidence_id(&atlas, "user-agent");
da_evidence_t headers[1] = {{ useragentid, useragent }};
da_deviceinfo_t device;
// it exists an alternative variadic version call ...
// da_search(&atlas, &device, headers[0].key, headers[0].value, 0);
if ((status = da_searchv(&atlas, &device, headers, 1)) != DA_OK)
{
fprintf(stderr, "da_search failed\n");
goto daclose;
}
da_propid_t *prop;
// da_getfirstprop / da_getnextprop are convenient way to iterate through the properties list
// alternatively, it is possible to know the number of properties via da_deviceinfo_t's propcount field
for (status = da_getfirstprop(&device, &prop); status == DA_OK;
status = da_getnextprop(&device, &prop)) {
const char *name;
da_type_t type;
da_getpropname(&device, *prop, &name);
da_getproptype(&device, *prop, &type);
char buf[256];
switch (type) {
case DA_TYPE_INTEGER: {
long val;
da_getpropinteger(&device, *prop, &val);
sprintf(buf, "%ld", val);
break;
}
case DA_TYPE_BOOLEAN: {
bool val;
da_getpropboolean(&device, *prop, &val);
sprintf(buf, "%d", val);
}
case DA_TYPE_STRING: {
const char *val;
da_getpropstring(&device, *prop, &val);
size_t vallen = min(strlen(val), sizeof(buf) - 1);
strncpy(buf, val, vallen);
buf[vallen] = 0;
break;
}
default:
break;
}
da_close(&device);
daclose:
da_atlas_close(&atlas);
free(ptr);
dafini:
da_fini();
```
### Sample applications ###
There are multiple examples in the /examples folder to test the API.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_ Copyright (c) DeviceAtlas Limited 2021. All Rights Reserved. _
https://deviceatlas.com