[S] Dokumentenindexer

Alles was sonst Nirgends passt
User avatar
Joe User
Project Manager
Project Manager
Posts: 11183
Joined: 2003-02-27 01:00
Location: Hamburg
 

[S] Dokumentenindexer

Post by Joe User »

Moin,

ich suche eine leichtgewichtige Alternative zu Sphinx mit der statische Dokumente (HTML, XML, PDF, PlainText) indexiert und durchsucht werden können.
Die Dokumente liegen direkt im Dateisystem, also keine Skriptsprachen und Datenbanken im Spiel, über mehrere Verzeichnisse verteilt und es werden bis zu 100.000 Dokumente erwartet. Der Index soll stündlich per Cron aktualisiert und webbasiert durchsucht werden können.

Voraussetzungen:
  • Open-Source
  • C, C++, Perl, Python oder PHP5
  • Dateibasierter Index (keine Datenbank)
  • Kostenfreie kommerzielle Nutzung
Gruss,
Joe User
PayPal.Me/JoeUserFreeBSD Remote Installation
Wings for LifeWings for Life World Run

„If there’s more than one possible outcome of a job or task, and one
of those outcomes will result in disaster or an undesirable consequence,
then somebody will do it that way.“ -- Edward Aloysius Murphy Jr.
User avatar
daemotron
Administrator
Administrator
Posts: 2641
Joined: 2004-01-21 17:44
 

Re: [S] Dokumentenindexer

Post by daemotron »

Da ich Deine Abneigung gegen Java kenne, Lucene aber die defacto-Referenz im FOSS-Umfeld ist, hier ein Port von Lucene auf C:

http://incubator.apache.org/lucy/

Leider gibt es noch kein Release, man muss also mit dem Code aus dem Development-Branch hantieren. Erfahrungen habe ich mit Lucy bisher keine.
“Some humans would do anything to see if it was possible to do it. If you put a large switch in some cave somewhere, with a sign on it saying 'End-of-the-World Switch. PLEASE DO NOT TOUCH', the paint wouldn't even have time to dry.” — Terry Pratchett, Thief of Time
Roger Wilco
Posts: 5923
Joined: 2004-05-23 12:53
 

Re: [S] Dokumentenindexer

Post by Roger Wilco »

Prinzipiell könnte ht://Dig die Anforderungen erfüllen, allerdings ist das letzte Release schon etwas angestaubt.
User avatar
Joe User
Project Manager
Project Manager
Posts: 11183
Joined: 2003-02-27 01:00
Location: Hamburg
 

Re: [S] Dokumentenindexer

Post by Joe User »

Es kommt jetzt erstmal mnoGoSearch zum Einsatz, da es relativ leichtgewichtig und unkompliziert zu konfigurieren ist. Ich hoffe nur, dass es sich langfristig auch im Praxiseinsatz bewährt ;)

Unabhängig davon suche ich weiterhin nach Alternativen.
PayPal.Me/JoeUserFreeBSD Remote Installation
Wings for LifeWings for Life World Run

„If there’s more than one possible outcome of a job or task, and one
of those outcomes will result in disaster or an undesirable consequence,
then somebody will do it that way.“ -- Edward Aloysius Murphy Jr.
User avatar
Joe User
Project Manager
Project Manager
Posts: 11183
Joined: 2003-02-27 01:00
Location: Hamburg
 

Re: [S] Dokumentenindexer

Post by Joe User »

Ich brauche mal ein wenig C-Nachhilfe ;)
Folgende Funktion ersetzt offenbar 'selected="$&(*)"' durch 'selected="selected"'
oder durch '', soweit OK. Ich brauche aber eine Erweiterung der Funktion zum
Ersetzen von 'checked="$&(*)' nach gleichem Muster.

Code: Select all

