Top-Themen

AppleEntwicklungHardwareInternetLinuxMicrosoftMultimediaNetzwerkeOff TopicSicherheitSonstige SystemeVirtualisierungWeiterbildungZusammenarbeit

Aktuelle Themen

Administrator.de FeedbackApache ServerAppleAssemblerAudioAusbildungAuslandBackupBasicBatch & ShellBenchmarksBibliotheken & ToolkitsBlogsCloud-DiensteClusterCMSCPU, RAM, MainboardsCSSC und C++DatenbankenDatenschutzDebianDigitiales FernsehenDNSDrucker und ScannerDSL, VDSLE-BooksE-BusinessE-MailEntwicklungErkennung und -AbwehrExchange ServerFestplatten, SSD, RaidFirewallFlatratesGoogle AndroidGrafikGrafikkarten & MonitoreGroupwareHardwareHosting & HousingHTMLHumor (lol)Hyper-VIconsIDE & EditorenInformationsdiensteInstallationInstant MessagingInternetInternet DomäneniOSISDN & AnaloganschlüsseiTunesJavaJavaScriptKiXtartKVMLAN, WAN, WirelessLinuxLinux DesktopLinux NetzwerkLinux ToolsLinux UserverwaltungLizenzierungMac OS XMicrosoftMicrosoft OfficeMikroTik RouterOSMonitoringMultimediaMultimedia & ZubehörNetzwerkeNetzwerkgrundlagenNetzwerkmanagementNetzwerkprotokolleNotebook & ZubehörNovell NetwareOff TopicOpenOffice, LibreOfficeOutlook & MailPapierkorbPascal und DelphiPeripheriegerätePerlPHPPythonRechtliche FragenRedHat, CentOS, FedoraRouter & RoutingSambaSAN, NAS, DASSchriftartenSchulung & TrainingSEOServerServer-HardwareSicherheitSicherheits-ToolsSicherheitsgrundlagenSolarisSonstige SystemeSoziale NetzwerkeSpeicherkartenStudentenjobs & PraktikumSuche ProjektpartnerSuseSwitche und HubsTipps & TricksTK-Netze & GeräteUbuntuUMTS, EDGE & GPRSUtilitiesVB for ApplicationsVerschlüsselung & ZertifikateVideo & StreamingViren und TrojanerVirtualisierungVisual StudioVmwareVoice over IPWebbrowserWebentwicklungWeiterbildungWindows 7Windows 8Windows 10Windows InstallationWindows MobileWindows NetzwerkWindows ServerWindows SystemdateienWindows ToolsWindows UpdateWindows UserverwaltungWindows VistaWindows XPXenserverXMLZusammenarbeit

Xspf autoplaylister

Tipp Entwicklung XML

Mitglied: jutzin

jutzin (Level 1) - Jetzt verbinden

24.06.2009, aktualisiert 13.09.2010, 6508 Aufrufe, 2 Danke

ein aus der windows command shell ausführbarer, scriptbarer xspf autoplaylister. hilft beim rekursiven erstellen von xspf playlists in großen mediensammlungen. funktioniert prima in verbindung mit flashplayern wie z.b. dem jw player.

ich habe vor kurzem Charlie Craigs xspf-playlister von vbs nach js (mit ActiveX und in verbindung mit MP3Tag.dll, also nur unter windows lauffähig) portiert und noch ein paar funktionen hinzugefügt. ursprünglich wollte ich ein utf-8/unicode problem, das beim auslesen der id3 tags von mp3-dateien auftritt, lösen, was mir in vbs zu schwer war; leider funktioniert das immer noch nur bei 2 bytes langen chars, also bis 0xff, d.h. japanische schriftzeichen etc. werden aus den tags immer noch nicht korrekt ausgelesen (die dateinamen können alle schriftzeichen, die in windows möglich sind enthalten und werden korrekt wiedergegeben).

wie auch immer: da ich selber ewig nach einer vernünftigen, scriptbaren lösung für den lokalen einsatz ohne php gesucht habe und es wirklich nur sehr wenig brauchbares in der richtung gibt, dachte ich, ich poste den code, für den fall, dass jemand so etwas sucht.

zur bedienung:
    • einmalige vorbereitungen:
        - besorge Dir die MP3Tag.dll
        - die dll in ein verzeichnis ablegen, in dem sie permanent aufbewahrt werden soll
        - die dll registrieren (in der kommandozeile regsvr32 pfad\zur\dll\MP3Tag.dll eingeben)
        - den untenstehenden javascript code als *.js datei speichern
    • im windows explorer: das verzeichnis mit den mediendateien auf die .js-datei ziehen und loslassen. doppelklick auf die datei gibt ein hilfe-fenster aus.
    • in der windows shell: cscript name_unter_dem_du_das_script_gespeichert_hast.js [optionen] \pfad\zu\den\mediendateien.
       für hilfe zur bedienung: cscript name_unter_dem_du_das_script_gespeichert_hast.js -h

beispiel:
    • folgender shell befehl
01.
for /r /d %%i in (*) do cscript //U //Nologo "ID3_XSPF_Playlister.js" -s "http://mein.server.de" -p a="lw:\das\apache\server\root\verzeichnis" --overwrite "%%~i" 
       erzeugt für jedes unterverzeichnis des aktuellen verzeichnisses eine xml playlist die so aussehen könnte:
01.
<?xml version="1.0" encoding="UTF-8"?> 
02.
<playlist version="1" xmlns="http://xspf.org/ns/0/"> 
03.
 
04.
	<title>playlist title</title> 
05.
 
06.
	<trackList> 
07.
 
08.
		<track> 
09.
			<location>http://mein.server.de/The%20Police/Reggatta%20De%20Blanc/The%20Police%20-%20Reggatta%20De%20Blanc%20-%2001%20-%20Message%20In%20A%20Bottle.mp3</location> 
10.
			<title>Message In A Bottle</title> 
11.
			<creator>The Police</creator> 
12.
			<album>Reggatta De Blanc</album> 
13.
			<tracknum>1/11</tracknum> 
14.
			<length>4m 51s</length> 
15.
			<year>1979</year> 
16.
			<annotation>The Police - Reggatta De Blanc - 01 - Message In A Bottle</annotation> 
17.
			<info>http://www.google.com/search?hl=en&q=The+Police+-+Reggatta+De+Blanc+-+01+-+Message+In+A+Bottle</info> 
18.
		</track> 
19.
 
20.
		<track> 
21.
			<location>http://mein.server.de/Fishmans/Aloha%20Polydor/Fishmans%20-%20Aloha%20Polydor%20-%2002%20-%20%E3%83%8A%E3%82%A4%E3%83%88%E3%82%AF%E3%83%AB%E3%83%BC%E3%82%B8%E3%83%B3%E3%82%B0.mp3</location> 
22.
			<title>Fishmans - Aloha Polydor - 02 - _________</title> 
