# -*- coding: ISO-8859-1 -*-
""" capellaScript
>>> Script Download Tk

    Mit diesem Skript werden Capellaskript Dateien von diversen Homepages heruntergeladen
    und in eigene Verzeichnisse "Plugins_<Autor>" im Capella Skript-Verzeichniss abgelegt.
    Die ".py" Dateien werden mit dem Zeitstempel vom Server versehen.
<<<


  File:     Scriptdownload.py
  Author:   Paul Villiger
  e-mail:   villpaul@bluewin.ch
  Created:  20.10.2004
  Modified: 08.04.2010

  Purpose:  Mit diesem Skript werden Capellaskript Dateien von diversen Homepages heruntergeladen
            und in eigene Verzeichnisse "Plugins_<Autor>" im Capella Skript-Verzeichnisses abgelegt.
            Die ".py" Dateien werden mit dem Zeitstempel vom Server versehen.

  Remark:   - Anwendung auf eigene Gefahr
            - Bestehende Skripts im Zielverzeichnis werden überschrieben
            - Skript kann auch ohne Capella aufgerufen werden, dann werden alle Plugins geladen

  Config:   - Die URL-Liste kann beliebig erweitert werden.
            - Zu jeder URL muss ein Zielverzeichnis definiert werden.

  History   20.10.04 Erstausgabe
            21.10.04 Dialog
            22.10.04 Proxywerte unter Optionen speichern
            12.11.04 - nur geänderte oder neue Dateien übertragen
                     - Externer Aufruf: Option -p <proxy>
            16.11.04 - Fehler mit win32traceutil
            24.04.05 - Download der Plugins von der capella-software Homepage
            30.06.05 - Neue HP von Stefan Thierfeldt

            16.07.05 - tk fenster von (Jørgen von Bargen=bassklampfe)
            05.11.05 - probleme mit tk und umlauten behoben (Jørgen von Bargen=bassklampfe)
            05.11.05 - detailiertere Fehlermeldungen (Jørgen von Bargen=bassklampfe)
            12.02.06 - hervorheben von neuen/aktualisierten Dateien (Jørgen von Bargen=bassklampfe)
            21.02.06 - Download von ZIP-Dateien, Link zu Klaus Meglitsch (Paul Villiger)
            01.03.06 - Download von CHM-Dateien
            18.03.06 - Icons werden aus Symbole.zip extrahiert
            19.03.06 - Alle Verzeichnisse werden wieder abgefragt
            01.01.07 - Neue Domain http://freenet-homepage.de/peter.becker/
            25.06.07 - Plugins von Hans H. Lampe
            04.07.07 - neue Domain sins942.ch
            13.10.07 - Behandlung für capella 2008
            13.10.07 - Proxy Behandlung entfernt
            14.10.07 - Korrektur
            27.10.07 - JJvB Download von info und Übersetzung
            29.03.09 - capella new website
            02.03.10 - Peter Becker neue HP
            08.04.10 - Plugin Symbols bei notensatz-fischer
            08.12.10 - Neue Seiten von Peters Homepage eingefügt  (P.Becker)

"""
import urllib2, sys, traceback
import htmllib, formatter, string, time
import urllib, urlparse, os.path, os, shutil, _winreg

def formatExceptionInfo(maxTBlevel=5):
    cla, exc, trbk = sys.exc_info()
    excName = cla.__name__
    try:
        excArgs = exc.__dict__["args"]
    except KeyError:
        excArgs = "<no args>"
    excTb = traceback.format_tb(trbk, maxTBlevel)
    return (excName, excArgs, excTb)

def latin1(u):
    return u.decode('Latin-1')

# JJvB: neue Hilfsfunktion
def has_extension(name,extensions):
    for extension in extensions:
        if name[-len(extension):] == extension:
            #progress.add("\"%s\" is %s",path,extension)
            return True
        #progress.add("\"%s\" not %s",path,extension)
    return False

#-------------------------------------------------------
# ab hier erzeugen des tkfensters
#-------------------------------------------------------

import Tkinter
from Tkinter import *

