Index: doxygentrac/doxygentrac.py
===================================================================
--- doxygentrac/doxygentrac.py	(revision 417)
+++ doxygentrac/doxygentrac.py	(working copy)
@@ -6,14 +6,18 @@
 from __future__ import generators
 
 import os
+import os.path
 import time
 import posixpath
 import re
+import mimetypes
 
 from trac.core import *
 from trac.web import IRequestHandler
 from trac.web.chrome import INavigationContributor, ITemplateProvider
 from trac.Search import ISearchSource
+from trac.perm import IPermissionRequestor
+from trac.wiki import IWikiSyntaxProvider
 from trac.util import Markup
 
 def compare_rank(x, y):
@@ -21,45 +25,84 @@
         return 0
     elif x['rank'] > y['rank']:
         return -1
-    
     return 1
 
 class DoxygenPlugin(Component):
-    implements(INavigationContributor, IRequestHandler, ITemplateProvider, ISearchSource)
+    implements(IPermissionRequestor, INavigationContributor, IRequestHandler,
+      ITemplateProvider, ISearchSource, IWikiSyntaxProvider)
 
+    # IPermissionRequestor methods
+
+    def get_permission_actions(self):
+        return ['DOXYGEN_VIEW']
+
     # INavigationContributor methods
 
     def get_active_navigation_item(self, req):
         return 'doxygen'
     def get_navigation_items(self, req):
-        yield ('mainnav', 'doxygen', Markup('<a href="%s">Doxygen</a>', self.env.href.doxygen()))
+        if not req.perm.has_permission('DOXYGEN_VIEW'):
+            return
+        yield 'mainnav', 'doxygen', Markup('<a href="%s">%s</a>' % \
+          (self.env.href.doxygen(), self.env.config.get('doxygen',
+          'title', 'Doxygen')))
 
     # IRequestHandler methods
 
     def match_request(self, req):
-        if req.path_info == '/doxygen':
-            req.args['path'] = ''.join([self.config.get('doxygen', 'path'), '/main.html'])
+        # getting config values
+        ext = self.config.get('doxygen', 'ext')
+        if ext:
+            ext = '|'.join(ext.split(' '))
+        else:
+            ext = 'htm|html|png'
+
+        path = self.config.get('doxygen', 'path')
+        wiki_index =  self.config.get('doxygen', 'wiki_index')
+
+        # don't know why my trac append slash at end of DoxygenPlugin URI.
+        if re.match('^%s[/]*$' % (self.env.href.doxygen()), req.path_info):
+            req.args['path'] = self.env.href.wiki(wiki_index)
+            req.args['type'] = 'index'
             return True
-        elif re.match(r'''^/.*[.]html$''', req.path_info):
-            self.log.debug("path = %s" % (req.path_info))
-            path = ''.join([self.config.get('doxygen', 'path'), req.path_info])
+        elif re.match('^%s/.*/search.php$' % (self.env.href.doxygen()),
+          req.path_info):
+            req.args['type'] = 'text/html'
+            return True
+        elif re.match('^%s/.*[.](%s)$' % (self.env.href.doxygen(), ext),
+          req.path_info):
+            file = re.sub('^%s' % (self.env.href.doxygen()), '', req.path_info)
+            path = self.env.href(path, file)
             req.args['path'] = path
+            req.args['type'] = mimetypes.guess_type(path)[0]
             return os.path.exists(path)
-        
         return False
 
     def process_request(self, req):
-        req.hdf['doxygen.path'] = req.args['path']
-        return 'doxygen.cs', 'text/html'
+        if req.args.has_key('query'):
+            req.redirect('/search?q=%s&doxygen=on' % (req.args['query']))
+            return None
+        elif req.args['type'] == 'index':
+            req.redirect(req.args['path'])
+            return None
+        elif req.args['type'] == 'text/html':
+            req.hdf['doxygen.path'] = req.args['path']
+        else:
+            req.send_file(req.args['path'], req.args['type'])
+        return 'doxygen.cs', req.args['type']
 
     # ITemplateProvider methods
 
+    def get_htdocs_dirs(self):
+        from pkg_resources import resource_filename
+        return [('doxygen', resource_filename(__name__, 'htdocs'))]
+
     def get_templates_dirs(self):
         from pkg_resources import resource_filename
         return [resource_filename(__name__, 'templates')]
 
     # ISearchProvider methods
-    
+
     def get_search_filters(self, req):
         yield('doxygen', 'Doxygen')
 
@@ -70,34 +113,43 @@
             keywords = [query[1:-1]]
         else:
             keywords = query.split(' ')
-  
+
         path = self.config.get('doxygen', 'path')
-        path = ''.join([path, '/search.idx'])
 
