// linear search for domain (and * if available) static const tldnode * findTldNode(const tldnode *parent, const char *seg_start, const char *seg_end) { const tldnode *allNode = 0; for (unsigned int i = 0; i < parent->num_children; i++) { if (!allNode && subnodes(parent)[i]->attr == ALL) allNode = subnodes(parent)[i]; else { size_t m = seg_end - seg_start; size_t n = strlen(subnodes(parent)[i]->label); if (m == n && !memcmp(subnodes(parent)[i]->label, seg_start, n)) return subnodes(parent)[i]; } } return allNode; }
static void printTldTreeI(const tldnode *node, const char *spacer) { if (node->attr) printf("%s%s: %c\n", spacer, node->label, node->attr); else printf("%s%s:\n", spacer, node->label); if (node->num_children > 0) { size_t n = strlen(spacer); char nspacer[n+2+1]; memcpy(nspacer, spacer, n); nspacer[n] = ' '; nspacer[n+1] = ' '; nspacer[n+2] = '\0'; for (unsigned int i = 0; i < node->num_children; i++) printTldTreeI(subnodes(node)[i], nspacer); } }
/* * Get next rendered chunk */ PyObject * tdi_render_next(tdi_render_t *self) { PyObject *tmp, *endtag, *nodes, *esc; tdi_node_t *node; int done, asked; switch (self->stage) { case TDI_RE_STAGE_ONLY_CONTENT: self->stage = TDI_RE_STAGE_DONE; Py_INCREF(self->model); return self->model; case TDI_RE_STAGE_BEGIN: self->stage = TDI_RE_STAGE_NEXTNODE; case TDI_RE_STAGE_NEXTNODE: tdi_re_stage_nextnode: if (!self->stack) { self->stage = TDI_RE_STAGE_DONE; goto exit; } if (!(tmp = PyIter_Next(self->stack->iter))) { if (PyErr_Occurred()) goto exit; self->done = self->stack->done; self->endtag = self->stack->endtag; Py_XINCREF(self->endtag); tdi_render_stack_pop(&self->stack); goto tdi_re_stage_endtag; } node = (tdi_node_t *)tmp; if (node->kind == TEXT_NODE) { tmp = self->emit_escaped ? node->content->with_escapes : node->content->clean; Py_INCREF(tmp); Py_DECREF(node); return tmp; } if (node->flags & NODE_REMOVED) { Py_DECREF(node); goto tdi_re_stage_nextnode; } if ((asked = ask_model(self, node, &done)) == -1) { Py_DECREF(node); goto exit; } if (asked == 1) { Py_DECREF(node); goto tdi_re_stage_nextnode; } if (!(node->flags & (NODE_NOELEMENT | NODE_MASKED))) { if (!(tmp = ENCODE_STARTTAG(node))) { Py_DECREF(node); goto exit; } asked = 1; Py_INCREF(node->endtag); endtag = node->endtag; } else endtag = NULL; if (node->content) { if (self->emit_escaped) { if (node->content->with_escapes) { Py_INCREF(node->content->with_escapes); self->content = node->content->with_escapes; } else { if (!(esc = ENCODE_ESCAPE(node, node->content->clean))) { Py_DECREF(node); goto exit; } self->content = esc; } } else { Py_INCREF(node->content->clean); self->content = node->content->clean; } Py_DECREF(node); self->endtag = endtag; self->stage = TDI_RE_STAGE_CONTENT; if (asked != 1) goto tdi_re_stage_content; } else { nodes = subnodes(node, (tdi_adapter_t *)self->model); Py_DECREF(node); if (!nodes) goto exit; if (tdi_render_stack_push(&self->stack, nodes, endtag, self->done) == -1) goto exit; if (done) self->done = 1; if (asked != 1) goto tdi_re_stage_nextnode; } return tmp; case TDI_RE_STAGE_CONTENT: tdi_re_stage_content: self->stage = self->endtag ? TDI_RE_STAGE_ENDTAG : TDI_RE_STAGE_NEXTNODE; tmp = self->content; self->content = NULL; return tmp; case TDI_RE_STAGE_ENDTAG: tdi_re_stage_endtag: self->stage = TDI_RE_STAGE_NEXTNODE; if (!self->endtag) goto tdi_re_stage_nextnode; tmp = self->endtag; self->endtag = NULL; return tmp; case TDI_RE_STAGE_DONE: goto exit; } exit: return NULL; }
static char * getRegisteredDomainDropI(const char *hostname, const tldnode *tree, int drop_unknown) { // Eliminate some special (always-fail) cases first. if (hostname[0] == '.' || hostname[0] == '\0') return 0; // The registered domain will always be a suffix of the input hostname. // Start at the end of the name and work backward. const char *head = hostname; const char *seg_end = hostname + strlen(hostname); const char *seg_start; if (seg_end[-1] == '.') seg_end--; seg_start = seg_end; for (;;) { while (seg_start > head && *seg_start != '.') seg_start--; if (*seg_start == '.') seg_start++; // [seg_start, seg_end) is one label. const tldnode *subtree = findTldNode(tree, seg_start, seg_end); if (!subtree || (subtree->num_children == 1 && subnodes(subtree)[0]->attr == THIS)) // Match found. break; if (seg_start == head) // No match, i.e. the input name is too short to be a // registered domain. return 0; // Advance to the next label. tree = subtree; if (seg_start[-1] != '.') abort(); seg_end = seg_start - 1; seg_start = seg_end - 1; } // Ensure the stripped domain contains at least two labels. if (!strchr(seg_start, '.')) { if (seg_start == head || drop_unknown) return 0; seg_start -= 2; while (seg_start > head && *seg_start != '.') seg_start--; if (*seg_start == '.') seg_start++; } #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" return (char *)seg_start; #pragma GCC diagnostic pop }