class StatusBar(Frame):

    def __init__(self, master):
        Frame.__init__(self, master)
        self.label = Label(self, bd=1, relief=SUNKEN, anchor=W)
        self.label.pack(fill=X)

    def set(self, format, *args):
        self.label.config(text=format % args)
        self.label.update_idletasks()
        root.update()

    def clear(self):
        self.label.config(text="")
        self.label.update_idletasks()

class Progress(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)
        self.scrollbar = Scrollbar(self)
        self.scrollbar.pack(side=RIGHT, fill=BOTH)
        self.listbox = Listbox(self,yscrollcommand=self.scrollbar.set,width=80, bd=1, relief=SUNKEN)
        self.listbox.pack(fill=BOTH,expand=1)
        #self.listbox.grid(row=0,column=0,sticky=N+S+W+E)
        self.scrollbar.config(command=self.listbox.yview)

    def add(self, format, *args):
        log.write(format%args)
        log.write('\n')
        self.listbox.insert(END,format % args)
        self.listbox.see(END)
        self.listbox.update_idletasks()
        root.update()

    def set(self, format, *args):
        log.write(format%args)
        log.write('\n')
        self.listbox.delete(END)
        self.listbox.insert(END,format % args)
        self.listbox.see(END)
        self.listbox.update_idletasks()
        root.update()

    def set_color(self,color):
        self.listbox.itemconfigure(END,background=color)

root = Tk()
root.title("Script Download")
progress = Progress(root);
progress.pack(side=TOP, fill=BOTH,expand=1)
status = StatusBar(root)
status.pack(side=BOTTOM, fill=X)
root.update()

scripts_aktuell = 0
scripts_neu = 0
scripts_fehler = 0

log=file('scriptdowload.log','w')
#-------------------------------------------------------
# ab hier unverändert bis auf die progress.add und status.set
#-------------------------------------------------------

ok = True # wird bei einem Fehler auf "False" gesetzt

# JJvB: liste der Extensions
wanted_extensions = ['.py','.zip','.chm','_tr.py','-de.html','-en.html','.info']

excludeFilter = ['Handbuch.zip', 'Update.zip']
downloadManual = False

# Testen ob intern (Capella) oder extern (ohne Capella
try:
    # interner Aufruf
     # if activeScore():
    if activeScore__():      # Fehler erzwingen Tk verträgt sich nicht mit capella Dialog
        internal = True
    options = ScriptOptions()
    opt = options.get()
    options.set(opt)

except:
    # externer Aufruf
    internal = False
    print 'Scriptdownload: External Call'

# Liste der zu untersuchenden URL's. Die Liste kann beliebig erweitert werden.
#            URL                                                             Verzeichnis                Autor
urlList = [('http://www.peter-becker-cap.de/scripts_meine.htm',             'Plugins_Becker',           'Peter Becker'),
           ('http://www.peter-becker-cap.de/scripts_salis.htm',             'Plugins_Becker',           'Peter Becker'),
           ('http://www.peter-becker-cap.de/scripts_lampe.htm',             'Plugins_Becker',           'Peter Becker'),
           ('http://www.peter-becker-cap.de/scripts_capella.htm',           'Plugins_Becker',           'Peter Becker'),
           ('http://www.peter-becker-cap.de/galerien.htm',                  'Plugins_Becker',           'Peter Becker'),
           ('http://www.peter-becker-cap.de/vorlagen.htm',                  'Plugins_Becker',           'Peter Becker'),
           ('http://www.sins942.ch/scripts_pv.html',                        'Plugins_Villiger',         'Paul Villiger'),
           ('http://www.sins942.ch/scripts_ah.html',                        'Plugins_Villiger',         'Andreas Herzog'),
           ('http://www.sins942.ch/scripts_lh.html',                        'Plugins_Villiger',         'Lutz Haas'),
           ('http://www.sins942.ch/scripts_hl.html',                        'Plugins_Villiger',         'Hartmut Lemmel'),
           ('http://www.thierfeldt.homepage.t-online.de/musik/index.html',  'Plugins_Thierfeldt',       'Stefan Thierfeldt'),
           ('http://www.capella.de/Plugins.cfm',                            'Plugins_Capella_Software', 'Capella Software'),
           ('http://www.hanshlampe.de/pageID_4712124.html',                 'Plugins_HHLampe',          'Hans H. Lampe'),
           ('http://www.notensatz-s-fischer.de/capella_Dokumente/html/capella_zubehoer.htm',             'Plugins_Symbols',          'Plugin Svmbols')]


