예제 #1
0
static int analyzer_smtp_event_process_begin(struct event *evt, void *obj, struct proto_process_stack *stack, unsigned int stack_index) {

	struct analyzer *analyzer = obj;
	struct analyzer_smtp_priv *apriv = analyzer->priv;
	struct proto_process_stack *s = &stack[stack_index];
	if (!s->ce)
		return POM_ERR;

	// Only process stuff if we have the DATA event or if we already have an event
	struct event_reg *evt_reg = event_get_reg(evt);
	struct data *evt_data = event_get_data(evt);

	struct analyzer_smtp_ce_priv *cpriv = conntrack_get_priv(s->ce, analyzer);
	
	// It's expected that an SMTP connection will always contain at least one message
	// So we always create the cpriv and event, no matter what
	if (!cpriv) {
		cpriv = malloc(sizeof(struct analyzer_smtp_ce_priv));
		if (!cpriv) {
			pom_oom(sizeof(struct analyzer_smtp_ce_priv));
			return POM_ERR;
		}
		memset(cpriv, 0, sizeof(struct analyzer_smtp_ce_priv));

		if (conntrack_add_priv(s->ce, analyzer, cpriv, analyzer_smtp_ce_priv_cleanup) != POM_OK) {
			free(cpriv);
			return POM_ERR;
		}
	}

	if (!cpriv->evt_msg) {
		cpriv->evt_msg = event_alloc(apriv->evt_msg);
		if (!cpriv->evt_msg)
			return POM_ERR;

	}


	struct data *msg_data = event_get_data(cpriv->evt_msg);
	
	if (evt_reg == apriv->evt_cmd) {

		if (!cpriv->common_data_fetched)
			analyzer_smtp_event_fetch_common_data(cpriv, stack, stack_index, POM_DIR_REVERSE(s->direction));


		// Process commands


		// A message was being transmitted and we recevied a new command
		if (event_is_started(cpriv->evt_msg)) {
			event_process_end(cpriv->evt_msg);
			cpriv->evt_msg = NULL;
		}

		char *cmd = PTYPE_STRING_GETVAL(evt_data[proto_smtp_cmd_name].value);
		if (!cmd)
			return POM_OK;

		char *arg = PTYPE_STRING_GETVAL(evt_data[proto_smtp_cmd_arg].value);
		if (arg) {
			while (*arg == ' ')
				arg++;
		}

		if (!strcasecmp(cmd, "MAIL")) {
			if (strncasecmp(arg, "FROM:", strlen("FROM:"))) {
				pomlog(POMLOG_DEBUG "Unparseable MAIL command");
				return POM_OK;
			}
			arg += strlen("FROM:");
			while (*arg == ' ')
				arg++;

			if (*arg == '<')
				arg++;

			size_t len;
			char *end = strchr(arg, '>');
			if (end)
				len = end - arg;
			else
				len = strlen(arg);

			PTYPE_STRING_SETVAL_N(msg_data[analyzer_smtp_msg_from].value, arg, len);
			data_set(msg_data[analyzer_smtp_msg_from]);
			cpriv->last_cmd = analyzer_smtp_last_cmd_mail_from;
			
		} else if (!strcasecmp(cmd, "RCPT")) {
			if (strncasecmp(arg, "TO:", strlen("TO:"))) {
				pomlog(POMLOG_DEBUG "Unparseable RCPT command");
				return POM_OK;
			}
			arg += strlen("TO:");
			while (*arg == ' ')
				arg++;

			if (*arg == '<')
				arg++;

			size_t len;
			char *end = strchr(arg, '>');
			if (end)
				len = end - arg;
			else
				len = strlen(arg);

			struct ptype *to = ptype_alloc("string");
			if (!to)
				return POM_ERR;

			PTYPE_STRING_SETVAL_N(to, arg, len);
			if (data_item_add_ptype(msg_data, analyzer_smtp_msg_to, strdup("to"), to) != POM_OK) {
				ptype_cleanup(to);
				return POM_ERR;
			}
			cpriv->last_cmd = analyzer_smtp_last_cmd_rcpt_to;

		} else if (!strcasecmp(cmd, "DATA")) {
			cpriv->last_cmd = analyzer_smtp_last_cmd_data;

			if (!event_is_started(cpriv->evt_msg)) {
				analyzer_smtp_event_fill_common_data(cpriv, msg_data);
				event_process_begin(cpriv->evt_msg, stack, stack_index, event_get_timestamp(evt));
			} else {
				pomlog(POMLOG_DEBUG "Message event already started !");
			}

		} else if (!strcasecmp(cmd, "RSET")) {
			// Cleanup the event
			event_cleanup(cpriv->evt_msg);
			cpriv->evt_msg = NULL;
			cpriv->last_cmd = analyzer_smtp_last_cmd_other;
		} else if (!strcasecmp(cmd, "HELO") || !strcasecmp(cmd, "EHLO")) {
			if (cpriv->client_hello) {
				pomlog(POMLOG_DEBUG "We already have a client hello !");
				free(cpriv->client_hello);
			}

			cpriv->client_hello = strdup(arg);
			if (!cpriv->client_hello) {
				pom_oom(strlen(arg) + 1);
				return POM_ERR;
			}
			cpriv->last_cmd = analyzer_smtp_last_cmd_other;

		} else if (!strcasecmp(cmd, "AUTH")) {
			if (!strncasecmp(arg, "PLAIN", strlen("PLAIN"))) {
				arg += strlen("PLAIN");
				while (*arg == ' ')
					arg++;


				if (cpriv->evt_auth) {
					event_process_end(cpriv->evt_auth);
					cpriv->evt_auth = NULL;
				}

				if (strlen(arg)) {
					if (analyzer_smtp_parse_auth_plain(apriv, cpriv, arg) == POM_OK) {
						event_process_begin(cpriv->evt_auth, stack, stack_index, event_get_timestamp(evt));
						cpriv->last_cmd = analyzer_smtp_last_cmd_auth_plain_creds;
					}
				} else {
					cpriv->last_cmd = analyzer_smtp_last_cmd_auth_plain;
					
				}

			} else if (!strncasecmp(arg, "LOGIN", strlen("LOGIN"))) {
				arg += strlen("LOGIN");
				while (*arg == ' ')
					arg++;

				if (cpriv->evt_auth) {
					event_process_end(cpriv->evt_auth);
					cpriv->evt_auth = NULL;
				}

				cpriv->evt_auth = event_alloc(apriv->evt_auth);
				if (!cpriv->evt_auth)
					return POM_ERR;

				struct data *auth_data = event_get_data(cpriv->evt_auth);

				analyzer_smtp_event_fill_common_data(cpriv, auth_data);

				// Set the authentication type
				PTYPE_STRING_SETVAL(auth_data[analyzer_smtp_auth_type].value, "LOGIN");
				data_set(auth_data[analyzer_smtp_auth_type]);

				if (strlen(arg)) {
					char *username = NULL;
					size_t out_len = 0;
					struct ptype *username_pt = NULL;
					if (decoder_decode_simple("base64", arg, strlen(arg), &username, &out_len) == POM_OK) {
						username_pt = ptype_alloc("string");
						if (username_pt) {
							PTYPE_STRING_SETVAL_P(username_pt, username);
							if (data_item_add_ptype(auth_data, analyzer_smtp_auth_params, strdup("username"), username_pt) != POM_OK) {
								ptype_cleanup(username_pt);
								event_cleanup(cpriv->evt_auth);
								cpriv->evt_auth = NULL;
								username_pt = NULL;
							}
						} else {
							free(username);
						}
					}

					if (!username_pt) {
						cpriv->last_cmd = analyzer_smtp_last_cmd_other;
						event_process_begin(cpriv->evt_auth, stack, stack_index, event_get_timestamp(evt));
					}
				} else {
					cpriv->last_cmd = analyzer_smtp_last_cmd_auth_login;
				}
			}

		} else if (cpriv->last_cmd == analyzer_smtp_last_cmd_auth_plain) {
			// We are expecting the credentials right now
			if (analyzer_smtp_parse_auth_plain(apriv, cpriv, cmd) == POM_OK) {
				event_process_begin(cpriv->evt_auth, stack, stack_index, event_get_timestamp(evt));
				cpriv->last_cmd = analyzer_smtp_last_cmd_auth_plain_creds;
			} else {
				cpriv->last_cmd = analyzer_smtp_last_cmd_other;
			}
		} else if (cpriv->last_cmd == analyzer_smtp_last_cmd_auth_login) {
			char *username = NULL;
			size_t out_len = 0;
			struct ptype *username_pt = NULL;
			if (decoder_decode_simple("base64", cmd, strlen(cmd), &username, &out_len) == POM_OK) {
				username_pt = ptype_alloc("string");
				if (username_pt) {
					PTYPE_STRING_SETVAL_P(username_pt, username);
					struct data *auth_data = event_get_data(cpriv->evt_auth);
					if (data_item_add_ptype(auth_data, analyzer_smtp_auth_params, strdup("username"), username_pt) != POM_OK) {
						ptype_cleanup(username_pt);
						event_process_end(cpriv->evt_auth);
						cpriv->evt_auth = NULL;
						username_pt = NULL;
					}
				} else {
					free(username);
				}
			}

			if (!username_pt) {
				cpriv->last_cmd = analyzer_smtp_last_cmd_other;
			} else {
				event_process_begin(cpriv->evt_auth, stack, stack_index, event_get_timestamp(evt));
				cpriv->last_cmd = analyzer_smtp_last_cmd_auth_login_user;
			}

		} else if (cpriv->last_cmd == analyzer_smtp_last_cmd_auth_login_user) {
			char *password = NULL;
			size_t out_len = 0;
			struct ptype *password_pt = NULL;
			if (decoder_decode_simple("base64", cmd, strlen(cmd), &password, &out_len) == POM_OK) {
				password_pt = ptype_alloc("string");
				if (password_pt) {
					PTYPE_STRING_SETVAL_P(password_pt, password);
					struct data *auth_data = event_get_data(cpriv->evt_auth);
					if (data_item_add_ptype(auth_data, analyzer_smtp_auth_params, strdup("password"), password_pt) != POM_OK) {
						ptype_cleanup(password_pt);
						event_process_end(cpriv->evt_auth);
						cpriv->evt_auth = NULL;
						password_pt = NULL;
					}
				} else {
					free(password);
				}
			}

			if (!password_pt) {
				cpriv->last_cmd = analyzer_smtp_last_cmd_other;
			} else {
				cpriv->last_cmd = analyzer_smtp_last_cmd_auth_login_pass;
			}
		} else {
			cpriv->last_cmd = analyzer_smtp_last_cmd_other;
		}

	} else if (evt_reg == apriv->evt_reply) {

		if (!cpriv->common_data_fetched)
			analyzer_smtp_event_fetch_common_data(cpriv, stack, stack_index, s->direction);

		// Process replies
		uint16_t code = *PTYPE_UINT16_GETVAL(evt_data[proto_smtp_reply_code].value);

		switch (cpriv->last_cmd) {

			default:
			case analyzer_smtp_last_cmd_other:
				if (code == 220 && evt_data[proto_smtp_reply_text].items && evt_data[proto_smtp_reply_text].items->value) {
					// STARTTLS returns 220 as well so ignore extra code 220
					if (!cpriv->server_hello) {
						char *helo = PTYPE_STRING_GETVAL(evt_data[proto_smtp_reply_text].items->value);
						cpriv->server_hello = strdup(helo);
						if (!cpriv->server_hello) {
							pom_oom(strlen(helo) + 1);
							return POM_ERR;
						}
					}
				}
				break;

			case analyzer_smtp_last_cmd_mail_from:
				if (code != 250) {
					// FROM is invalid
					data_unset(msg_data[analyzer_smtp_msg_from]);
				}
				break;
			case analyzer_smtp_last_cmd_rcpt_to:
				// For now just don't do anything
				// It's best to keep a destination in there even if it's invalid or denied
				break;
			
			case analyzer_smtp_last_cmd_data:
				if (code == 354) {
					// The message is starting, keep last_cmd intact
					return POM_OK;
				}

				// Message is over (if ever transmited)
				if (event_is_started(cpriv->evt_msg)) {
					struct data *msg_data = event_get_data(cpriv->evt_msg);
					PTYPE_UINT16_SETVAL(msg_data[analyzer_smtp_msg_result].value, code);
					data_set(msg_data[analyzer_smtp_msg_result]);
					event_process_end(cpriv->evt_msg);
					cpriv->evt_msg = NULL;
				}
				break;

			case analyzer_smtp_last_cmd_auth_plain:
			case analyzer_smtp_last_cmd_auth_login:
			case analyzer_smtp_last_cmd_auth_login_user:
				// Check if authentication phase can continue
				if (code == 334) {
					// Don't reset cpriv->last_cmd
					return POM_OK;
				} else {
					struct data *evt_data = event_get_data(cpriv->evt_auth);
					PTYPE_BOOL_SETVAL(evt_data[analyzer_smtp_auth_success].value, 0);
					data_set(evt_data[analyzer_smtp_auth_success]);
					event_process_end(cpriv->evt_auth);
					cpriv->evt_auth = NULL;
				}
				break;

			case analyzer_smtp_last_cmd_auth_plain_creds:
			case analyzer_smtp_last_cmd_auth_login_pass: {
				// We just processed the credentials
				struct data *auth_data = event_get_data(cpriv->evt_auth);
				char success = 0;
				if (code == 235)
					success = 1;
				PTYPE_BOOL_SETVAL(auth_data[analyzer_smtp_auth_success].value, success);
				data_set(auth_data[analyzer_smtp_auth_success]);
				event_process_end(cpriv->evt_auth);
				cpriv->evt_auth = NULL;
				break;
			}

		}

		cpriv->last_cmd = analyzer_smtp_last_cmd_other;

	}


	return POM_OK;
}
예제 #2
0
static int analyzer_rtp_pload_process(void *obj, struct packet *p, struct proto_process_stack *stack, unsigned int stack_index) {

	struct analyzer *analyzer = obj;
	struct analyzer_rtp_priv *priv = analyzer->priv;

	struct proto_process_stack *pload_stack = &stack[stack_index];
	struct proto_process_stack *s = &stack[stack_index - 1];

	if (!s->ce)
		return POM_ERR;

	struct analyzer_rtp_ce_priv *cp = conntrack_get_priv(s->ce, obj);
	if (!cp) {
		cp = malloc(sizeof(struct analyzer_rtp_ce_priv));
		if (!cp) {
			pom_oom(sizeof(struct analyzer_rtp_ce_priv));
			return POM_ERR;
		}
		memset(cp, 0, sizeof(struct analyzer_rtp_ce_priv));

		if (conntrack_add_priv(s->ce, obj, cp, analyzer_rtp_ce_cleanup) != POM_OK)
			return POM_ERR;
	}

	int dir = s->direction;

	if (!cp->evt[dir]) {
		cp->evt[dir] = event_alloc(priv->evt_rtp_stream);
		if (!cp->evt[dir])
			return POM_ERR;

		struct data *evt_data = event_get_data(cp->evt[dir]);
		ptype_copy(evt_data[analyzer_rtp_stream_ssrc].value, s->pkt_info->fields_value[proto_rtp_field_ssrc]);
		data_set(evt_data[analyzer_rtp_stream_ssrc]);

		// For now we always assume RTP is over UDP or TCP
		if (stack_index > 2) {
			struct proto_process_stack *l4_stack = &stack[stack_index - 2];
			unsigned int i;
			for (i = 0; !data_is_set(evt_data[analyzer_rtp_stream_src_port]) || !data_is_set(evt_data[analyzer_rtp_stream_dst_port]); i++) {
				struct proto_reg_info *l4_info = proto_get_info(l4_stack->proto);
				char *name = l4_info->pkt_fields[i].name;
				if (!name)
					break;
				if (!data_is_set(evt_data[analyzer_rtp_stream_src_port]) && !strcmp(name, "sport")) {
					ptype_copy(evt_data[analyzer_rtp_stream_src_port].value, l4_stack->pkt_info->fields_value[i]);
					data_set(evt_data[analyzer_rtp_stream_src_port]);
				} else if (!data_is_set(evt_data[analyzer_rtp_stream_dst_port]) && !strcmp(name, "dport")) {
					ptype_copy(evt_data[analyzer_rtp_stream_dst_port].value, l4_stack->pkt_info->fields_value[i]);
					data_set(evt_data[analyzer_rtp_stream_dst_port]);
				}
			}

		}

		if (stack_index > 3) {
			struct proto_process_stack *l3_stack = &stack[stack_index - 3];
			unsigned int i;
			for (i = 0; !data_is_set(evt_data[analyzer_rtp_stream_src_addr]) || !data_is_set(evt_data[analyzer_rtp_stream_dst_addr]); i++) {
				struct proto_reg_info *l3_info = proto_get_info(l3_stack->proto);
				char *name = l3_info->pkt_fields[i].name;
				if (!name)
					break;
				if (!data_is_set(evt_data[analyzer_rtp_stream_src_addr]) && !strcmp(name, "src")) {
					evt_data[analyzer_rtp_stream_src_addr].value = ptype_alloc_from(l3_stack->pkt_info->fields_value[i]);
					if (evt_data[analyzer_rtp_stream_src_addr].value)
						data_set(evt_data[analyzer_rtp_stream_src_addr]);
				} else if (!data_is_set(evt_data[analyzer_rtp_stream_dst_addr]) && !strcmp(name, "dst")) {
					evt_data[analyzer_rtp_stream_dst_addr].value = ptype_alloc_from(l3_stack->pkt_info->fields_value[i]);
					if (evt_data[analyzer_rtp_stream_dst_addr].value)
						data_set(evt_data[analyzer_rtp_stream_dst_addr]);
				}
			}

		}

		struct proto *sess_proto = telephony_stream_info_get_sess_proto(s->ce);
		if (sess_proto) {
			struct proto_reg_info *proto_reg = proto_get_info(sess_proto);
			PTYPE_STRING_SETVAL(evt_data[analyzer_rtp_stream_sess_proto].value, proto_reg->name);
			data_set(evt_data[analyzer_rtp_stream_sess_proto]);
		}

		char *call_id = telephony_stream_info_get_call_id(s->ce);
		if (call_id) {
			PTYPE_STRING_SETVAL_P(evt_data[analyzer_rtp_stream_call_id].value, call_id);
			data_set(evt_data[analyzer_rtp_stream_call_id]);
		}

		if (event_process_begin(cp->evt[dir], stack, stack_index, p->ts) != POM_OK)
			return POM_ERR;
	}

	if (!cp->pload[dir]) {
		cp->pload[dir] = pload_alloc(cp->evt[dir], 0);
		if (!cp->pload[dir])
			return POM_ERR;

		struct telephony_codec_info info = { 0 };
		if (telephony_stream_info_get_codec(&info, stack, stack_index - 1) == POM_OK) {
			char *pload_type = telephony_codec_info_get_pload_type(&info);
			if (pload_type)
				pload_set_type(cp->pload[dir], pload_type);
		}
	}

	if (pload_append(cp->pload[dir], pload_stack->pload, pload_stack->plen) != POM_OK)
		return POM_ERR;

	return POM_OK;
}
예제 #3
0
파일: registry.c 프로젝트: k0a1a/pom-ng
int registry_config_save(char *config_name) {

	if (strlen(config_name) >= REGISTRY_CONFIG_NAME_MAX) {
		pomlog(POMLOG_ERR "Configuration name too long, max %u characters.", REGISTRY_CONFIG_NAME_MAX);
		return POM_ERR;
	}

	struct dataset_query *dsq_config_list = NULL, *dsq_config = NULL;
	
	struct datastore *sys_dstore = system_datastore();
	if (!sys_dstore)
		return POM_ERR;

	struct datastore_connection *dc = datastore_connection_new(sys_dstore);
	if (!dc)
		return POM_ERR;

	dsq_config_list = datastore_dataset_query_open(sys_dstore, REGISTRY_CONFIG_LIST, registry_config_list_dataset_template, dc);
	if (!dsq_config_list)
		goto err;

	if (datastore_dataset_query_set_string_condition(dsq_config_list, 0, PTYPE_OP_EQ, config_name) != POM_OK)
		goto err;

	dsq_config = datastore_dataset_query_open(sys_dstore, REGISTRY_CONFIG, registry_config_dataset_template, dc);
	if (!dsq_config)
		goto err;

	if (datastore_transaction_begin(dc) != POM_OK)
		goto err;

	// Find out if we already have a config by that name
	int res = datastore_dataset_read_single(dsq_config_list);
	if (res == DATASET_QUERY_MORE) {

		// Delete existing stuff about this config
		if (datastore_dataset_query_set_uint64_condition(dsq_config, 0, PTYPE_OP_EQ, dsq_config_list->data_id) != POM_OK)
			goto err;

		if (datastore_dataset_delete(dsq_config_list) != DATASET_QUERY_OK)
			goto err;

		if (datastore_dataset_delete(dsq_config) != DATASET_QUERY_OK)
			goto err;
	}

	if (res < 0)
		goto err;

	// Add the config to the config list
	PTYPE_STRING_SETVAL(dsq_config_list->values[0].value, config_name);
	PTYPE_TIMESTAMP_SETVAL(dsq_config_list->values[1].value, pom_gettimeofday());

	if (datastore_dataset_write(dsq_config_list) != DATASET_QUERY_OK)
		goto err;



	PTYPE_UINT64_SETVAL(dsq_config->values[0].value, dsq_config_list->data_id);

	registry_lock();
	struct registry_class *cls;

	// Browse each class
	for (cls = registry_head; cls; cls = cls->next) {

		// Browse each instance of the class
		struct registry_instance *inst;
		for (inst = cls->instances; inst; inst = inst->next) {
			
			// Don't add the instance if it's not added by the user
			
			if (cls->instance_add) {

				// The system datastore will always exist
				if (inst == sys_dstore->reg_instance)
					continue;

				char *buff = malloc(strlen(cls->name) + 1 + strlen(inst->name) + 1);
				if (!buff) {
					pom_oom(strlen(cls->name) + 1 + strlen(inst->name) + 1);
					goto err_locked;
				}

				strcpy(buff, cls->name);
				strcat(buff, ".");
				strcat(buff, inst->name);
				PTYPE_STRING_SETVAL_P(dsq_config->values[1].value, buff);

				struct registry_param *p;
				for (p = inst->params; p && strcmp(p->name, "type"); p = p->next);

				if (p) {
					dsq_config->values[2].is_null = 0;
					char *type = PTYPE_STRING_GETVAL(p->value);
					PTYPE_STRING_SETVAL(dsq_config->values[2].value, type);
				} else {
					dsq_config->values[2].is_null = 1;
				}

				PTYPE_UINT8_SETVAL(dsq_config->values[3].value, registry_config_instance);

				if (datastore_dataset_write(dsq_config) != DATASET_QUERY_OK)
					goto err_locked;

			}

			// Browse the parametrers and add the non default ones

			struct registry_param *param;
			for (param = inst->params; param; param = param->next) {

				// Check if the parameter value is not the default one anymore
				if (param->default_value) {
					struct ptype *defval = ptype_alloc_from(param->value);
					if (!defval)
						goto err_locked;

					if (ptype_parse_val(defval, param->default_value) != POM_OK) {
						pomlog(POMLOG_ERR "Unable to parse default value !");
						ptype_cleanup(defval);
						goto err_locked;
					}

					if (ptype_compare_val(PTYPE_OP_EQ, param->value, defval)) {
						// Param still has the default value, do nothing
						ptype_cleanup(defval);
						continue;
					}

					ptype_cleanup(defval);
				}

				char *buff = malloc(strlen(cls->name) + 1 + strlen(inst->name) + 1 + strlen(param->name) + 1);
				if (!buff) {
					pom_oom(strlen(cls->name) + 1 + strlen(inst->name) + 1 + strlen(param->name) + 1);
					goto err_locked;
				}
				strcpy(buff, cls->name);
				strcat(buff, ".");
				strcat(buff, inst->name);
				strcat(buff, ".");
				strcat(buff, param->name);
				PTYPE_STRING_SETVAL_P(dsq_config->values[1].value, buff);

				char *value = ptype_print_val_alloc(param->value, NULL);
				if (!value)
					goto err_locked;
				
				dsq_config->values[2].is_null = 0;
				PTYPE_STRING_SETVAL_P(dsq_config->values[2].value, value);

				PTYPE_UINT8_SETVAL(dsq_config->values[3].value, registry_config_instance_param);

				if (datastore_dataset_write(dsq_config) != DATASET_QUERY_OK)
					goto err_locked;
			}
		
		}

	}

	registry_config_serial++;
	registry_serial++;
	xmlrcpcmd_serial_inc();

	registry_unlock();

	if (datastore_transaction_commit(dc) != POM_OK)
		goto err;

	datastore_dataset_query_cleanup(dsq_config_list);
	datastore_dataset_query_cleanup(dsq_config);
	
	datastore_connection_release(dc);

	pomlog("Registry configuration saved as \"%s\"", config_name);

	return POM_OK;

err_locked:
	registry_unlock();

err:
	if (dsq_config_list)
		datastore_dataset_query_cleanup(dsq_config_list);

	if (dsq_config)
		datastore_dataset_query_cleanup(dsq_config);

	if (dc) {
		datastore_transaction_rollback(dc);
		datastore_connection_release(dc);
	}

	return POM_ERR;

}
예제 #4
0
static void analyzer_jpeg_exif_entry_analyze(ExifEntry *entry, void *pload) {

	ExifIfd ifd = exif_content_get_ifd(entry->parent);

	const char *tag_name = exif_tag_get_name_in_ifd(entry->tag, ifd);
	if (!tag_name) // Unknown tag
		return;

	struct ptype *value = NULL;
	// First parse ascii values
	if (entry->format == EXIF_FORMAT_ASCII) {
		char *str = malloc(entry->size);
		if (!str) {
			pom_oom(entry->size);
			return;
		}
		memcpy(str, entry->data, entry->size);
		// Make sure it's NULL terminated
		str[entry->size - 1] = 0;

		value = ptype_alloc("string");
		if (!value) {
			free(str);
			return;
		}
		PTYPE_STRING_SETVAL_P(value, str);
	} else if (entry->components == 1) {
		
		ExifByteOrder byte_order = exif_data_get_byte_order(entry->parent->parent);
		if (entry->format == EXIF_FORMAT_BYTE) {
			value = ptype_alloc("uint8");
			if (!value)
				return;
			PTYPE_UINT8_SETVAL(value, *entry->data);
		} else if (entry->format == EXIF_FORMAT_SHORT)	{
			value = ptype_alloc("uint16");
			if (!value)
				return;
			PTYPE_UINT16_SETVAL(value, exif_get_short(entry->data, byte_order));
		} else if (entry->format == EXIF_FORMAT_LONG) {
			value = ptype_alloc("uint32");
			if (!value)
				return;
			PTYPE_UINT32_SETVAL(value, exif_get_long(entry->data, byte_order));
		}

	}

	if (!value) {
		// Fallback for types not parsed by us yet
		// FIXME this is subject to the locale

		char buff[256];
		buff[sizeof(buff) - 1] = 0;
		exif_entry_get_value(entry, buff, sizeof(buff) - 1);

		value = ptype_alloc("string");
		if (!value)
			return;
		PTYPE_STRING_SETVAL(value, buff);

	}

	char *key = strdup(tag_name);
	if (!key) {
		pom_oom(strlen(tag_name) + 1);
		return;
	}

	struct data *data = analyzer_pload_buffer_get_data(pload);
	data_item_add_ptype(data, analyzer_jpeg_pload_exif, key, value);

}