23.
			<creator>Fishmans</creator> 
24.
			<album>Aloha Polydor</album> 
25.
			<tracknum>1/10</tracknum> 
26.
			<length>0m 00s</length> 
27.
			<annotation>Fishmans - Aloha Polydor - 02 - ?????????</annotation> 
28.
			<info>http://www.google.com/search?hl=en&q=Fishmans+-+Aloha+Polydor+-+02+-+?????????</info> 
29.
		</track> 
30.
	</trackList> 
31.
 
32.
</playlist>
      man beachte, dass beim zweiten track die sonderzeichen, die aus den id3 tags ausgelesen wurden, verstümmelt, die aus dem dateinamen und -pfad ausgelesenen sonderzeichen jedoch korrekt dargestellt werden.

also dann, hier kommt das script. viel spaß damit.

viele grüße
jutzin


01.
// JavaScript Document 
02.
// ID3_XSPF_Playlister.js 
03.
/****************************************************************** 
04.
 * :: AUTHOR ::     based on vbs by charlie craig (http://www.iol.ie/~craigcharlie/blog/2006/04/xspf-mp3-playlister_06.html), 
05.
 *                  which was based on php by la_boost (http://www.interclasse.com/scripts/ Mp3Playlister_singleList.php), 
06.
 *                  char conversion by richard ishida (http://rishida.net/scripts/uniview/conversionfunctions.js).   
07.
 *                   
08.
 * :: HOWTO ::      installation: get the MP3Tag.dll from http://www.iol.ie/~craigcharlie/blog/ 
09.
 *                  and follow instructions to register the dll. 
10.
 *                  start the script from shell by typing 
11.
 *                        cscript ID3_XSPF_Playlister.js --usage 
12.
 *                  or by doubleclicking on the script file for 
13.
 *                  instructions on usage       
14.
15.
 * :: DATE ::       06-22-2009 
16.
 *   
17.
 * :: VERSION ::    0.2 
18.
 *   
19.
 * :: TODO ::    1) better checking of args 
20.
 *               2) there should be a switch to only write the list 
21.
 *                  to screen, not to fs. (:: DONE::) 
22.
 *               3) maybe a user definable regex feature that guesses 
23.
 *                  title info from file path for files that do not 
24.
 *                  have readable id3 tags 
25.
 *               4) instead of the binary silentoverwrite(true/false) a 
26.
 *                  dialogue controlled overwrite(yes/no/don't bother 
27.
 *                  me anymore) 
28.
 *               5) the MP3Tag.dll unfortunately seems to mix up hex and 
29.
 *                  utf-8, so that e.g. "?ô?" in the artist tag comes 
30.
 *                  out as ",ôn" in the playlist. i initially did the 
31.
 *                  translation iot include richard ishidas encoding 
32.
 *                  conversion functions (which would have been a real 
33.
 *                  hassle to implement in vbs, at least to me), to 
34.
 *                  re-translate the misspelled characters. turns out 
35.
 *                  this is not possible due to information loss by 
36.
 *                  cutting off parts od the hex code points. bummer. 
37.
 *                  at least it replaces the more common chars up to 
38.
 *                  7 bit correctly.   
39.
 *                   
40.
 *                  if anybody finds a dll or other solution that can 
41.
 *                  handle this encoding issue, please drop me a line 
42.
 *                  at goetz.freytag_ät_gmail.com   
43.
44.
 * :: BUGS ::       probably. please tell me if you find one.        
45.
 *  
46.
 ******************************************************************/ 
47.
  
48.
/********************** 
49.
 *     
50.
 * :: begin script :: 
51.
52.
 **********************/ 
53.
              
54.
var id3              = new ActiveXObject("MP3Tag.clsMP3"); 
55.
var fso              = new ActiveXObject("Scripting.FileSystemObject"); 
56.
var WshShell         = WScript.CreateObject("WScript.Shell"); 
57.
var sAppName         = "ID3 XPSF Playlister"; 
58.
var fScript          = fso.GetFile(WScript.ScriptFullName); 
59.
var outputDir        = fScript.parentFolder.Path; 
60.
 
61.
// switches (default args) 
62.
var sPlaylistName    = "playlist";                                                 // playlist file name 
63.
var sPlaylistExt     = "xspf";                                                     // playlist file extension 
64.
var sPlaylistTitle   = "";                                                         // change this if you want to give your playlist a certain title. when "", the name of the folder that gets playlisted, will be the playlist title 
65.
var sExtToGetArr     = new Array("mp3","wma","flac","ogg","m4a","mpc","ape");      // file extensions to include in playlist 
66.
var sExclDirsArr     = new Array("iTunes","System Volume Information","RECYCLER"); // directories wich contain one of the following strings are excluded from scanning 
67.
var serverString     = "";                                                         // this string will be put at the beginning of the <location> tag 
68.
var rootDir          = "";                                                         // root directory for absolute pathnames in <location> tag. only active when -p a="rootDir" is set, so that absPaths == true. 
69.
var delim            = ":";                                                        // change this if you prefer another character to be the standard delimiter (something like "param 1,param 2,param 3" instead of "param 1:param 2:param 3") 
70.
var pattern          = "\\s*" + delim + "\\s*";                                    // the pattern for the regular expression that is used to distinguish option argument list items (deletes whitespaces left and right of the delimiter, as it is.) 
71.
var regex            = new RegExp(pattern, 'g');                                   // the instance of the regular expression itself 
72.
var verbose          = false;                                                      // verbose. false unless user switches with -v or --verbose 
73.
var showMessages     = true;                                                       // show messages (includes messages that show up even before the verbose switch is read). put this on false if you want absolutely no messages. 
74.
var writeAnnotation  = true;                                                       // if this is set on true, each track gets its filename (without extension) written in the <annotation> tag. nice for jw-player playlists 
75.
var writeInfo        = true;                                                       // if this is set on true, each track gets a suiting (?) google search link written in the <info> tag. 
76.
var absPaths         = false;                                                      // if set on true, the paths in the <location> tag are absolute instead of relative to the playlist's location 
77.
var silentoverwrite  = false;                                                      // if set to true, exisiting playlists will be overwritten without asking 
78.
var simulate         = false;                                                      // if this option is set, the playlist gets written to stdout instead of to file system 
79.
var badchar          = "_";                                                        // unreadable characters (anything with a value > 0xFF, that's hiragana, cyrillic, greece etc.) will be replaced wit this char 
80.
 
81.
// globals 
82.
var id3Readables     = new Array("mp3");    // array of file extensions whose id3 tags are readable by our chosen dll. change this if you use a dll that can also read id3 tags of other file types. 
83.
var arrFolders       = new Array();         // array for ouput of recursive function. must be global because it needs to be static. 
84.
 