def errorMsg(text):
    progress.add("FEHLER %s",text);

# Capella Verzeichnis aus der Registry auslesen
try:
    r = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, r'Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders')
    homePath, x = _winreg.QueryValueEx(r, 'Personal')
    _winreg.CloseKey(r)
    scriptPath = os.path.join(homePath,'capella', 'scripts')


    version6 = False
    if internal:
        if (6, 0, 0) <= capVersion():
            version6 = True
    elif os.path.exists(scriptPath):
        version6 = True
        if not internal:
            print 'Download for capella 6.'


    if not version6:
        r = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, r'SOFTWARE\capella-software\capella\5.0')
        capPath = os.path.split(_winreg.QueryValueEx(r, 'ExePath')[0])[0]
        _winreg.CloseKey(r)

        scriptPath = os.path.join(capPath,'scripts')
        if not internal:
            print 'Download for capella 5.'
except:
    errorMsg('ERROR reading Capella registry')
    ok = False



if ok and internal:
    selList = ['Alle Plugins']
    for (url, pluginDir, author) in urlList:
        selList.append('Plugins von '+author)
    dlManual = CheckBox('', value = downloadManual)

    selPlugin = Radio(selList,value=0)
    dlg = Dialog('Plugin Download',
                 VBox([selPlugin,
                       Label(' '),
                       HBox([dlManual, Label('Skript Handbuch herunterladen')]),
                       Label(' '),
                       Label('Die Plugins werden im Skript-Verzeichnis', width = 40),
                       Label('unter "Plugins_<Autor>" gespeichert'),
                       ], text='Auswahl')
                 )
    if dlg.run():
        sel = selPlugin.value()
        if sel > 0:
            urlList = [urlList[sel-1]]
        options.set(opt)
        downloadManual = dlManual.value()

    else:
        ok = False


if ok:
    for (url, pluginDir, author) in urlList:
        status.set("url=%s dir=%s aut=%s",url,pluginDir,author)
        if os.path.isdir(scriptPath):
            progress.add("URL    %s",url);
            progress.add("DIR    %s",pluginDir);
            progress.add("AUTHOR %s",author);
            pDir = os.path.join(scriptPath,pluginDir)
            if not os.path.isdir(pDir):
                progress.add("- erzeuge verzeichnis %s",pDir);
                os.mkdir(pDir)   # Plugin Directory erzeugen wenn noch nicht vorhanden

            # URL lesen
            try:
                progress.add("- hole \"%s\"",url)
                f = urllib2.urlopen(url)
                lines = f.read()
                f.close()
            except:
                progress.set("! urlopen \"%s\" fehler (%s)",url,sys.exc_info()[0]);
                progress.set_color('red')
                scripts_fehler = scripts_fehler+1
                continue     # Goto next URL