static size_t PrintTagTemplate(UDM_AGENT *Agent,FILE *stream,
                               char *dst,size_t dst_len,
                               UDM_VARLIST *vars,const char *tok,
                               const char *HlBeg, 
                               const char *HlEnd)
{
  char * opt;
  UDM_HTMLTOK ltag, *tag = &ltag;
  const char *last;
  UDM_VAR * var=NULL;
  char * vname = NULL, *value = NULL;
  size_t i, res = 0;
  
  opt = (char*)UdmMalloc(strlen(tok) + 200);
  UdmHTMLTOKInit(tag);
  UdmHTMLToken(tok, &last, tag);
  sprintf(opt, "<");

  for (i = 0; i < ltag.ntoks; i++)
  {
    const char *space= (i == 0) ? "" : " ";
    if (ISTAG(i, "selected") && ltag.toks[i].vlen)
    {
      vname = UdmStrndup(ltag.toks[i].val, ltag.toks[i].vlen);
    }
    else if (ISTAG(i, "value"))
    {
      value = UdmStrndup(ltag.toks[i].val, ltag.toks[i].vlen);
      sprintf(UDM_STREND(opt), "%svalue=\"%s\"", space, value);
    }
    else
    {
      char *tname = UdmStrndup(ltag.toks[i].name, ltag.toks[i].nlen);
      if (ltag.toks[i].vlen)
      {
        char *tval = UdmStrndup(ltag.toks[i].val, ltag.toks[i].vlen);
        sprintf(UDM_STREND(opt), "%s%s=\"%s\"", space, tname, tval);
        UDM_FREE(tval);
      }
      else
      {
         sprintf(UDM_STREND(opt), "%s%s", space, tname);
      }
      UDM_FREE(tname);
    }
  }

  if(vname)
  {
    var= UdmVarListFindWithValue(vars, UdmTrim(vname, "$&()"), value ? value:"");
  }

  sprintf(UDM_STREND(opt), "%s>", var ? " selected=\"selected\"":"");

  if (vname) { UDM_FREE(vname); }
  if (value) { UDM_FREE(value); }

  res = PrintTextTemplate(Agent, stream, dst, dst_len, vars, opt, HlBeg, HlEnd);
  UDM_FREE(opt);
  return res;
}
Das if..else im for-Loop bekomme ich ja noch selbst erweitert, aber beim letzten sprintf muss ich dann doch passen :/

Vermutlich sehr primitiv und ich stehe momentan nur gewaltig auf dem Schlauch, aber ich bekomme es gerade ums Verrecken nicht gebacken.


BTW: Wie schiebe ich dem FreeBSD-Port den Patch am Geschicktesten unter, ohne es bei jedem Portupdate manuell wiederholen zu müssen?
Last edited by Joe User on 2011-03-30 12:34, edited 2 times in total.
PayPal.Me/JoeUserFreeBSD Remote Installation
Wings for LifeWings for Life World Run

„If there’s more than one possible outcome of a job or task, and one
of those outcomes will result in disaster or an undesirable consequence,
then somebody will do it that way.“ -- Edward Aloysius Murphy Jr.
User avatar
daemotron
Administrator
Administrator
Posts: 2641
Joined: 2004-01-21 17:44
 

Re: [S] Dokumentenindexer

Post by daemotron »

Das könnte es tun:

Code: Select all

