static int yaf_route_pathinfo_route(yaf_request_t *request, char *req_uri, int req_uri_len TSRMLS_DC) /* {{{ */ { zval *params; char *module = NULL, *controller = NULL, *action = NULL, *rest = NULL; do { #define strip_slashs(p) while (*p == ' ' || *p == '/') { ++p; } char *s, *p, *q; char *uri; if (req_uri_len == 0 || (req_uri_len == 1 && *req_uri == '/')) { break; } uri = req_uri; s = p = uri; q = req_uri + req_uri_len - 1; while (*q == ' ' || *q == '/') { *q-- = '\0'; } strip_slashs(p); if ((s = strstr(p, "/")) != NULL) { if (yaf_application_is_module_name(p, s-p TSRMLS_CC)) { module = estrndup(p, s - p); p = s + 1; strip_slashs(p); if ((s = strstr(p, "/")) != NULL) { controller = estrndup(p, s - p); p = s + 1; } } else { controller = estrndup(p, s - p); p = s + 1; } } strip_slashs(p); if ((s = strstr(p, "/")) != NULL) { action = estrndup(p, s - p); p = s + 1; } strip_slashs(p); if (*p != '\0') { do { if (!module && !controller && !action) { if (yaf_application_is_module_name(p, strlen(p) TSRMLS_CC)) { module = estrdup(p); break; } } if (!controller) { controller = estrdup(p); break; } if (!action) { action = estrdup(p); break; } rest = estrdup(p); } while (0); } if (module && controller == NULL) { controller = module; module = NULL; } else if (module && action == NULL) { action = controller; controller = module; module = NULL; } else if (controller && action == NULL ) { /* /controller */ if (YAF_G(action_prefer)) { action = controller; controller = NULL; } } } while (0); if (module != NULL) { zend_update_property_string(yaf_request_ce, request, ZEND_STRL(YAF_REQUEST_PROPERTY_NAME_MODULE), module TSRMLS_CC); efree(module); } if (controller != NULL) { zend_update_property_string(yaf_request_ce, request, ZEND_STRL(YAF_REQUEST_PROPERTY_NAME_CONTROLLER), controller TSRMLS_CC); efree(controller); } if (action != NULL) { zend_update_property_string(yaf_request_ce, request, ZEND_STRL(YAF_REQUEST_PROPERTY_NAME_ACTION), action TSRMLS_CC); efree(action); } if (rest) { params = yaf_router_parse_parameters(rest TSRMLS_CC); (void)yaf_request_set_params_multi(request, params TSRMLS_CC); zval_ptr_dtor(¶ms); efree(rest); } }
/** {{{ int yaf_route_map_route(yaf_route_t *route, yaf_request_t *request) */ int yaf_route_map_route(yaf_route_t *route, yaf_request_t *request) { zval *ctl_prefer, *delimer, *zuri, *base_uri, params; char *req_uri, *tmp, *rest, *ptrptr, *seg; char *query_str = NULL; uint seg_len = 0; smart_str route_result = {0}; zuri = zend_read_property(yaf_request_ce, request, ZEND_STRL(YAF_REQUEST_PROPERTY_NAME_URI), 1, NULL); base_uri = zend_read_property(yaf_request_ce, request, ZEND_STRL(YAF_REQUEST_PROPERTY_NAME_BASE), 1, NULL); ctl_prefer = zend_read_property(yaf_route_map_ce, route, ZEND_STRL(YAF_ROUTE_MAP_VAR_NAME_CTL_PREFER), 1, NULL); delimer = zend_read_property(yaf_route_map_ce, route, ZEND_STRL(YAF_ROUTE_MAP_VAR_NAME_DELIMETER), 1, NULL); if (base_uri && IS_STRING == Z_TYPE_P(base_uri) && !strncasecmp(Z_STRVAL_P(zuri), Z_STRVAL_P(base_uri), Z_STRLEN_P(base_uri))) { req_uri = estrdup(Z_STRVAL_P(zuri) + Z_STRLEN_P(base_uri)); } else { req_uri = estrdup(Z_STRVAL_P(zuri)); } if (Z_TYPE_P(delimer) == IS_STRING && Z_STRLEN_P(delimer)) { if ((query_str = strstr(req_uri, Z_STRVAL_P(delimer))) != NULL && *(query_str - 1) == '/') { tmp = req_uri; rest = query_str + Z_STRLEN_P(delimer); if (*rest == '\0') { req_uri = estrndup(req_uri, query_str - req_uri); query_str = NULL; efree(tmp); } else if (*rest == '/') { req_uri = estrndup(req_uri, query_str - req_uri); query_str = estrdup(rest); efree(tmp); } else { query_str = NULL; } } else { query_str = NULL; } } seg = php_strtok_r(req_uri, YAF_ROUTER_URL_DELIMIETER, &ptrptr); while (seg) { seg_len = strlen(seg); if (seg_len) { smart_str_appendl(&route_result, seg, seg_len); } smart_str_appendc(&route_result, '_'); seg = php_strtok_r(NULL, YAF_ROUTER_URL_DELIMIETER, &ptrptr); } if (route_result.s) { ZSTR_LEN(route_result.s)--; ZSTR_VAL(route_result.s)[ZSTR_LEN(route_result.s)] = '\0'; if (Z_TYPE_P(ctl_prefer) == IS_TRUE) { zend_update_property_str(yaf_request_ce, request, ZEND_STRL(YAF_REQUEST_PROPERTY_NAME_CONTROLLER), route_result.s); } else { zend_update_property_str(yaf_request_ce, request, ZEND_STRL(YAF_REQUEST_PROPERTY_NAME_ACTION), route_result.s); } smart_str_free(&route_result); } if (query_str) { (void)yaf_router_parse_parameters(query_str, ¶ms); (void)yaf_request_set_params_multi(request, ¶ms); zval_ptr_dtor(¶ms); efree(query_str); } efree(req_uri); return 1; }
static bool yaf_route_map_route(const Object& o, const Object& request) { auto ptr_uri = request->o_realProp(YAF_REQUEST_PROPERTY_NAME_URI, ObjectData::RealPropUnchecked, "Yaf_Request_Abstract"); auto ptr_base_uri = request->o_realProp(YAF_REQUEST_PROPERTY_NAME_BASE, ObjectData::RealPropUnchecked, "Yaf_Request_Abstract"); auto ptr_ctl_prefer = o->o_realProp(YAF_ROUTE_MAP_VAR_NAME_CTL_PREFER, ObjectData::RealPropUnchecked, "Yaf_Route_Map"); auto ptr_delim = o->o_realProp(YAF_ROUTE_MAP_VAR_NAME_DELIMETER, ObjectData::RealPropUnchecked, "Yaf_Route_Map"); if (ptr_uri == NULL) { raise_warning("invalid uri:%p", ptr_uri); return false; } std::string req_uri; if (ptr_uri && ptr_uri->isString() && ptr_base_uri && ptr_base_uri->isString()&& strncasecmp(ptr_uri->toString().c_str(), ptr_base_uri->toString().c_str(), ptr_base_uri->toString().length()) == 0) { req_uri = std::string(ptr_uri->toString().c_str() + ptr_base_uri->toString().length()); } else { req_uri = std::string(ptr_uri->toString().c_str()); } if (req_uri.length() == 0) { return false; } std::string str_query_str; if (ptr_delim->isString() && ptr_delim->toString().length()) { const char* str_delim = ptr_delim->toString().c_str(); char* tmp_req_uri = strdup(req_uri.c_str()); char* query_str = strstr(tmp_req_uri, str_delim); if (query_str && *(query_str - 1) == '/') { char* rest = query_str + strlen(str_delim); if (*rest == '\0') { req_uri = std::string(req_uri, query_str - tmp_req_uri); query_str = NULL; } else if(*rest == '/') { req_uri = std::string(req_uri, query_str - tmp_req_uri); str_query_str = std::string(rest); } else { query_str = NULL; } } free(tmp_req_uri); } std::string route_result; char* save_ptr = NULL; char* tmp = strdup(req_uri.c_str()); char* seg = strtok_r(tmp, YAF_ROUTER_URL_DELIMIETER, &save_ptr); while (seg) { int seg_len = strlen(seg); if (seg_len) { route_result += seg; } route_result += "_"; seg = strtok_r(NULL, YAF_ROUTER_URL_DELIMIETER, &save_ptr); } free(tmp); if (route_result.length()) { if (route_result[route_result.length() - 1] == '_') { route_result.pop_back(); } if (ptr_ctl_prefer->toBoolean()) { auto ptr_controller = request->o_realProp(YAF_REQUEST_PROPERTY_NAME_CONTROLLER, ObjectData::RealPropUnchecked, "Yaf_Request_Abstract"); *ptr_controller = String(route_result); } else { auto ptr_action = request->o_realProp(YAF_REQUEST_PROPERTY_NAME_ACTION, ObjectData::RealPropUnchecked, "Yaf_Request_Abstract"); *ptr_action = String(route_result); } } if (str_query_str.length()) { Array arr = yaf_router_parse_parameters(str_query_str.c_str()); yaf_request_set_params_multi(&request, arr); } return true; }
static Variant yaf_route_rewrite_match(const Object& o, const char* req_uri, int req_uri_len) { char match[8192]; auto ptr_match = o->o_realProp(YAF_ROUTE_PROPETY_NAME_MATCH, ObjectData::RealPropUnchecked, "Yaf_Route_Rewrite"); snprintf(match, sizeof(match), "%s", ptr_match->toString().c_str()); std::string pattern; pattern.append(YAF_ROUTE_REGEX_DILIMITER_STR); pattern.append("^"); char* save_ptr; char* seg = strtok_r(match, YAF_ROUTER_URL_DELIMIETER, &save_ptr); while (seg != NULL) { int len = strlen(seg); if (len) { pattern.append(YAF_ROUTER_URL_DELIMIETER); if (*seg == '*') { pattern.append("(?P<__yaf_route_rest>.*)"); break; } if (*seg == ':') { pattern.append("(?P<"); pattern.append(std::string(seg+1)); pattern.append(std::string(">[^") + YAF_ROUTER_URL_DELIMIETER + "]+)"); } else { pattern.append(seg); } } seg = strtok_r(NULL, YAF_ROUTER_URL_DELIMIETER, &save_ptr); } pattern.append(YAF_ROUTE_REGEX_DILIMITER_STR); pattern.append("i"); Variant matches; Variant ret = preg_match_all(String(pattern), String(std::string(req_uri, req_uri_len)), matches); int match_count = 0; if (ret.isIntVal() ) { match_count = ret.toInt32(); } if (match_count <= 0) { return init_null_variant; } if (!matches.isArray()) { return init_null_variant; } Array args = Array::Create(); Array& arr_matches = matches.toArrRef(); ArrayIter iter = arr_matches.begin(); while (!iter.end()) { Variant key = iter.first(); Variant value = iter.second(); if (!key.isString()) { iter.next(); continue; } if (!strncmp(key.toString().c_str(), "__yaf_route_rest", key.toString().length())) { Variant retval = yaf_router_parse_parameters(value.toArrRef()[0].toString().c_str()); if (retval.isArray()) { args.merge(retval.toArray()); } } else { args.set(key, value.toArrRef()[0]); } iter.next(); } return args; }