/**
 * Internal function that goes through every property specified in the PHP.ini
 * file and for each of the properties checks that such property exists in the
 * data set properties array. If a property exists, then a corresponding value
 * is added to the array that will be returned to PHP. If a property does not
 * exist, then a "Switch Data Set" message is returned as the property value
 * @param returnArray a pointer to the Zend array to store results in.
 */
void buildArray(zval *returnArray)
{
    char* propertyName;
    char *valueString;
    char* methodString;
    int propertyIndex;
    int valueCount;
    int valueIndex;
    int32_t sigRank;

    for(propertyIndex = 0;
        propertyIndex < FIFTYONE_G(ws)->dataSet->requiredPropertyCount;
        propertyIndex++) {
        propertyName = (char*)fiftyoneDegreesGetPropertyName(
                FIFTYONE_G(ws)->dataSet,
                *(FIFTYONE_G(ws)->dataSet->requiredProperties + propertyIndex));
        valueCount = fiftyoneDegreesSetValues(FIFTYONE_G(ws), propertyIndex);

        if (valueCount == 1) {
            valueString = (char*)fiftyoneDegreesGetValueName(
                FIFTYONE_G(ws)->dataSet,
                *FIFTYONE_G(ws)->values);
            add_assoc_string(returnArray, propertyName, valueString, 1);
        } else if (valueCount > 1) {
            zval* valueArray;
            ALLOC_INIT_ZVAL(valueArray);
            array_init(valueArray);
            add_assoc_zval(returnArray, propertyName, valueArray);
            for(valueIndex = 0; valueIndex < valueCount; valueIndex++) {
                valueString = (char*)fiftyoneDegreesGetValueName(
                    FIFTYONE_G(ws)->dataSet,
                    *(FIFTYONE_G(ws)->values + valueIndex));
                add_next_index_string(valueArray, valueString, 1);
            }
        }
    }
    // Add signature rank information.
    sigRank = fiftyoneDegreesGetSignatureRank(FIFTYONE_G(ws));
    // SignatureRank is obsolete and will be removed in future versions.
    // Use Rank instead.
    add_assoc_long(returnArray, "SignatureRank", sigRank);
    add_assoc_long(returnArray, "Rank", sigRank);
    add_assoc_long(returnArray, "Difference", FIFTYONE_G(ws)->difference);

    // Add method that was used for detection to the results array.
    switch(FIFTYONE_G(ws)->method){
        case NONE: methodString = "None"; break;
        case EXACT: methodString = "Exact"; break;
        case NUMERIC: methodString = "Numeric"; break;
        case NEAREST: methodString = "Nearest"; break;
        case CLOSEST: methodString = "Closest"; break;
        default: methodString = "Unknown"; break;
    }
    add_assoc_string(returnArray, "Method", methodString, 1);
    addDeviceIdToArray(returnArray);
}
Exemplo n.º 2
0
/**
 * Returns a string representation of the value associated with the required
 * property index. If the index is not valid an empty string is returned. If
 * the property relates to a list with more than one value then values are
 * seperated by | characters.
 * @param requiredPropertyIndex of the property required
 * @returns a string representation of the value for the property
 */
string Match::getValue(int requiredPropertyIndex) {
    string result;
    const fiftyoneDegreesAsciiString* valueName;
    if (requiredPropertyIndex >= 0 &&
        fiftyoneDegreesSetValues(ws, requiredPropertyIndex) > 0) {
        valueName = fiftyoneDegreesGetString(
        	ws->dataSet,
        	ws->values[0]->nameOffset);
        result.assign(&(valueName->firstByte));
    }
    return result;
}
Exemplo n.º 3
0
/**
 * Returns a vector with all values associated with the required property
 * index. If the index is not valid an empty vector is returned.
 * @param requiredPropertyIndex of the property required
 * @returns a vector of values for the property
 */