static size_t PrintTagTemplate(UDM_AGENT *Agent,FILE *stream,
                               char *dst,size_t dst_len,
                               UDM_VARLIST *vars,const char *tok,
                               const char *HlBeg, 
                               const char *HlEnd)
{
  char * opt;
  UDM_HTMLTOK ltag, *tag = &ltag;
  const char *last;
  UDM_VAR * var=NULL;
  UDM_VAR * var2=NULL;
  char * vname = NULL, *value = NULL;
  char * vname2 = NULL, *value2 = NULL;
  size_t i, res = 0;
  
  opt = (char*)UdmMalloc(strlen(tok) + 200);
  UdmHTMLTOKInit(tag);
  UdmHTMLToken(tok, &last, tag);
  sprintf(opt, "<");

  for (i = 0; i < ltag.ntoks; i++)
  {
    const char *space= (i == 0) ? "" : " ";
    if (ISTAG(i, "selected") && ltag.toks[i].vlen)
    {
      vname = UdmStrndup(ltag.toks[i].val, ltag.toks[i].vlen);
    }
    else if (ISTAG(i, "checked") && ltag.toks[i].vlen)
    {
      vname2 = UdmStrndup(ltag.toks[i].val, ltag.toks[i].vlen);
    }
    else if (ISTAG(i, "value"))
    {
      value = UdmStrndup(ltag.toks[i].val, ltag.toks[i].vlen);
      sprintf(UDM_STREND(opt), "%svalue=\"%s\"", space, value);
    }
    else
    {
      char *tname = UdmStrndup(ltag.toks[i].name, ltag.toks[i].nlen);
      if (ltag.toks[i].vlen)
      {
        char *tval = UdmStrndup(ltag.toks[i].val, ltag.toks[i].vlen);
        sprintf(UDM_STREND(opt), "%s%s=\"%s\"", space, tname, tval);
        UDM_FREE(tval);
      }
      else
      {
         sprintf(UDM_STREND(opt), "%s%s", space, tname);
      }
      UDM_FREE(tname);
    }
  }

  if(vname)
  {
    var= UdmVarListFindWithValue(vars, UdmTrim(vname, "$&()"), value ? value:"");
  }
  
  if(vname2)
  {
    var2= UdmVarListFindWithValue(vars, UdmTrim(vname2, "$&()"), value2 ? value2:"");
  }

  sprintf(UDM_STREND(opt), "%s%s>", var ? " selected=\"selected\"":"", var2 ? " checked=\"checked\"":"");

  if (vname) { UDM_FREE(vname); }
  if (value) { UDM_FREE(value); }
  if (vname2) { UDM_FREE(vname2); }
  if (value2) { UDM_FREE(value2); }

  res = PrintTextTemplate(Agent, stream, dst, dst_len, vars, opt, HlBeg, HlEnd);
  UDM_FREE(opt);
  return res;
}
Last edited by daemotron on 2011-03-30 18:18, edited 1 time in total.
“Some humans would do anything to see if it was possible to do it. If you put a large switch in some cave somewhere, with a sign on it saying 'End-of-the-World Switch. PLEASE DO NOT TOUCH', the paint wouldn't even have time to dry.” — Terry Pratchett, Thief of Time
User avatar
Joe User
Project Manager
Project Manager
Posts: 11183
Joined: 2003-02-27 01:00
Location: Hamburg
 

Re: [S] Dokumentenindexer

Post by Joe User »

Wunderbar, danke Dir! Das hätte mir eigentlich auch einfallen müssen :/
PayPal.Me/JoeUserFreeBSD Remote Installation
Wings for LifeWings for Life World Run

„If there’s more than one possible outcome of a job or task, and one
of those outcomes will result in disaster or an undesirable consequence,
then somebody will do it that way.“ -- Edward Aloysius Murphy Jr.
User avatar
daemotron
Administrator
Administrator
Posts: 2641
Joined: 2004-01-21 17:44
 

Re: [S] Dokumentenindexer

Post by daemotron »

Hm, mir gefällt der Code ehrlich gesagt nicht besonders... gerade das sprintf ist nicht ungefährlich, da in einen begrenzt großen Buffer geschrieben wird, ohne dass eine Prüfung auf die Anzahl der zu schreibenden Bytes stattfindet. snprintf wäre eine sicherere Alternative, oder ich müsste mich noch mal in den gesamten Code reinfummeln und versuchen herauszufinden, wie groß opt schlimmstenfalls werden kann.

Kleine Optimierung:

Code: Select all