-        if os.path.exists(path): 
-            fd = open(path)
-            
-            results = []
-            for keyword in keywords:
-                results += self._search(fd, keyword)
-            
-            results.sort(compare_rank)            
-            
-            # use the creation time for the search.idx file for all results      
-            creation = os.path.getctime(path)
+        for dir in os.listdir(path):
+            if os.path.isdir(os.path.join(path, dir)):
+                index = os.path.join(path, dir, 'search.idx')
+                fd = open(index)
 
-            for result in results:
-                yield result['url'], result['name'], creation, 'doxygen', None
-    
+                results = []
+                for keyword in keywords:
+                    results += self._search(fd, keyword)
+
+                results.sort(compare_rank)
+
+                # use the creation time for the search.idx file for all results
+                creation = os.path.getctime(path)
+
+                for result in results:
+                    yield (self.env.href('doxygen', dir, str(result['url'])),
+                      result['name'], creation, 'doxygen', None)
+
+    # IWikiSyntaxProvider
+    def get_link_resolvers(self):
+        yield ('doxygen', self._doxygen_link)
+
+    def get_wiki_syntax(self):
+        return []
+
     # internal methods
-        
+
     def _search(self, fd, word):
         results = []
         index = self._computeIndex(word)
         if index != -1:
             fd.seek(index * 4 + 4, 0)
             index = self._readInt(fd)
-            
+
             if index:
                 fd.seek(index)
                 w = self._readString(fd)
@@ -108,7 +160,7 @@
                     if w.find(low) != -1:
                         matches.append({'word' : word, 'match' : w, 'index' : statIdx, 'full' : len(low) == len(w)})
                     w = self._readString(fd)
-                
+
                 count = 0
                 totalHi = 0
                 totalFreqHi = 0
@@ -121,7 +173,7 @@
 
                     fd.seek(match['index'])
                     numDocs = self._readInt(fd)
-                   
+
                     for i in range(numDocs):
                         idx = self._readInt(fd)
                         freq = self._readInt(fd)
@@ -131,7 +183,7 @@
                             totalFreqHi += freq * multiplier
                         else:
                             totalFreqLo += freq * multiplier
-                    
+
                     for i in range(numDocs):
                         fd.seek(results[count]['idx'])
                         name = self._readString(fd)
@@ -139,7 +191,7 @@
                         results[count]['name'] = name
                         results[count]['url'] = url
                         count += 1
-                
+
                 totalFreq = (totalHi + 1) * totalFreqLo + totalFreqHi
                 for i in range(count):
                     freq = results[i]['freq']
@@ -148,40 +200,44 @@
                         results[i]['rank'] = float((freq * multi + totalFreqLo)) / float(totalFreq)
                     else:
                         results[i]['rank'] = float((freq * multi)) / float(totalFreq)
-                        
+
         return results
 
     def _computeIndex(self, word):
         if len(word) < 2:
             return -1
-        
+
         hi = ord(word[0].lower())
         if hi == 0:
             return -1
-            
+
         lo = ord(word[1].lower())
         if lo == 0:
             return -1
-       
+
         return hi * 256 + lo
-        
+
     def _readInt(self, fd):
         b1 = fd.read(1)
         b2 = fd.read(1)
         b3 = fd.read(1)
         b4 = fd.read(1)
-        
+
         return (ord(b1) << 24) | (ord(b2) << 16) | (ord(b3) << 8) | ord(b4)
-    
-    
+
     def _readString(self, fd):
-        byte = fd.read(1)
-        if byte == '\0':
-            return ""
-        result = byte
-        while byte != '\0':
-            byte = fd.read(1)
-            result = ''.join([result, byte])
-    
-        return result
+        result = ''
+        while True:
+           byte = fd.read(1)
+           if byte == '\0':
+               return result
+           else:
+               result = ''.join([result, byte])
 
+    def _doxygen_link(self, formatter, ns, params, label):
+        if ns == 'doxygen':
+            return '<a href="%s" title="%s">%s</a>' % \
+              (self.env.href.doxygen(params), params, label)
+        else:
+            return '<a href="%s" class="missing">%s?</a>' % \
+              (self.env.href.doxygen(), label)
Index: setup.py
===================================================================
--- setup.py	(revision 417)
+++ setup.py	(working copy)
@@ -42,5 +42,5 @@
     """,
     zip_safe=True,
     packages=['doxygentrac'],
-    package_data={'doxygentrac': ['templates/*.cs']},
+    package_data={'doxygentrac': ['templates/*.cs', 'htdocs/css/*.css']},
     entry_points={'trac.plugins': 'doxygentrac = doxygentrac.doxygentrac'})