85.
// errorcodes  
86.
var ErrNoErrCode     = -1; 
87.
var ErrAllGood       =  0; 
88.
var ErrHelpMsgCall   =  1; 
89.
var ErrNoArg         =  2; 
90.
var ErrWrongArg      =  3; 
91.
var ErrPathNotExist  =  4; 
92.
var ErrIO            =  5; 
93.
var ErrOverwrite     =  6; 
94.
var ErrExclDir       =  7; 
95.
 
96.
// helpmessage  
97.
var usage = "" 
98.
            + " ID3_XSPF_Playlister\n" 
99.
            + "\n" 
100.
            + " originally written in vbs by Charlie Craig,\n" 
101.
            + " translated to js and rebored by vincent.\n\n" 
102.
            + "\n    usage:\n\n" 
103.
            + "  cscript ID3_XSPF_Playlister [options] pathToScan\n\n" 
104.
            + "  where pathToScan is the path with the files that will be included in the playlist.\n\n"     
105.
            + "\n    options:\n\n" 
106.
            + "  -h, --help         \t  displays this message.\n\n" 
107.
            + "  -u, --usage        \t  displays this message.\n\n"                        
108.
            + "  -n    plName       \t  where plName will be the name of the created playlist file.\n" 
109.
            + "                     \t  Default is \"" + sPlaylistName + "\".\n\n" 
110.
            + "  -x    plExtension  \t  where plExtension will be the extension of the created playlist file.\n" 
111.
            + "                     \t  Default is \"" + sPlaylistExt + "\".\n\n" 
112.
            + "  -t    plTitle      \t  where plTitle is the title of the resulting playlist. Default is \n" 
113.
            + "                     \t  the playlist\'s parent folder\'s name.\n\n"             
114.
            + "  -e    extStr       \t  where extStr is a string of file extension to be considered.\n" 
115.
            + "                     \t  The format of the string is \"String 1:String 2: ... :String n\".\n" 
116.
            + "                     \t  Default is \"" + sExtToGetArr + "\".\n\n" 
117.
            + "  --xcl excludeStr   \t  where excludeStr is a string that will be checked against \n" 
118.
            + "                     \t  pathToScan. If pathToScan contains excludeStr, the according \n" 
119.
            + "                     \t  subdirectory will not be scanned. The format of the string is\n" 
120.
            + "                     \t  \"String 1:String 2: ... :String n\".\n" 
121.
            + "                     \t  Default is \"" + sExclDirsArr + "\".\n\n" 
122.
            + "  --overwrite        \t  if this flag is set, old playlists will be overwritten without asking.\n\n" 
123.
            + "  -a                 \t  Write an <annotation> tag for each track. Default is the filename\n" 
124.
            + "                     \t  without the extension.\n\n" 
125.
            + "  -i                 \t  Write an <info> tag for each track. Default is a google search term\n" 
126.
            + "                     \t  for the filename.\n\n" 
127.
            + "  -p    r,a=rootDir  \t  where a switches to absolute and r to relative (to the playlist's location)\n" 
128.
            + "                     \t  paths in the <location> tag. Default is r. When switched to a, the root\n" 
129.
            + "                     \t  directory rootDir must be defined and locations will be relative to rootDir.\n\n" 
130.
            + "  -s    serverString \t  where serverString is a string that will be put in the beginning \n" 
131.
            + "                     \t  of each <location> tag of the playlist. Default is \"\".\n\n" 
132.
            + "  --simulate         \t  writes the playlist to the screen instead of the file system.\n\n" 
133.
            + "  -m, --showmsg      \t  shows messages.\n\n" 
134.
            + "  -v, --verbose      \t  shows a lot of messages. Includes -m, --showmsg.\n\n" 
135.
            + "\n  ... or in the explorer just drag and drop the directory you want to be playlisted on the script file.\n\n"; 
136.
 
137.
 
138.
var objArgs = WScript.Arguments; 
139.
 
140.
// there is at least one argument 
141.
if (objArgs.length > 0) 
142.
143.
    // the last argument should be the path 
144.
    pathToScan = objArgs(objArgs.length-1); 