vector<string> Match::getValues(int requiredPropertyIndex) {
    vector<string> result;
    const fiftyoneDegreesAsciiString* valueName;
    if (requiredPropertyIndex >= 0 &&
        fiftyoneDegreesSetValues(ws, requiredPropertyIndex) > 0) {
        for (int valueIndex = 0; valueIndex < ws->valuesCount; valueIndex++) {
            valueName = fiftyoneDegreesGetString(
            	ws->dataSet,
            	ws->values[valueIndex]->nameOffset);
            result.insert(result.end(), string(&(valueName->firstByte)));
        }
    }
    return result;
}
Exemplo n.º 4
0
/**
* Returns the hash code for the values of properties contained in the work
* set.
* @param ws work set containing the results of a match
*/
static unsigned long getHashCode(fiftyoneDegreesWorkset *ws) {
	unsigned long hashCode = 0;
	int32_t requiredPropertyIndex;
	const fiftyoneDegreesAsciiString *valueName;
	for (requiredPropertyIndex = 0;
		requiredPropertyIndex < ws->dataSet->requiredPropertyCount;
		requiredPropertyIndex++) {
		fiftyoneDegreesSetValues(ws, requiredPropertyIndex);
		valueName = fiftyoneDegreesGetString(
			ws->dataSet,
			ws->values[0]->nameOffset);
		hashCode ^= hash((unsigned char*)&(valueName->firstByte));
	}
	return hashCode;
}
/**
 * Returns a string representation of the value associated with the required
 * property name. If the property name is not valid an empty string is
 * returned.If the property relates to a list with more than one value then
 * values are separated by | characters.
 * @param propertyName pointer to a string containing the property name
 * @returns a string representation of the value for the property
 */
const char* getValue(fiftyoneDegreesWorkset* ws, char* propertyName) {
	int requiredPropertyIndex;
	const char* result;
	const fiftyoneDegreesAsciiString* valueName;

	requiredPropertyIndex = fiftyoneDegreesGetRequiredPropertyIndex(ws->dataSet, propertyName);
	if (requiredPropertyIndex != -1) {
		fiftyoneDegreesSetValues(ws, requiredPropertyIndex);
		valueName = fiftyoneDegreesGetString(ws->dataSet, ws->values[0]->nameOffset);
		result = &(valueName->firstByte);
		return result;
	}
	else {
		return "";
	}
}
Exemplo n.º 6
0
// Execute a performance test using a file of null terminated useragent strings
// as input. If calibrate is true then the file is read but no detections
// are performed.
void runPerformanceTest(PERFORMANCE_STATE *state) {
	char *input = (char*)malloc(state->pool->dataSet->header.maxUserAgentLength + 1);
	char *result = NULL;
	long valueCount;
	FILE *inputFilePtr;
	int i, v, count = 0;
	fiftyoneDegreesWorkset *ws = NULL;

    // Open the file and check it's valid.
    inputFilePtr = fopen(state->fileName, "r");
	if (inputFilePtr == NULL) {
        printf("Failed to open file with null-terminating user agent strings to fiftyoneDegreesMatch against 51Degrees data file. \n");
        fclose(inputFilePtr);
        exit(0);
	}

    // Get the first entry from the file.
    result = fgets(input, state->pool->dataSet->header.maxUserAgentLength, inputFilePtr);

	while(result != NULL && !feof(inputFilePtr)) {

        // Split the string at carriage returns.
		strtok(result, "\n");

		// If detection should be performed get the result and the property values.
		if (state->calibrate == 0) {
            ws = fiftyoneDegreesWorksetPoolGet(state->pool);
			fiftyoneDegreesMatch(ws, input);
			valueCount = 0;
			for (i = 0; i < ws->dataSet->requiredPropertyCount; i++) {
				fiftyoneDegreesSetValues(ws, i);
				for (v = 0; v < ws->valuesCount; v++) {
					valueCount += (long)(ws->values[v]->nameOffset);
				}
			}
			fiftyoneDegreesWorksetPoolRelease(state->pool, ws);
#ifndef FIFTYONEDEGREES_NO_THREADING
			FIFTYONEDEGREES_MUTEX_LOCK(&state->lock);
#endif
			state->valueCount += valueCount;
#ifndef FIFTYONEDEGREES_NO_THREADING
			FIFTYONEDEGREES_MUTEX_UNLOCK(&state->lock);
#endif
		}

		count++;

		// Print a progress marker.
		if (count == state->progress) {
			reportProgress(state, count);
			count = 0;
		}

		// Get the next entry from the data file.
		result = fgets(input, state->pool->dataSet->header.maxUserAgentLength, inputFilePtr);
    }

    free(input);

	reportProgress(state, count);
	fclose(inputFilePtr);

#ifndef FIFTYONEDEGREES_NO_THREADING
	FIFTYONEDEGREES_THREAD_EXIT;
#endif
}