snprintf(UDM_STREND(opt), strlen(tok) + 200 - 1, "%s%s>", var ? " selected=\"selected\"":"", var2 ? " checked=\"checked\"":"");
P. S. hab grade gesehen, dass da noch mehr sprintf()s drinne sind, bei denen kein Buffer Overflow abgefangen wird :(
Last edited by daemotron on 2011-03-30 21:09, edited 1 time in total.
“Some humans would do anything to see if it was possible to do it. If you put a large switch in some cave somewhere, with a sign on it saying 'End-of-the-World Switch. PLEASE DO NOT TOUCH', the paint wouldn't even have time to dry.” — Terry Pratchett, Thief of Time
User avatar
Joe User
Project Manager
Project Manager
Posts: 11183
Joined: 2003-02-27 01:00
Location: Hamburg
 

Re: [S] Dokumentenindexer

Post by Joe User »

mnogosearch-3.3.11/src/template.c ist das Sourcefile. Das Template ist statisch und wird zur Runtime geparsed. Es müsste also das Templatefile gegen ein manipuliertes im Filesystem ersetzt werden. Wenn der Angreifer soweit kommt, hat er ohnehin genug Rechte, so dass er sich den Spass schenken kann. Trotzdem könnte ein Audit natürlich nie schaden, insbesondere bei einer so stark verbreiteten und mehrfach geforkten Software.
PayPal.Me/JoeUserFreeBSD Remote Installation
Wings for LifeWings for Life World Run

„If there’s more than one possible outcome of a job or task, and one
of those outcomes will result in disaster or an undesirable consequence,
then somebody will do it that way.“ -- Edward Aloysius Murphy Jr.
User avatar
Joe User
Project Manager
Project Manager
Posts: 11183
Joined: 2003-02-27 01:00
Location: Hamburg
 

Re: [S] Dokumentenindexer

Post by Joe User »

Punkt für Dich! Noch bin ich auf der betroffenen Maschine zwar mein eigener Kollege, aber das könnte sich langfristig ändern. Andererseits hoffe ich, dass die potentiellen Overflows an anderer Stelle (UDMMalloc?) abgefangen werden. Habe von C leider immernoch zu wenig Ahnung :/ Wird Zeit, dass ich mal wieder Zeit zum Lernen finde...
PayPal.Me/JoeUserFreeBSD Remote Installation
Wings for LifeWings for Life World Run

„If there’s more than one possible outcome of a job or task, and one
of those outcomes will result in disaster or an undesirable consequence,
then somebody will do it that way.“ -- Edward Aloysius Murphy Jr.
User avatar
daemotron
Administrator
Administrator
Posts: 2641
Joined: 2004-01-21 17:44
 

Re: [S] Dokumentenindexer

Post by daemotron »

So, ich hab mir das ganze noch mal etwas genauer angeschaut. Zunächst einmal, das von mir angemäkelte sprintf() schreibt in einen (vermutlich) ausreichend dimensionierten Buffer. Sollten allerdings noch weitere Anhänge drangebastelt werden, sollten die +200 Bytes (in Zeile 16 in obigem Code, original Zeile 770) nach oben gesetzt werden.

Sodann hat ein bisschen weiteres Graben tatsächlich zu Tage gefördert, dass UdmMalloc() die Ausnutzbarkeit eines Buffer Overflows einschränkt. Speicher für Buffer werden dabei so allokiert, dass dahinter immer ein für den Prozess ungültiger Speicherbereich liegt. Das führt dazu, dass die Anwendung mit einem Segfault stirbt, wenn jemand versucht, da einen Buffer Overflow zu triggern.

Das ist insofern interessant, als man es als zusätzliches Sicherheitsnetz betrachten kann. Eine solche Strategie mit entsprechender Implementierung habe ich noch nirgendwo anders gesehen; malloc()-Wrapper sind zwar üblich, aber meist tun sie nicht mehr, als ENOMEM auf geeignete Weise abzufangen, damit das nicht an jeder Stelle im Code nach einem malloc() ausprogrammiert werden muss. Echt clever, muss ich sagen. Ob das tatsächlich immer und überall auch so funktioniert, kann ich auf die Schnelle allerdings nicht sehen.

Also erst mal Entwarnung: der oder die Programmierer wussten offenbar, was sie da tun. sprinft() anstelle von snprintf() ist stilistisch trotzdem nicht schön - so könnte man den Segfault von vornherein vermeiden und würde so doppelte Sicherheit erreichen - grade auch dann, wenn jemand mal am Code fummelt, um eine zusätzliche Property reinzubasteln, ohne die Speicherallokierung dabei anzupassen :wink:
“Some humans would do anything to see if it was possible to do it. If you put a large switch in some cave somewhere, with a sign on it saying 'End-of-the-World Switch. PLEASE DO NOT TOUCH', the paint wouldn't even have time to dry.” — Terry Pratchett, Thief of Time
User avatar
Joe User
Project Manager
Project Manager
Posts: 11183
Joined: 2003-02-27 01:00
Location: Hamburg
 

Re: [S] Dokumentenindexer

Post by Joe User »

Vielen Dank für den Quick-Audit, das beruhigt doch ungemein. Mit Segfaults kann man deutlich ruhiger leben als mit Overflows.

Schön, dass Du wieder etwas für Dich Neues entdeckt hast ;)
PayPal.Me/JoeUserFreeBSD Remote Installation
Wings for LifeWings for Life World Run

„If there’s more than one possible outcome of a job or task, and one
of those outcomes will result in disaster or an undesirable consequence,
then somebody will do it that way.“ -- Edward Aloysius Murphy Jr.