145.
146.
// there is no argument 
147.
else 
148.
{     
149.
    if (showMessages) 
150.
    {    
151.
        alert(usage); 
152.
153.
    if (objArgs.length == 0) 
154.
155.
        if (verbose) alert("Exiting with error code " + ErrNoArg + "."); 
156.
        exit(ErrNoArg); 
157.
158.
    else 
159.
    {         
160.
        if (verbose) alert("Exiting with error code " + ErrHelpMsgCall + "."); 
161.
        exit(ErrHelpMsgCall); 
162.
    }     
163.
164.
 
165.
var arg = ""; 
166.
 
167.
// walk through the arguments and get parameters 
168.
for (i = 0; i < objArgs.length; i++) 
169.
170.
    arg = objArgs(i); 
171.
    switch(arg) 
172.
173.
        case "-h" || "--help" || "-u" || "--usage": 
174.
175.
            alert(usage); 
176.
            if (verbose) alert("Exiting with error code " + ErrHelpMsgCall + "."); 
177.
            exit(ErrHelpMsgCall); 
178.
            break; 
179.
180.
        case "-v" || "--verbose": 
181.
182.
            verbose        = true; 
183.
            showMessages   = true; 
184.
            break;              
185.
186.
        case "-m" || "--showmsg": 
187.
188.
             showMessages  = true; 
189.
             break; 
190.
191.
        case "-n": 
192.
193.
            sPlaylistName  = objArgs(i+1); 
194.
            break; 
195.
196.
        case "-x": 
197.
198.
            sPlaylistExt   = objArgs(i+1); 
199.
            break; 
200.
201.
        case "-t": 
202.
203.
            sPlaylistTitle = objArgs(i+1); 
204.
            break; 
205.
206.
        case "-e": 
207.
208.
            sExtToGetArr   = null; 
209.
            sExtToGetArr   = objArgs(i+1); 
210.
            var pattern    = "\\s*,\\s*"; 
211.
            sExtToGetArr   = sExtToGetArr.replace(regex, delim); 
212.
            sExtToGetArr   = sExtToGetArr.split(regex);  
213.
            break; 
214.
215.
        case "--xcl": 
216.
217.
            sExclDirsArr   = null; 
218.
            sExclDirsArr   = objArgs(i+1); 
219.
            sExclDirsArr   = sExclDirsArr.replace(regex, delim); 
220.
            sExclDirsArr   = sExclDirsArr.split(delim); 
221.
            break; 
222.
223.
        case "--overwrite": 
224.
225.
            silentoverwrite = true; 
226.
227.
        case "-a": 
228.
229.
             writeAnnotation = true; 
230.
             // :: TODO :: get an argument that holds a user defined <annotation> 
231.
             break; 
232.
233.
        case "-i": 
234.
235.
             writeInfo     = true; 
236.
             // :: TODO :: get an argument that holds a user defined <info> 
237.
             break; 
238.
239.
        case "-p": 
240.
241.
            absPaths       = objArgs(i+1); 
242.
            if (absPaths   == "r") 
243.
244.
                absPaths   = false; 
245.
                break; 
246.
247.
            else if (absPaths.substring(0,2) == "a=") 
248.
249.
                var rootDir  = absPaths; 
250.
                absPaths     = true; 
251.
                rootDir      = rootDir.substring(2, rootDir.length);  
252.
                break; 
253.
254.
            else 
255.
            {                 
256.
                if (showMessages) alert("The argument for -p must either be r or a=\"rootDir\"."); 
257.
                if (verbose) alert("Exiting with error code " + ErrWrongArg + "."); 
258.
                exit(ErrWrongArg); 
259.
                break;  
260.
261.
262.
        case "-s": 
263.
264.
            serverString   = objArgs(i+1); 
265.
            break; 
266.
267.
        case "--simulate": 
268.
269.
            simulate       = true; 
270.
271.
        default: 
272.
273.
            // probably an argument of an option 
274.
275.
276.
277.
 
278.
// check, if our pathToScan exists 
279.
if (! fso.FolderExists(pathToScan)) 
280.
{     
281.
    if (showMessages) alert("It seems that the path to scan does not exist."); 
282.
    if (verbose) alert("Exiting with error code " + ErrPathNotExist + "."); 
283.
    exit(ErrPathNotExist); 
284.
285.
 
286.
// get the absolute path of pathToScan 
287.
pathToScan = fso.getAbsolutePathName(pathToScan); 
288.
 
289.
// get the playlist's name (default: the lowest level of the AbsolutePathToScan) 
290.
if (sPlaylistTitle == "") 
291.
292.
    sPlaylistTitle = pathToScan; 
293.
    sPlaylistTitle = sPlaylistTitle.substring(sPlaylistTitle.lastIndexOf("\\")+1, sPlaylistTitle.length);       
294.
295.
 
296.
// input summary 
297.
if (verbose) 
298.
299.
                             str = "\n ****  Input ****\n\n"; 
300.
                             str = str + "path to scan                        \t: " + pathToScan + "\n"; 
301.
                             str = str + "playlist name                       \t: " + sPlaylistName + "\n"; 
302.
                             str = str + "playlist extension                  \t: " + sPlaylistExt + "\n"; 
303.
                             str = str + "playlist title                      \t: " + sPlaylistTitle + "\n"; 
304.
                             str = str + "considered extensions               \t: " + sExtToGetArr + "\n"; 
305.
                             str = str + "excluded directories                \t: " + sExclDirsArr + "\n"; 
306.
                             str = str + "absolute paths                      \t: " + absPaths + "\n"; 
307.
    if (absPaths)            str = str + "root directory for absolute paths   \t: " + rootDir + "\n"; 
308.
    if (serverString != "")  str = str + "server string                       \t: " + serverString + "\n";     
309.
                             str = str + "delimiting character                \t: " + delim + "\n"; 
310.
    if (delim != ":")        str = str + "regexp for splitting argument lists \t: " + regex + "\n"; 
311.
                             str = str + "\n\n **** Process ****\n"; 
312.
    alert(str); 
313.
314.
 
315.
// check if playlist already exists 
316.
playlistFile = pathToScan + "\\" + sPlaylistName + "." + sPlaylistExt; 
317.
if (fso.fileExists(playlistFile)) 
318.
319.
    if(silentoverwrite) 
320.
321.
        // if not in simulation mode: delete the existing file and go ahead 
322.
        if (! simulate) fso.deleteFile(playlistFile); 
323.
324.
    else 
325.
    {         
326.
        if (showMessages) alert("The playlist file \"" + pathToScan + "\\" + sPlaylistName + "." + sPlaylistExt + "\" already exists.\nNo playlist has been written."); 
327.
        if (verbose) alert("Exiting with error code " + ErrOverwrite + "."); 
328.
        exit(ErrOverwrite); 
329.
330.
331.
 
332.
// check, if pathToScan contains one of sExclDirsArr 
333.
for (i = 0; i < sExclDirsArr.length; i++) 
334.
335.
    str   = sExclDirsArr[i]; 
336.
    regex = new RegExp(str, 'i'); 
337.
    if (regex.test(pathToScan)) 
338.
    {         
339.
        if (showMessages) alert("The directory \"" + pathToScan + "\" has been excluded from playlisting. (exclusion string \"" + str + "\")."); 
340.
        if (verbose) alert ("Exiting with error code " + ErrExclDir + "."); 
341.
        exit(ErrExclDir); 
342.
343.
344.
 
345.
// perform the scan  
346.
var playlist = scan(pathToScan, sPlaylistName, sPlaylistExt, sPlaylistTitle, sExtToGetArr, serverString); 
347.
 
348.
// write the playlist to stdout 
349.
if (simulate) 
350.
351.
    WScript.echo("\n\n" + playlist + "\n\n"); 
352.
353.
 
354.
// write the playlist do disk 
355.
else 
356.
357.
    if (! fso.fileExists(playlistFile)) 
358.
359.
        try 
360.
361.
            var txtStream           = new ActiveXObject("ADODB.Stream"); 
362.
            var streamType          = 2;             // 1 := binary, 2:= text 
363.
            var charSet             = "utf-8";       // utf-8 
364.
            var saveCreateOverWrite = 2;             // 1 := create if not exists, 2 := overwrite. we choose overwrite because we allready checke through fso if file already exists 
365.
             
366.
            txtStream.Type          = streamType; 
367.
            txtStream.Charset       = charSet; 
368.
       
369.
            txtStream.open() 
370.
            txtStream.writeText(playlist); 
371.
            txtStream.saveToFile(playlistFile, saveCreateOverWrite); 
372.
            txtStream.close(); 
373.
            txtStream = null; 
374.
                         
375.
            if (showMessages) alert("A playlist has been written to \"" + playlistFile + "\"."); 
376.
            if (verbose) alert("Exiting with error code " + ErrAllGood + " (meaning there have been no errors)."); 
377.
            exit(ErrAllGood); 
378.
379.
        catch (exc_io) 
380.
        {             
381.
            if (showMessages) alert("There has been an exception writing the playlist."); 
382.
            if (verbose) alert("The exception is: " + exc_io); 
383.
            if (verbose) alert("Exiting with error code " + ErrIO + "."); 
384.
            exit(ErrIO); 
385.
386.
387.
    else 
388.
389.
        if (silentoverwrite) 
390.
391.
            // if not in simulation mode: delete the existing file and go ahead 
392.
            if (! simulate) fso.deleteFile(playlistFile); 
393.
394.
        else 
395.
396.
            if (showMessages) alert("The playlist file \"" + pathToScan + "\\" + sPlaylistName + "." + sPlaylistExt + "\" already exists.\nNo playlist has been written."); 
397.
            exit(ErrOverwrite); 
398.
399.
400.
401.
// clean up 
402.
fso = null; 
403.
 
404.
 
405.
/********************** 
406.
 *     
407.
 * :: begin functions :: 
408.
409.
 **********************/ 
410.
  
411.
// the scanning function 
412.
function scan(pathToScan, sPlaylistName, sPlaylistExt, sPlaylistTitle, sExtToGetArr, serverString) 
413.
414.
    var i, j;                                     
415.
    var strPlaylist;                               // the playlist as a string that will be returned 
416.
    var ext;                                       // the file extension we are looking for 
417.
    var fileEnum;                                  // enumerator of all the files in the respective folder (or subfolder) 
418.
    var itm;                                       // the respective item of the enumerator 
419.
    var fold          = fso.Getfolder(pathToScan); // the search folder (top) 
420.
        arrFolders.push(fold);                     // first add the pathToScan folder 
421.
        arrFolders    = getSubfolders(fold);       // then the subfolders (getSubfodlers(folder) returns an array of all the subfolders of the pathToScan. arrFolders needs to be static!) 
422.
    var arrFiles      = new Array();               // an array that will contain all the files we will put into the playlist 
423.
    var aktFile;                                   // the respective file 
424.
    var aktFileName;                               // the respective file's name 
425.
    var aktFilePath;                               // the respective file's path, relatiove or absolute, depending pon how the user set the switch 
426.
    var strFolderList = "";                        // a string containing the respective subfolder's part of the playlist 
427.
     
428.
    var id3Title, id3Artist, id3Album, id3Track, id3Year, id3Genre, id3Comment; 
429.
    var xspfLocation, xspfAnnotation, xspfInfo; 
430.
     
431.
    // open the tags 
432.
    strPlaylist = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" 
433.
                + "<playlist version=\"1\" xmlns=\"http:\/\/xspf.org\/ns\/0\/\">\n" 
434.
                + "\n"; 
435.
    if (sPlaylistTitle) strPlaylist = strPlaylist 
436.
                                    + "\t<title>" + sPlaylistTitle + "<\/title>\n\n" 
437.
                                    + "\t<trackList>\n"; 
438.
     
439.
    // loop through all the folders and subfolders 
440.
    for (i = 0; i < arrFolders.length; i++) 
441.
442.
        fold = arrFolders[i]; 
443.
        fileEnum = new Enumerator(fold.Files); 
444.
         
445.
        // then loop through all the files of each folder and subfolder	 
446.
        for (; !fileEnum.atEnd(); fileEnum.moveNext()) 
447.
448.
            itm = fileEnum.item().name; 
449.
            // check if the extension is in strExtToGetArr 
450.
              
451.
            for (j = 0; j < sExtToGetArr.length; j++) 
452.
453.
                // if we are looking for files with this extension, write the file into the file-array 
454.
                if (itm.indexOf(sExtToGetArr[j]) != - 1) 
455.
456.
                   arrFiles.push(fileEnum.item()); 
457.
458.
459.
460.
461.
    // let's give a little status message 
462.
    if (verbose) alert(arrFiles.length + " files will be playlisted.\n"); 
463.
     
464.
    // we now have an array of files with the extensions we were looking for, sorted by path. 
465.
    // loop through that array and collect each track's information 
466.
    for (i = 0; i < arrFiles.length; i++) 
467.
468.
        aktFile     = arrFiles[i]; 
469.
        if (verbose) alert((i+1) + "/" + (arrFiles.length) + ":   \t adding \"" + aktFile + "\" to the playlist.") 
470.
         
471.
        id3Title    = ""; 
472.
        id3Artist   = ""; 
473.
        id3Album    = ""; 
474.
        id3Track    = ""; 
475.
        id3Year     = ""; 
476.
        id3Duration = ""; 
477.
        id3Genre    = ""; 
478.
        id3Comment  = ""; 
479.
         
480.
        // do we have a file whose id3 tags we can read? 
481.
        for (j = 0; j < id3Readables.length; j++) 
482.
483.
            if (getFileExtension(aktFile) == id3Readables[j]) 
484.
485.
               // it seems we do, so let's get the id3 tags 
486.
               // first the title; we want to catch exceptions here, especially for the readMP3 part 
487.
               try 
488.
489.
    		      id3.readMP3(aktFile.Path); 
490.
 			      id3Title = id3.Songname; 
491.
492.
		       // catch unread title tags 
493.
               catch(exc_titleNotReadable) 
494.
495.
                  if (verbose) alert("\t\t The id3 tags of \"" + aktFile + "\" could not be received. Taking information from filename."); 
496.
                  id3Title = aktFile.Name.replace("." + getFileExtension(aktFile), ""); 
497.
498.
               // catch empty <title> tags 
499.
               if (id3Title == "") 
500.
501.
                   if (verbose) alert("\t\t The id3 tags of \"" + aktFile + "\" could not be received. Taking information from filename."); 
502.
                   id3Title = aktFile.Name.replace("." + getFileExtension(aktFile), ""); 
503.
504.
                
505.
               // then the rest, also encoding conversion of id3 tags iot remove false utf-8 interpretations at chars beyond asc(255) 
506.
                
507.
               /*  :: TODO :: reverse the utf-8 char misinterpretation, branch 1 (leaves as is) 
508.
               id3Title      = id3Title; 
509.
               id3Artist     = id3.Artist; 
510.
               id3Album      = id3.Album; 
511.
               id3Track      = id3.Track; 
512.
               id3Year       = id3.Year; 
513.
               id3Duration   = id3.Duration; 
514.
               id3Genre      = id3.Genre; 
515.
               id3Comment    = id3.Comment; 
516.
               //  :: END TODO ::    */ 
517.
                    
518.
               //*  :: TODO :: reverse the utf-8 char misinterpretation, branch 2 (beautifies chars lower than 0xFF) 
519.
               id3Title      = repairUTF8(id3Title); 
520.
               id3Artist     = repairUTF8(id3.Artist); 
521.
               id3Album      = repairUTF8(id3.Album); 
522.
               id3Track      = repairUTF8(id3.Track); 
523.
               id3Year       = repairUTF8(id3.Year); 
524.
               id3Duration   = repairUTF8(id3.Duration); 
525.
               id3Genre      = repairUTF8(id3.Genre); 
526.
               id3Comment    = repairUTF8(id3.Comment); 
527.
               //  :: END TODO ::    */ 
528.
                
529.
               // no need to go through the rest of id3Readables[] 
530.
               break; 
531.
532.
            else 
533.
534.
                // no readable id3 tags, so we have to get our information from the filename or so. 
535.
                 
536.
                /*   :: TODO :: there is much room for improvement here, e.g. one could get the information through 
537.
                 *   a user defined regex from the filepath or so... one for normal albums, one for 
538.
                 *   compilations is what i'd do.  
539.
                 */ 
540.
                
541.
                id3Title =  aktFile.Name.replace("." + getFileExtension(aktFile), "");               
542.
543.
544.
         
545.
        // get the <location> tag 
546.
        // user wants absolute paths in location tag 
547.
        if (absPaths) 
548.
        {  
549.
            pattern     = rootDir.replace(/\\/g, "\\\\");                           // the pattern that portrays the rootDir 
550.
            regex       = new RegExp(pattern, 'i');                                 // the regex, caseinsensitive, only first occurence 
551.
            aktFilePath = aktFile.Path;                                             // the aktFile absolute path 
552.
            aktFilePath = aktFilePath.replace(regex, "");                           // replace first occurence of rootDir in path with "" 
553.
554.
        // user wants relative paths in location tag 
555.
        else 
556.
557.
            aktFilePath  = aktFile.Path.replace(pathToScan, "");                    // the aktFile relative path 
558.
        }        
559.
        xspfLocation = serverString + aktFilePath.replace(/\\/g, "\/");             // make unix-like path and add server string 
560.
        xspfLocation = encodeURL(xspfLocation);                                     // encode to url %-encoding                         
561.
        aktFileName    = aktFile.Name.replace("." + getFileExtension(aktFile), ""); // the aktFile name (without extension) 
562.
        // get, if the respective switch is on, the <annotation> tag 
563.
        if (writeAnnotation) xspfAnnotation = aktFileName; 
564.
        // and perhaps also the <info> tag 
565.
        if (writeInfo) xspfInfo = "http://www.google.com/search?hl=en&q=" + (aktFileName.replace(/\s/g, "+")).replace(/&/g,"&amp;"); 
566.
             
567.
        // we have now collected the respective track's information. 
568.
        // let's make a nicely formatted string of it 
569.
        strFolderList = "\n\t\t<track>\n"; 
570.
                               strFolderList = strFolderList + "\t\t\t<location>"   + xspfLocation   + "<\/location>\n"; 
571.
                               strFolderList = strFolderList + "\t\t\t<title>"      + id3Title       + "<\/title>\n"; 
572.
        if (id3Artist   != "") strFolderList = strFolderList + "\t\t\t<creator>"    + id3Artist      + "<\/creator>\n"; 
573.
        if (id3Album    != "") strFolderList = strFolderList + "\t\t\t<album>"      + id3Album       + "<\/album>\n"; 
574.
        if (id3Track    != "") strFolderList = strFolderList + "\t\t\t<tracknum>"   + id3Track       + "<\/tracknum>\n"; 
575.
        if (id3Duration != "") strFolderList = strFolderList + "\t\t\t<length>"     + id3Duration    + "<\/length>\n"; 
576.
        if (id3Year     != "") strFolderList = strFolderList + "\t\t\t<year>"       + id3Year        + "<\/year>\n"; 
577.
        if (id3Comment  != "") strFolderList = strFolderList + "\t\t\t<comments>"   + id3Comment     + "<\/comments>\n"; 
578.
        if (writeAnnotation)   strFolderList = strFolderList + "\t\t\t<annotation>" + xspfAnnotation + "<\/annotation>\n";  
579.
        if (writeInfo)         strFolderList = strFolderList + "\t\t\t<info>"       + xspfInfo       + "<\/info>\n"; 
580.
        strFolderList = strFolderList + "\t\t<\/track>\n"; 
581.
         
582.
        // add this folder's list to the playlist 
583.
        strPlaylist = strPlaylist + strFolderList 
584.
585.
     
586.
    // close the tags 
587.
    strPlaylist = strPlaylist + "\n\t\<\/trackList>\n" 
588.
                              + "\n<\/playlist>"; 
589.
    return strPlaylist;  				 	 	 
590.
591.
 
592.
// recursive subfolder search. Needs static var "arrFolders". 
593.
function getSubfolders(dir) 
594.
{      
595.
    //arrFolders.push(fso.getFolder(dir)); 
596.
    var foldEnum = new Enumerator(fso.getFolder(dir).SubFolders); 
597.
    for (; !foldEnum.atEnd(); foldEnum.moveNext()) 
598.
599.
        getSubfolders(foldEnum.item()) // recursive 
600.
        if (foldEnum.item() != null) arrFolders.push(foldEnum.item());    
601.
602.
    if (foldEnum.item() != null) arrFolders.push(foldEnum.item()); 
603.
    return arrFolders; 
604.
605.
 
606.
// helper functions 
607.
// makro for WScript.echo 
608.
function alert(string) 
609.
610.
    //time = new Date(); 
611.
    //time = time.getHours() + ":" + time.getMinutes() + ":" + time.getSeconds() + "," + time.getMilliseconds(); 
612.
    //WScript.Echo(time + " ... " + string); 
613.
    WScript.Echo(string); 
614.
615.
 
616.
// makro for WScript.quit() 
617.
function exit(errcode) 
618.
619.
   if(isNaN(errcode)) 
620.
621.
       errcode = ErrNoErrCode; // exit without valid errorcode; 
622.
623.
   WScript.quit(errcode); 
624.
625.
 
626.
// get fileextension 
627.
function getFileExtension(filename) 
628.
629.
    return (/[.]/.exec(filename)) ? /[^.]+$/.exec(filename) : undefined; 
630.
631.
 
632.
// encode url 
633.
function encodeURL(urlstr) 
634.
635.
    urlstr = getCPfromChar(urlstr);                    // convert to code points 
636.
    urlstr = urlstr.substring(0, urlstr.length-1);     // cut off last space 
637.
    urlstr = convertCP2pEsc(urlstr);                   // convert to url escape coding 
638.
    urlstr = urlstr.replace(/%2F/g, "\/");             // re-replace code %2f with "/" 
639.
    urlstr = urlstr.replace(/%3A/, ":");               // re-replace the first occurence of %3a with ":" 
640.
    return urlstr;   
641.
642.
 
643.
function encodeXML(xmlstr) 
644.
645.
    xmlstr = getCPfromChar(xmlstr);                    // convert to code points 
646.
    xmlstr = xmlstr.substring(0, xmlstr.length-1);     // cut off last space 
647.
    xmlstr = convertCP2XML(xmlstr);                    // convert to xml compliant 
648.
    return xmlstr; 
649.
650.
 
651.
//*  :: TODO :: reversion of utf-8 misinterpretation 
652.
// re-encode utf-8 special chars 
653.
function repairUTF8(utfstr) 
654.
655.
    utfstr = getCPfromChar(utfstr); 
656.
    utfstr = utfstr.substring(0, utfstr.length-1); 
657.
    utfstr = convertUTF82CP(utfstr); 
658.
    utfstr = convertCP2Char(utfstr); 
659.
    utfstr = utfstr.replace(/_NAN/g , badchar); 
660.
    return utfstr;   
661.
662.
//  :: END TODO ::    */  
663.
 
664.
/********************** 
665.
 *     
666.
 * :: begin encoding conversion fucntions by richard ishida :: 
667.
668.
 **********************/ 
669.
  
670.
var escapeMap = ''; 
671.
var CPstring  = ''; 
672.
 
673.
var hexNum    = {0:1, 1:1, 2:1, 3:1, 4:1, 5:1, 6:1, 7:1, 8:1, 9:1,  
674.
				 A:1, B:1, C:1, D:1, E:1, F:1,  
675.
				 a:1, b:1, c:1, d:1, e:1, f:1}; 
676.
var jEscape   = {0:1, b:1, t:1, n:1, v:1, f:1, r:1}; 
677.
var decDigit  = {0:1, 1:1, 2:1, 3:1, 4:1, 5:1, 6:1, 7:1, 8:1, 9:1}; 
678.
 
679.
 
680.
function dec2hex(textString) 
681.
682.
    return (textString+0).toString(16).toUpperCase(); 
683.
684.
 
685.
function  dec2hex2(textString) 
686.
687.
    var hexequiv = new Array ("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"); 
688.
    return hexequiv[(textString >> 4) & 0xF] + hexequiv[textString & 0xF]; 
689.
690.
 
691.
function  dec2hex4(textString) 
692.
693.
    var hexequiv = new Array ("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"); 
694.
    return hexequiv[(textString >> 12) & 0xF] + hexequiv[(textString >> 8) & 0xF] + hexequiv[(textString >> 4) & 0xF] + hexequiv[textString & 0xF]; 
695.
696.
 
697.
// converts a character or sequence of characters to hex codepoint values 
698.
// copes with supplementary characters 
699.
// returned values include a space between each hex value and at the end 
700.
function getCPfromChar(textString) 
701.
702.
	var codepoint = ""; 
703.
	var haut = 0; 
704.
	var n = 0;  
705.
	for (var i = 0; i < textString.length; i++) 
706.
707.
		var b = textString.charCodeAt(i);  
708.
		if (b < 0 || b > 0xFFFF) 
709.
710.
			//codepoint += 'Error: Initial byte out of range in getCPfromChar: '+dec2hex(b); 
711.
			codepoint += '_' + dec2hex(b); 
712.
713.
		if (haut != 0) 
714.
715.
            // we should be dealing with the second part of a supplementary character 
716.
			if (0xDC00 <= b && b <= 0xDFFF) 
717.
718.
				codepoint += '_' + dec2hex(0x10000 + ((haut - 0xD800) << 10) + (b - 0xDC00)) + ' '; 
719.
				haut = 0; 
720.
				continue; 
721.
722.
			else 
723.
724.
				//codepoint += 'Error: Second byte out of range in getCPfromChar: '+dec2hex(haut); 
725.
				codepoint += dec2hex(haut); 
726.
				haut = 0; 
727.
728.
729.
		if (0xD800 <= b && b <= 0xDBFF) 
730.
731.
            //b is the first part of a supplementary character 
732.
			haut = b; 
733.
734.
		else 
735.
        {    
736.
            // this is not a supplementary character 
737.
            // codepoint += dec2hex(b); 
738.
			codepoint += b.toString(16).toUpperCase()+' '; 
739.
740.
	}  
741.
    //alert('>'+codepoint+'<'); 
742.
	return codepoint; 
743.
744.
 
745.
// converts hex codepoint values to url %-escape values 	 
746.
function convertCP2pEsc(textString) 
747.
748.
	// textstring: sequence of Unicode code points, derived from convertChar2CP() 
749.
	var outputString = ""; 
750.
	// remove initial spaces 
751.
	textString = textString.replace(/^\s+/, ''); 
752.
	if (textString.length == 0) {return "";} 
753.
	// make all multiple spaces a single space 
754.
	textString = textString.replace(/\s+/g, ' '); 
755.
	var listArray = textString.split(' '); 
756.
	// process each codepoint 
757.
	for (var i = 0; i < listArray.length; i++) 
758.
759.
		var n = parseInt(listArray[i], 16); 
760.
		//if (i > 0) {outputString += ' ';} 
761.
		if (n == 0x20) {outputString += '%20';} 
762.
		else if (n >= 0x41 && n <= 0x5A) {outputString += String.fromCharCode(n);}                           // alpha 
763.
		else if (n >= 0x61 && n <= 0x7A) {outputString += String.fromCharCode(n);}                           // alpha 
764.
		else if (n >= 0x30 && n <= 0x39) {outputString += String.fromCharCode(n);}                           // digits 
765.
		else if (n == 0x2D || n == 0x2E || n == 0x5F || n == 0x7E) {outputString += String.fromCharCode(n);} // - . _ ~ 
766.
		else if (n <= 0x7F) {outputString += '%'+dec2hex2(n);} 
767.
		else if (n <= 0x7FF) {outputString += '%'+dec2hex2(0xC0 | ((n>>6) & 0x1F)) + '%' + dec2hex2(0x80 | (n & 0x3F));}  
768.
		else if (n <= 0xFFFF) {outputString += '%'+dec2hex2(0xE0 | ((n>>12) & 0x0F)) + '%' + dec2hex2(0x80 | ((n>>6) & 0x3F)) + '%' + dec2hex2(0x80 | (n & 0x3F));}  
769.
		else if (n <= 0x10FFFF) {outputString += '%'+dec2hex2(0xF0 | ((n>>18) & 0x07)) + '%' + dec2hex2(0x80 | ((n>>12) & 0x3F)) + '%' + dec2hex2(0x80 | ((n>>6) & 0x3F)) + '%' + dec2hex2(0x80 | (n & 0x3F));}  
770.
		//else {outputString += '!Error ' + dec2hex(n) +'!';} 
771.
		else {outputString += '_' + dec2hex(n) +'!';} 
772.
773.
	return(outputString); 
774.
775.
 
776.
// converts hex codepoints to characters 
777.
function convertCP2Char (textString) 
778.
779.
    var outputString = ''; 
780.
    textString = textString.replace(/^\s+/, ''); 
781.
    if (textString.length == 0) {return "";} 
782.
  	textString = textString.replace(/\s+/g, ' '); 
783.
    var listArray = textString.split(' '); 
784.
    for (var i = 0; i < listArray.length; i++) 
785.
786.
        var n = parseInt(listArray[i], 16); 
787.
        if (n <= 0xFFFF) 
788.
789.
            outputString += String.fromCharCode(n); 
790.
791.
        else if (n <= 0x10FFFF) 
792.
793.
            n -= 0x10000 
794.
            outputString += String.fromCharCode(0xD800 | (n >> 10)) + String.fromCharCode(0xDC00 | (n & 0x3FF)); 
795.
796.
        else 
797.
798.
            //outputString += 'convertCP2Char error: Code point out of range: '+dec2hex(n); 
799.
            outputString += '_' + dec2hex(n); 
800.
801.
802.
    return(outputString); 
803.
804.
 
805.
//converts hex-codepoints to xml compliant chars 
806.
function convertCP2XML (textString) 
807.
808.
	var outputString = ''; 
809.
	textString = textString.replace(/^\s+/, ''); 
810.
	if (textString.length == 0) {return "";} 
811.
	 
812.
	textString = textString.replace(/\s+/g, ' '); 
813.
	var listArray = textString.split(' '); 
814.
	for (var i = 0; i < listArray.length; i++) 
815.
816.
		var n = parseInt(listArray[i], 16); 
817.
		if (n <= 0xFFFF) 
818.
819.
			switch (n) 
820.
821.
				case 34: outputString += '&quot;'; break; 
822.
				case 38: outputString += '&amp;'; break; 
823.
				case 60: outputString += '&lt;'; break; 
824.
				case 62: outputString += '&gt;'; break; 
825.
				default: outputString += String.fromCharCode(n); 
826.
827.
		}  
828.
		else if (n <= 0x10FFFF) 
829.
830.
			n -= 0x10000; 
831.
			outputString += String.fromCharCode(0xD800 | (n >> 10)) + String.fromCharCode(0xDC00 | (n & 0x3FF)); 
832.
		}  
833.
		else 
834.
835.
			//outputString += 'convertCP2Char error: Code point out of range: '+dec2hex(n); 
836.
			outputString += '_' + dec2hex(n); 
837.
838.
839.
	return(outputString); 
840.
841.
 
842.
// converts hex codepoints to utf-8 double digit codepoints 
843.
function convertCP2UTF8(textString) 
844.
845.
    var outputString = ""; 
846.
    textString = textString.replace(/^\s+/, ''); 
847.
    if (textString.length == 0) { return ""; } 
848.
    textString = textString.replace(/\s+/g, ' '); 
849.
    var listArray = textString.split(' '); 
850.
    for (var i = 0; i < listArray.length; i++) 
851.
852.
        var n = parseInt(listArray[i], 16); 
853.
        if (i > 0) {outputString += ' ';} 
854.
        if (n <= 0x7F) 
855.
856.
            outputString += dec2hex2(n); 
857.
858.
        else if (n <= 0x7FF) 
859.
860.
            outputString += dec2hex2(0xC0 | ((n>>6) & 0x1F)) + ' ' + dec2hex2(0x80 | (n & 0x3F)); 
861.
862.
        else if (n <= 0xFFFF) 
863.
864.
            outputString += dec2hex2(0xE0 | ((n>>12) & 0x0F)) + ' ' + dec2hex2(0x80 | ((n>>6) & 0x3F)) + ' ' + dec2hex2(0x80 | (n & 0x3F)); 
865.
866.
        else if (n <= 0x10FFFF) 
867.
868.
            outputString += dec2hex2(0xF0 | ((n>>18) & 0x07)) + ' ' + dec2hex2(0x80 | ((n>>12) & 0x3F)) + ' ' + dec2hex2(0x80 | ((n>>6) & 0x3F)) + ' ' + dec2hex2(0x80 | (n & 0x3F)); 
869.
870.
        else 
871.
872.
            //outputString += '!erreur ' + dec2hex(n) +'!'; 
873.
            outputString += '_' + dec2hex(n) +'!'; 
874.
875.
876.
    return(outputString); 
877.
878.
 
879.
// converts UTF-8 values to hex codepoints 
880.
function convertUTF82CP (textString) 
881.
882.
    var outputString = ""; 
883.
    CPstring = ''; 
884.
    var compte = 0; 
885.
    var n = 0; 
886.
    textString = textString.replace(/^\s+/, ''); 
887.
    if (textString.length == 0) {return "";} 
888.
    textString = textString.replace(/\s+/g, ' '); 
889.
    var listArray = textString.split(' '); 
890.
     
891.
    for (var i = 0; i < listArray.length; i++) 
892.
893.
        var b = parseInt(listArray[i], 16);  // alert('b:'+dec2hex(b)); 
894.
        switch (compte) 
895.
896.
            case 0: 
897.
898.
                if (0 <= b && b <= 0x7F) 
899.
                {  
900.
                    // 0xxxxxxx 
901.
                    outputString += dec2hex(b) + ' '; 
902.
903.
                else if (0xC0 <= b && b <= 0xDF) 
904.
905.
                    // 110xxxxx 
906.
                    compte = 1; 
907.
                    n = b & 0x1F; 
908.
909.
                else if (0xE0 <= b && b <= 0xEF) 
910.
911.
                    // 1110xxxx 
912.
                    compte = 2; 
913.
                    n = b & 0xF; 
914.
915.
                else if (0xF0 <= b && b <= 0xF7) 
916.
917.
                    // 11110xxx 
918.
                    compte = 3; 
919.
                    n = b & 0x7; 
920.
921.
                else 
922.
923.
                    //outputString += '!erreur ' + dec2hex(b) + '! '; 
924.
                    outputString += '_' + dec2hex(b) + '! '; 
925.
926.
                break; 
927.
928.
                 
929.
            case 1: 
930.
931.
                if (b < 0x80 || b > 0xBF) 
932.
933.
                    //outputString += '!erreur ' + dec2hex(b) + '! '; 
934.
                    outputString += '_' + dec2hex(b) + '! '; 
935.
936.
                compte--; 
937.
                outputString += dec2hex((n << 6) | (b-0x80)) + ' '; 
938.
                n = 0; 
939.
                break; 
940.
941.
             
942.
            case 2: case 3: 
943.
944.
                if (b < 0x80 || b > 0xBF) 
945.
946.
                    //outputString += '!erreur ' + dec2hex(b) + '! '; 
947.
                    outputString += '_' + dec2hex(b) + '! '; 
948.
949.
                n = (n << 6) | (b-0x80); 
950.
                compte--; 
951.
                break; 
952.
953.
954.
955.
    CPstring = outputString.replace(/ $/, ''); 
956.
    return CPstring; 
957.
958.
 
959.
/********************** 
960.
 *     
961.
 * :: end encoding conversion functions by richard ishida :: 
962.
963.
 **********************/ 
964.
 
965.
/********************** 
966.
 *     
967.
 * :: end functions :: 
968.
969.
 **********************/ 
970.
  
971.
/********************** 
972.
 *     
973.
 * :: end script :: 
974.
975.
 **********************/
Neuester Wissensbeitrag
CPU, RAM, Mainboards

Angetestet: PC Engines APU 3a2 im Rack-Gehäuse

(1)

Erfahrungsbericht von ashnod zum Thema CPU, RAM, Mainboards ...

Heiß diskutierte Inhalte
Switche und Hubs
Trunk für 2xCisco Switch. Wo liegt der Fehler? (14)

Frage von JayyyH zum Thema Switche und Hubs ...

DSL, VDSL
DSL-Signal bewerten (13)

Frage von SarekHL zum Thema DSL, VDSL ...

Windows Server
Mailserver auf Windows Server 2012 (9)

Frage von StefanT81 zum Thema Windows Server ...