# nur zu testzwecken
#            try:
#                indexFile = os.path.join(pDir,"index.html")
#                progress.add("- schreibe \"%s\"",indexFile);
#                inf = file(indexFile,'w')
#                inf.write(lines);
#                inf.close();
#            except:
#                progress.set("! schreibe %s fehler (%s)",indexFile,sys.exc_info()[0]);
#                continue     # Goto next URL

            # URL Inhalt nach Links durchsuchen -> anchorlist
            try:
                progress.set("- untersuche %s",url);
                parser = htmllib.HTMLParser(formatter.NullFormatter(), verbose=1)
                parser.feed(lines)
                parser.close()
            except:
                progress.set("! untersuche %s fehler (%s)",url,url,sys.exc_info()[0]);
                progress.set_color('red')
                scripts_fehler = scripts_fehler+1
                continue     # Goto next URL

            for l in parser.anchorlist:

                (addressing_scheme, network_location, path, parameters, query, fragment_identifier) = urlparse.urlparse(l)

                #if path[len(path)-3:] in ['.py','zip','chm']:
                # JJvB: liste der Extensions
                want_it = has_extension(path,wanted_extensions)
                if want_it:
                    progress.add("- script \"%s\"",path)
                    # exludeFilter anwenden
                    if not downloadManual:
                        exclude = False
                        for x in excludeFilter:
                            if x in path:
                                exclude = True
                        if exclude:
                            continue    # Datei überspringen

                    if addressing_scheme <> '' :
                        # Absoluter Link
                        u = l
                    else:
                        # Relativer Link
                        u = urlparse.urljoin(url, path)

                    # Dateinamen aus Link bestimmen
                    (head,tail) = os.path.split(path)
                    tail = latin1(tail)
                    scriptName = tail
                    pluginFile = os.path.join(pDir,tail)

                    if os.path.isfile(pluginFile):
                        modTime = os.stat(pluginFile)[8]
                        modStamp = time.strftime(".%Y.%m.%d", (time.localtime(modTime)))
                        text = 'update'
                    else:
                        modTime = 0.0
                        modStamp = '.-'
                        text = 'neu'

                    # Link in Datei speichern
                    try:
                        progress.set("- hole \"%s\"",u)
                        f = urllib2.urlopen(u)
                    except:
                        progress.set("- urlopen \"%s\" fehler(%s)",u,formatExceptionInfo())
                        progress.set_color('red')
                        scripts_fehler = scripts_fehler+1
                        continue

                    # Speicherdatum des Links bestimmen und Dateidatum setzen
                    t = time.time()    # default actual time
                    try:
                        infoLines = str(f.info()).splitlines()
                        for l in infoLines:
                            if 'Last-Modified: ' == l[0:15]:
                                t = time.mktime(time.strptime(l[15:],'%a, %d %b %Y %H:%M:%S GMT'))
                                break
                    except:
                        progress.set("ERROR setting timestamp of \"%s\"",pluginFile)
                        scripts_fehler = scripts_fehler+1
                        progress.set_color('red')
                        continue

                    log.write('%s : %s %s %s\n' % (scriptName,modTime,modStamp,t))
                    # Datei nur übertragen wenn neuere Datei auf Server vorhanden
                    #  oder sich die Zeit auf dem Server nicht bestimmen lässt
                    if modTime >= t:
                        progress.set("- script %s ist aktuell",scriptName);
                        continue

                    try:
                        progress.set("- script %s (%s) wird gelesen",scriptName,text);
                        data = f.read(-1)
                    except:
                        progress.set("! script read %s fehler (%s)",u,formatExceptionInfo());
                        progress.set_color('red')
                        scripts_fehler = scripts_fehler+1
                        continue     # Goto next file

                    try:
                        old=pluginFile+modStamp+".old"
                        if os.path.isfile(old) :
                            os.unlink(old)
                        if os.path.isfile(pluginFile) :
                            os.rename(pluginFile,old)
                        progress.set("- script %s wird geschrieben",pluginFile);
                        pf = file(pluginFile,'wb')
                        pf.write(data)
                        pf.flush()
                        pf.close()
                        os.utime(pluginFile,(t,t))
                        progress.set("- script %s (%s) aktualisiert",scriptName,text);
                        if modTime :
                            progress.set_color('yellow')
                            scripts_aktuell = scripts_aktuell+1
                        else :
                            progress.set_color('green')
                            scripts_neu = scripts_neu+1

                    except:
                        progress.add("! script.write %s fehler (%s)",u,sys.exc_info()[0]);
                        progress.set_color('red')
                        scripts_fehler = scripts_fehler+1
                        continue     # Goto next file

#----------------------------------------------
# zeige ergebnis
# fenster bleibt offen, bis es geschlossen wird
#----------------------------------------------
progress.add("%d neue scripts",scripts_neu)
progress.add("%d aktualisierte scripts",scripts_aktuell)
if scripts_fehler>0 :
    progress.add("%d Fehler!",scripts_fehler)
status.set(" alles erledigt ")
root.mainloop()

