toBala KM King


Requires Javascript.
Linux 網路服務 - 學習筆記本 - V1.2 (2011/06/22) 由土芭樂知識聯盟設計與維護
<!--{{{-->
<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml'/>
<!--}}}-->
Background: #fff
Foreground: #000
PrimaryPale: #8cf
PrimaryLight: #18f
PrimaryMid: #04b
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
/*{{{*/
body {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}

a {color:[[ColorPalette::PrimaryMid]];}
a:hover {background-color:[[ColorPalette::PrimaryMid]]; color:[[ColorPalette::Background]];}
a img {border:0;}

h1,h2,h3,h4,h5,h6 {color:[[ColorPalette::SecondaryDark]]; background:transparent;}
h1 {border-bottom:2px solid [[ColorPalette::TertiaryLight]];}
h2,h3 {border-bottom:1px solid [[ColorPalette::TertiaryLight]];}

.button {color:[[ColorPalette::PrimaryDark]]; border:1px solid [[ColorPalette::Background]];}
.button:hover {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::SecondaryLight]]; border-color:[[ColorPalette::SecondaryMid]];}
.button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::SecondaryDark]];}

.header {background:[[ColorPalette::PrimaryMid]];}
.headerShadow {color:[[ColorPalette::Foreground]];}
.headerShadow a {font-weight:normal; color:[[ColorPalette::Foreground]];}
.headerForeground {color:[[ColorPalette::Background]];}
.headerForeground a {font-weight:normal; color:[[ColorPalette::PrimaryPale]];}

.tabSelected{color:[[ColorPalette::PrimaryDark]];
	background:[[ColorPalette::TertiaryPale]];
	border-left:1px solid [[ColorPalette::TertiaryLight]];
	border-top:1px solid [[ColorPalette::TertiaryLight]];
	border-right:1px solid [[ColorPalette::TertiaryLight]];
}
.tabUnselected {color:[[ColorPalette::Background]]; background:[[ColorPalette::TertiaryMid]];}
.tabContents {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::TertiaryPale]]; border:1px solid [[ColorPalette::TertiaryLight]];}
.tabContents .button {border:0;}

#sidebar {}
#sidebarOptions input {border:1px solid [[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel {background:[[ColorPalette::PrimaryPale]];}
#sidebarOptions .sliderPanel a {border:none;color:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:hover {color:[[ColorPalette::Background]]; background:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:active {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::Background]];}

.wizard {background:[[ColorPalette::PrimaryPale]]; border:1px solid [[ColorPalette::PrimaryMid]];}
.wizard h1 {color:[[ColorPalette::PrimaryDark]]; border:none;}
.wizard h2 {color:[[ColorPalette::Foreground]]; border:none;}
.wizardStep {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];
	border:1px solid [[ColorPalette::PrimaryMid]];}
.wizardStep.wizardStepDone {background:[[ColorPalette::TertiaryLight]];}
.wizardFooter {background:[[ColorPalette::PrimaryPale]];}
.wizardFooter .status {background:[[ColorPalette::PrimaryDark]]; color:[[ColorPalette::Background]];}
.wizard .button {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryLight]]; border: 1px solid;
	border-color:[[ColorPalette::SecondaryPale]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryPale]];}
.wizard .button:hover {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Background]];}
.wizard .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::Foreground]]; border: 1px solid;
	border-color:[[ColorPalette::PrimaryDark]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryDark]];}

#messageArea {border:1px solid [[ColorPalette::SecondaryMid]]; background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]];}
#messageArea .button {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::SecondaryPale]]; border:none;}

.popupTiddler {background:[[ColorPalette::TertiaryPale]]; border:2px solid [[ColorPalette::TertiaryMid]];}

.popup {background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]]; border-left:1px solid [[ColorPalette::TertiaryMid]]; border-top:1px solid [[ColorPalette::TertiaryMid]]; border-right:2px solid [[ColorPalette::TertiaryDark]]; border-bottom:2px solid [[ColorPalette::TertiaryDark]];}
.popup hr {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::PrimaryDark]]; border-bottom:1px;}
.popup li.disabled {color:[[ColorPalette::TertiaryMid]];}
.popup li a, .popup li a:visited {color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:active {background:[[ColorPalette::SecondaryPale]]; color:[[ColorPalette::Foreground]]; border: none;}
.popupHighlight {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
.listBreak div {border-bottom:1px solid [[ColorPalette::TertiaryDark]];}

.tiddler .defaultCommand {font-weight:bold;}

.shadow .title {color:[[ColorPalette::TertiaryDark]];}

.title {color:[[ColorPalette::SecondaryDark]];}
.subtitle {color:[[ColorPalette::TertiaryDark]];}

.toolbar {color:[[ColorPalette::PrimaryMid]];}
.toolbar a {color:[[ColorPalette::TertiaryLight]];}
.selected .toolbar a {color:[[ColorPalette::TertiaryMid]];}
.selected .toolbar a:hover {color:[[ColorPalette::Foreground]];}

.tagging, .tagged {border:1px solid [[ColorPalette::TertiaryPale]]; background-color:[[ColorPalette::TertiaryPale]];}
.selected .tagging, .selected .tagged {background-color:[[ColorPalette::TertiaryLight]]; border:1px solid [[ColorPalette::TertiaryMid]];}
.tagging .listTitle, .tagged .listTitle {color:[[ColorPalette::PrimaryDark]];}
.tagging .button, .tagged .button {border:none;}

.footer {color:[[ColorPalette::TertiaryLight]];}
.selected .footer {color:[[ColorPalette::TertiaryMid]];}

.sparkline {background:[[ColorPalette::PrimaryPale]]; border:0;}
.sparktick {background:[[ColorPalette::PrimaryDark]];}

.error, .errorButton {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Error]];}
.warning {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryPale]];}
.lowlight {background:[[ColorPalette::TertiaryLight]];}

.zoomer {background:none; color:[[ColorPalette::TertiaryMid]]; border:3px solid [[ColorPalette::TertiaryMid]];}

.imageLink, #displayArea .imageLink {background:transparent;}

.annotation {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border:2px solid [[ColorPalette::SecondaryMid]];}

.viewer .listTitle {list-style-type:none; margin-left:-2em;}
.viewer .button {border:1px solid [[ColorPalette::SecondaryMid]];}
.viewer blockquote {border-left:3px solid [[ColorPalette::TertiaryDark]];}

.viewer table, table.twtable {border:2px solid [[ColorPalette::TertiaryDark]];}
.viewer th, .viewer thead td, .twtable th, .twtable thead td {background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::Background]];}
.viewer td, .viewer tr, .twtable td, .twtable tr {border:1px solid [[ColorPalette::TertiaryDark]];}

.viewer pre {border:1px solid [[ColorPalette::SecondaryLight]]; background:[[ColorPalette::SecondaryPale]];}
.viewer code {color:[[ColorPalette::SecondaryDark]];}
.viewer hr {border:0; border-top:dashed 1px [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::TertiaryDark]];}

.highlight, .marked {background:[[ColorPalette::SecondaryLight]];}

.editor input {border:1px solid [[ColorPalette::PrimaryMid]];}
.editor textarea {border:1px solid [[ColorPalette::PrimaryMid]]; width:100%;}
.editorFooter {color:[[ColorPalette::TertiaryMid]];}

#backstageArea {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::TertiaryMid]];}
#backstageArea a {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstageArea a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; }
#backstageArea a.backstageSelTab {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
#backstageButton a {background:none; color:[[ColorPalette::Background]]; border:none;}
#backstageButton a:hover {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstagePanel {background:[[ColorPalette::Background]]; border-color: [[ColorPalette::Background]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]];}
.backstagePanelFooter .button {border:none; color:[[ColorPalette::Background]];}
.backstagePanelFooter .button:hover {color:[[ColorPalette::Foreground]];}
#backstageCloak {background:[[ColorPalette::Foreground]]; opacity:0.6; filter:'alpha(opacity:60)';}
/*}}}*/
/*{{{*/
* html .tiddler {height:1%;}

body {font-size:.75em; font-family:arial,helvetica; margin:0; padding:0;}

h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
h4,h5,h6 {margin-top:1em;}
h1 {font-size:1.35em;}
h2 {font-size:1.25em;}
h3 {font-size:1.1em;}
h4 {font-size:1em;}
h5 {font-size:.9em;}

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

ol {list-style-type:decimal;}
ol ol {list-style-type:lower-alpha;}
ol ol ol {list-style-type:lower-roman;}
ol ol ol ol {list-style-type:decimal;}
ol ol ol ol ol {list-style-type:lower-alpha;}
ol ol ol ol ol ol {list-style-type:lower-roman;}
ol ol ol ol ol ol ol {list-style-type:decimal;}

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

.indent {margin-left:3em;}
.outdent {margin-left:3em; text-indent:-3em;}
code.escaped {white-space:nowrap;}

.tiddlyLinkExisting {font-weight:bold;}
.tiddlyLinkNonExisting {font-style:italic;}

/* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
a.tiddlyLinkNonExisting.shadow {font-weight:bold;}

#mainMenu .tiddlyLinkExisting,
	#mainMenu .tiddlyLinkNonExisting,
	#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
#sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}

.header {position:relative;}
.header a:hover {background:transparent;}
.headerShadow {position:relative; padding:4.5em 0em 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0em 1em 1em; left:0px; top:0px;}

.siteTitle {font-size:3em;}
.siteSubtitle {font-size:1.2em;}

#mainMenu {position:absolute; left:0; width:10em; text-align:right; line-height:1.6em; padding:1.5em 0.5em 0.5em 0.5em; font-size:1.1em;}

#sidebar {position:absolute; right:3px; width:16em; font-size:.9em;}
#sidebarOptions {padding-top:0.3em;}
#sidebarOptions a {margin:0em 0.2em; padding:0.2em 0.3em; display:block;}
#sidebarOptions input {margin:0.4em 0.5em;}
#sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
#sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
#sidebarOptions .sliderPanel input {margin:0 0 .3em 0;}
#sidebarTabs .tabContents {width:15em; overflow:hidden;}

.wizard {padding:0.1em 1em 0em 2em;}
.wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizardStep {padding:1em 1em 1em 1em;}
.wizard .button {margin:0.5em 0em 0em 0em; font-size:1.2em;}
.wizardFooter {padding:0.8em 0.4em 0.8em 0em;}
.wizardFooter .status {padding:0em 0.4em 0em 0.4em; margin-left:1em;}
.wizard .button {padding:0.1em 0.2em 0.1em 0.2em;}

#messageArea {position:fixed; top:2em; right:0em; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
.messageToolbar {display:block; text-align:right; padding:0.2em 0.2em 0.2em 0.2em;}
#messageArea a {text-decoration:underline;}

.tiddlerPopupButton {padding:0.2em 0.2em 0.2em 0.2em;}
.popupTiddler {position: absolute; z-index:300; padding:1em 1em 1em 1em; margin:0;}

.popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
.popup .popupMessage {padding:0.4em;}
.popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0em;}
.popup li.disabled {padding:0.4em;}
.popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
.listBreak {font-size:1px; line-height:1px;}
.listBreak div {margin:2px 0;}

.tabset {padding:1em 0em 0em 0.5em;}
.tab {margin:0em 0em 0em 0.25em; padding:2px;}
.tabContents {padding:0.5em;}
.tabContents ul, .tabContents ol {margin:0; padding:0;}
.txtMainTab .tabContents li {list-style:none;}
.tabContents li.listLink { margin-left:.75em;}

#contentWrapper {display:block;}
#splashScreen {display:none;}

#displayArea {margin:1em 17em 0em 14em;}

.toolbar {text-align:right; font-size:.9em;}

.tiddler {padding:1em 1em 0em 1em;}

.missing .viewer,.missing .title {font-style:italic;}

.title {font-size:1.6em; font-weight:bold;}

.missing .subtitle {display:none;}
.subtitle {font-size:1.1em;}

.tiddler .button {padding:0.2em 0.4em;}

.tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
.isTag .tagging {display:block;}
.tagged {margin:0.5em; float:right;}
.tagging, .tagged {font-size:0.9em; padding:0.25em;}
.tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
.tagClear {clear:both;}

.footer {font-size:.9em;}
.footer li {display:inline;}

.annotation {padding:0.5em; margin:0.5em;}

* html .viewer pre {width:99%; padding:0 0 1em 0;}
.viewer {line-height:1.4em; padding-top:0.5em;}
.viewer .button {margin:0em 0.25em; padding:0em 0.25em;}
.viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
.viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}

.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
table.listView th, table.listView td, table.listView tr {padding:0px 3px 0px 3px;}

.viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
.viewer code {font-size:1.2em; line-height:1.4em;}

.editor {font-size:1.1em;}
.editor input, .editor textarea {display:block; width:100%; font:inherit;}
.editorFooter {padding:0.25em 0em; font-size:.9em;}
.editorFooter .button {padding-top:0px; padding-bottom:0px;}

.fieldsetFix {border:0; padding:0; margin:1px 0px 1px 0px;}

.sparkline {line-height:1em;}
.sparktick {outline:0;}

.zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
.zoomer div {padding:1em;}

* html #backstage {width:99%;}
* html #backstageArea {width:99%;}
#backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0em; right:0em;}
#backstageButton a {padding:0.1em 0.4em 0.1em 0.4em; margin:0.1em 0.1em 0.1em 0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; margin:0em 3em 0em 3em; padding:1em 1em 1em 1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding:0.2em 0.4em 0.2em 0.4em;}
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
/***
StyleSheet for use when a translation requires any css style changes.
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which need larger font sizes.
***/
/*{{{*/
body {font-size:0.8em;}
#sidebarOptions {font-size:1.05em;}
#sidebarOptions a {font-style:normal;}
#sidebarOptions .sliderPanel {font-size:0.95em;}
.subtitle {font-size:0.8em;}
.viewer table.listView {font-size:0.95em;}
/*}}}*/
/*{{{*/
@media print {
#mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton, #backstageArea {display: none ! important;}
#displayArea {margin: 1em 1em 0em 1em;}
/* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */
noscript {display:none;}
}
/*}}}*/
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar closeTiddler closeOthers +editTiddler > fields syncing permalink references jump'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler deleteTiddler'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>
<!--}}}-->
To get started with this blank TiddlyWiki, you'll need to modify the following tiddlers:
* SiteTitle & SiteSubtitle: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* MainMenu: The menu (usually on the left)
* DefaultTiddlers: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
These InterfaceOptions for customising TiddlyWiki are saved in your browser

Your username for signing your edits. Write it as a WikiWord (eg JoeBloggs)

<<option txtUserName>>
<<option chkSaveBackups>> SaveBackups
<<option chkAutoSave>> AutoSave
<<option chkRegExpSearch>> RegExpSearch
<<option chkCaseSensitiveSearch>> CaseSensitiveSearch
<<option chkAnimate>> EnableAnimations

----
Also see AdvancedOptions
<<importTiddlers>>
Revision 3497
''參考文章''
1. ISPConfig 3 For Ubuntu 10.04
http://blog.darkhero.net/?p=412
2. Ubuntu Server Guide
https://help.ubuntu.com/12.04/serverguide/index.html

<html><img src="img/linux/mail/mailprocess.jpg" style="width:85%;height: 85%;"/></html>

<<toBalaNotes "mailpro">>
{{item1{查詢 MX 記錄}}}
{{{
# dig big200.dos mx +short
10 USMS02.big200.dos.
}}}


///%mailpro
//%/
__{{item1{筆記本設定 (設定將存於瀏覽器 Cookies 中)}}}__

請簽名 <<option txtUserName>>
<<option chkGenerateAnRssFeed>> 儲存變更時,也儲存 RSS feed

__{{item1{版面設定 (設定將存於筆記本中)}}}__
<<toBalaManager>>

__{{item1{筆記本備份 (設定將存於瀏覽器 Cookies 中)}}}__
{{op1{1. 資訊樹}}}
備份檔名 : <<option txtBalaBackupFileName>>
備份主標籤 : <<option txtBalaTreeBody>>
其它備份文章 : <<option txtBalaBackupOthers>>

<<toBalaBackup "NotepadBackup.html">>

{{op1{2. 土芭樂巨集}}}
備份檔名 : <<option txtBalaCoreBackupFileName>>
其它備份文章 : <<option txtBalaCoreBackupOthers>>

<<toBalaCoreBackup "toBalaCoreMacro.html">>

__{{item1{巨集管理}}}__

<<loadTiddlers "label:檢查更新土芭樂巨集" http://tbala.net/x/toBalaMacro.html updates quiet>>













































///%

Linux 網路服務 - 學習筆記本

V1.2 (2011/06/22) 由土芭樂知識聯盟設計與維護

<<tagsTree twcms "" 1 4 index label>>
<<tagsTree lns01 "" 1 4 index label>>
<<tagsTree lns02 "" 1 4 index label>>
<<tagsTree lns03 "" 1 4 index label>>
<<tagsTree lns04 "" 1 4 index label>>
<<tagsTree lns05 "" 1 4 index label>>
<<tagsTree lns06 "" 1 4 index label>>
<<tagsTree lns07 "" 1 4 index label>>
<<tagsTree lns08 "" 1 4 index label>>
<<tagsTree KMKConfig "" 1 4 index label>>

 [[首頁]] | [[土芭樂 3.0 - 數位新思路|http://tbala.net/]]  | [[TiddlyWiki 練功坊|http://tiddlywiki.tbala.net/]] | [[匯入文章]]  | [[匯出文章]]  |  &nbsp;&nbsp;<<toBalaRun "Java-CMD.bat" "" "命令提示視窗">>&nbsp;&nbsp;<<newTiddler label:"新增文章">>&nbsp;&nbsp;<<closeAll>>&nbsp;&nbsp;<<saveChanges>> &nbsp;&nbsp;IT 無涯,關機是岸
//%/
''參考文章''
1. Ubuntu Server Guide
https://help.ubuntu.com/12.04/serverguide/index.html

Apache 維基百科 : http://zh.wikipedia.org/zh-tw/Apache_HTTP_Server
Apache 軟體基金會 : http://www.apache.org/

Apache HTTP Server(簡稱 Apache)是  Apache 軟體基金會的一個開放源碼的網頁伺服器,可以在大多數電腦作業系統中運行,由於其跨平台和安全性被廣泛使用,是最流行的 Web 伺服器端軟體之一。它快速、可靠並且可通過簡單的 API 擴充,將 Perl/Python 等直譯器編譯到伺服器中。

''歷史''
Apache 起初由伊利諾大學香檳分校的國家超級電腦應用中心(NCSA)開發。此後,Apache Httpd 被開放原始碼團體的成員不斷的發展和加強。Apache Http 網站伺服器擁有牢靠可信的美譽,已經在全球超過半數的網站中被使用-特別是幾乎所有最熱門和瀏覽量最大的網站。比方說,維基百科網站伺服器就是使用 Apache 的。

剛開始發展時,Apache 只是 Netscape 網頁伺服器(現在是Sun ONE)之外的開放原始碼選擇之一。慢慢地,它開始在功能和速度超越其他基於 Unix 的 HTTP 伺服器。到了Apache 2.x 的時代,實際效率又比 Apache 1.x更快,2.x 比1.x 能同時服務更多的網頁連線數。

1996 年 4 月以來,Apache 一直是 Internet 上最流行的 HTTP 伺服器:1999年5月它在57%的網頁伺服器上運行,到了 2005 年 7 月這個比例上升到了 69%。在 2005 年11月最風光的時候達到接近 70% 的市佔率,不過在部份擁有大量域名的主機域名商轉換為微軟 IIS 平台後,Apache市佔率近年來呈現些微下滑。同時搜尋引擎巨擘Google自己的網頁伺服器平台 GWS 推出後(也可說是一種修改版的 Apache),再加上 nginx、Lighttpd 等輕量化網頁伺服器軟體在市場上有一些能見度,這些因素都反應在整體網頁伺服器市佔率的消長,Apache 的市佔率就隨之滑落。根據 Netcraft 在 2009 年12月的最新統計數據,Apache 的市佔率已經降為 53.67%,IIS 降為18.26%,谷歌網頁服務器 13.53%,nginx 8.75%。儘管如此,Apache 仍舊是當前網際網路市場上,市佔率最高的網頁伺服器軟體。

<<toBalaNotes "apache">>


///%apache
//%/
''參考文章''
1. 伺服器安裝與設定 - Apache HTTP Server
http://linux.nchc.org.tw/intro_to_linux/part4/apache.html

{{item1{Apache 2 安裝}}}

''$ sudo apt-get install apache2''
{{{
[sudo] password for student:
正在讀取套件清單... 完成
正在重建相依關係
正在讀取狀態資料... 完成
以下套件是被自動安裝進來的,且已不再會被用到了:
  linux-headers-2.6.32-21 linux-headers-2.6.32-22
  linux-headers-2.6.32-22-generic-pae
使用 'apt-get autoremove' 來將其移除。
下列的額外套件將被安裝:
  apache2-mpm-worker apache2-utils apache2.2-bin apache2.2-common libapr1
  libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap
建議套件:
  apache2-doc apache2-suexec apache2-suexec-custom
下列【新】套件將會被安裝:
  apache2 apache2-mpm-worker apache2-utils apache2.2-bin apache2.2-common
  libapr1 libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap
升級 0 個,新安裝 9 個,移除 0 個,有 1 個未被升級。
需要下載 3,328kB 的套件檔。
此操作完成之後,會多佔用 10.1MB 的磁碟空間。
是否繼續進行 [Y/n]?y
下載:1 http://tw.archive.ubuntu.com/ubuntu/ lucid/main libapr1 1.3.8-1build1 [116kB]
下載:2 http://tw.archive.ubuntu.com/ubuntu/ lucid/main libaprutil1 1.3.9+dfsg-3build1 [85.4kB]
下載:3 http://tw.archive.ubuntu.com/ubuntu/ lucid/main libaprutil1-dbd-sqlite3 1.3.9+dfsg-3build1 [27.1kB]
下載:4 http://tw.archive.ubuntu.com/ubuntu/ lucid/main libaprutil1-ldap 1.3.9+dfsg-3build1 [25.1kB]
下載:5 http://tw.archive.ubuntu.com/ubuntu/ lucid/main apache2.2-bin 2.2.14-5ubuntu8 [2,622kB]
下載:6 http://tw.archive.ubuntu.com/ubuntu/ lucid/main apache2-utils 2.2.14-5ubuntu8 [159kB]
下載:7 http://tw.archive.ubuntu.com/ubuntu/ lucid/main apache2.2-common 2.2.14-5ubuntu8 [290kB]
下載:8 http://tw.archive.ubuntu.com/ubuntu/ lucid/main apache2-mpm-worker 2.2.14-5ubuntu8 [2,364B]
下載:9 http://tw.archive.ubuntu.com/ubuntu/ lucid/main apache2 2.2.14-5ubuntu8 [1,482B]
取得 3,328kB 用了 2s (1,345kB/s)
選取了原先未被選取的套件 libapr1。
(正在讀取資料庫 ... 系統目前共安裝了 159384 個檔案和目錄。)
正在解開 libapr1 (從 .../libapr1_1.3.8-1build1_i386.deb)...
選取了原先未被選取的套件 libaprutil1。
正在解開 libaprutil1 (從 .../libaprutil1_1.3.9+dfsg-3build1_i386.deb)...
選取了原先未被選取的套件 libaprutil1-dbd-sqlite3。
正在解開 libaprutil1-dbd-sqlite3 (從 .../libaprutil1-dbd-sqlite3_1.3.9+dfsg-3build1_i386.deb)...
選取了原先未被選取的套件 libaprutil1-ldap。
正在解開 libaprutil1-ldap (從 .../libaprutil1-ldap_1.3.9+dfsg-3build1_i386.deb)...
選取了原先未被選取的套件 apache2.2-bin。
正在解開 apache2.2-bin (從 .../apache2.2-bin_2.2.14-5ubuntu8_i386.deb)...
選取了原先未被選取的套件 apache2-utils。
正在解開 apache2-utils (從 .../apache2-utils_2.2.14-5ubuntu8_i386.deb)...
選取了原先未被選取的套件 apache2.2-common。
正在解開 apache2.2-common (從 .../apache2.2-common_2.2.14-5ubuntu8_i386.deb)...
選取了原先未被選取的套件 apache2-mpm-worker。
正在解開 apache2-mpm-worker (從 .../apache2-mpm-worker_2.2.14-5ubuntu8_i386.deb)...
選取了原先未被選取的套件 apache2。
正在解開 apache2 (從 .../apache2_2.2.14-5ubuntu8_i386.deb)...
正在進行 man-db 的觸發程式 ...
正在進行 ufw 的觸發程式 ...
正在進行 ureadahead 的觸發程式 ...
ureadahead will be reprofiled on next reboot
正在設定 libapr1 (1.3.8-1build1) ...

正在設定 libaprutil1 (1.3.9+dfsg-3build1) ...

正在設定 libaprutil1-dbd-sqlite3 (1.3.9+dfsg-3build1) ...
正在設定 libaprutil1-ldap (1.3.9+dfsg-3build1) ...
正在設定 apache2.2-bin (2.2.14-5ubuntu8) ...
正在設定 apache2-utils (2.2.14-5ubuntu8) ...
正在設定 apache2.2-common (2.2.14-5ubuntu8) ...
Enabling site default.
Enabling module alias.
Enabling module autoindex.
Enabling module dir.
Enabling module env.
Enabling module mime.
Enabling module negotiation.
Enabling module setenvif.
Enabling module status.
Enabling module auth_basic.
Enabling module deflate.
Enabling module authz_default.
Enabling module authz_user.
Enabling module authz_groupfile.
Enabling module authn_file.
Enabling module authz_host.
Enabling module reqtimeout.

正在設定 apache2-mpm-worker (2.2.14-5ubuntu8) ...
 * Starting web server apache2                                                  
apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1 for ServerName
                                                                         [ OK ]
正在設定 apache2 (2.2.14-5ubuntu8) ...

正在進行 libc-bin 的觸發程式 ...
ldconfig deferred processing now taking place
}}}

''@@color:red;[問題]@@'' 由上述安裝資訊, Apache 2 已啟動那些 Module ?

{{item1{檢視 Apache 2 的內部設定值}}}

''$ /usr/sbin/apache2 -V''
{{{
Server version: Apache/2.2.14 (Ubuntu)
Server built:   Apr 13 2010 19:29:28
Server's Module Magic Number: 20051115:23
Server loaded:  APR 1.3.8, APR-Util 1.3.9
Compiled using: APR 1.3.8, APR-Util 1.3.9
Architecture:   32-bit
Server MPM:     Worker
  threaded:     yes (fixed thread count)
    forked:     yes (variable process count)
Server compiled with....
 -D APACHE_MPM_DIR="server/mpm/worker"
 -D APR_HAS_SENDFILE
 -D APR_HAS_MMAP
 -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
 -D APR_USE_SYSVSEM_SERIALIZE
 -D APR_USE_PTHREAD_SERIALIZE
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D APR_HAS_OTHER_CHILD
 -D AP_HAVE_RELIABLE_PIPED_LOGS
 -D DYNAMIC_MODULE_LIMIT=128
 -D HTTPD_ROOT=""
 -D SUEXEC_BIN="/usr/lib/apache2/suexec"
 -D DEFAULT_PIDLOG="/var/run/apache2.pid"
 -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
 -D DEFAULT_ERRORLOG="logs/error_log"
 -D AP_TYPES_CONFIG_FILE="/etc/apache2/mime.types"
 -D SERVER_CONFIG_FILE="/etc/apache2/apache2.conf"
}}}

@@color:red;''[註]'' 由上面資訊中, 可以得知 Apache 2 的主要設定檔是 ''/etc/apache2/apache2.conf''@@

{{item1{停止 Apache 2}}}
{{{
$ sudo /etc/init.d/apache2 stop
 * Stopping web server apache2                                                   
... waiting                                                             [ OK ]
}}}

{{item1{啟動 Apache 2}}}
{{{
$ sudo /etc/init.d/apache2 start
 * Starting web server apache2                                           [ OK ]
}}}

{{item1{重新啟動 Apache 2}}}
{{{
$ sudo /etc/init.d/apache2 restart
}}}

{{item1{Troubleshooting Apache}}}

在啟動或重新啟動, 如出現以下錯誤訊息 : 
{{{
$ sudo /etc/init.d/apache2 restart
[sudo] password for student:
 * Restarting web server apache2                                                
apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1 for ServerName
 ... waiting apache2: Could not reliably determine the server's fully qualified domain name, 
using 127.0.1.1 for ServerName                                   [ OK ]
}}}
then use a text editor such as ''nano'' to create a new file
{{{
$ sudo nano /etc/apache2/conf.d/fqdn
}}}
then add
{{{
ServerName localhost
}}}
to the file and save. This can all be done in a single command with the following:
{{{
echo "ServerName localhost" | sudo tee /etc/apache2/conf.d/fqdn
}}}

''再一次啟動 Apache 2''
{{{
$ sudo /etc/init.d/apache2 restart
 * Restarting web server apache2                                                
 ... waiting                                                             [ OK ]
}}}

<<toBalaNotes "apache2">>


///%apache2
//%/
{{op1{1. 下載  jdk-6u14-linux-i586.bin}}}
下載網址 : http://java.sun.com/javase/downloads/index.jsp

{{op1{2. 設定 jdk-6u14-linux-i586.bin 具有執行屬性}}}
{{{
tobala@tobalaking:~$ ls -l
總計 86188
-rw-r--r-- 1 tobala tobala  6379115 2009-06-18 01:18 apache-tomcat-6.0.20.zip
drwxr-xr-x 2 tobala tobala     4096 2009-06-16 15:57 Desktop
-rw-r--r-- 1 tobala tobala 81771117 2009-06-18 01:45 jdk-6u14-linux-i586.bin
tobala@tobalaking:~$ sudo chmod +x jdk-6u14-linux-i586.bin
[sudo] password for tobala:
}}}

{{op1{3. 以 root (sudo) 身份, 至 /opt 目錄中執行 jdk-6u14-linux-i586.bin}}}
{{{
tobala@tobalaking:~$ cd /opt
tobala@tobalaking:/opt$ sudo /home/tobala/jdk-6u14-linux-i586.bin
Sun Microsystems, Inc. Binary Code License Agreement

for the JAVA SE DEVELOPMENT KIT (JDK), VERSION 6

SUN MICROSYSTEMS, INC. ("SUN") IS WILLING TO LICENSE THE
SOFTWARE IDENTIFIED BELOW TO YOU ONLY UPON THE CONDITION
THAT YOU ACCEPT ALL OF THE TERMS CONTAINED IN THIS BINARY
CODE LICENSE AGREEMENT AND SUPPLEMENTAL LICENSE TERMS
(COLLECTIVELY "AGREEMENT"). PLEASE READ THE AGREEMENT
CAREFULLY. BY DOWNLOADING OR INSTALLING THIS SOFTWARE, YOU
ACCEPT THE TERMS OF THE AGREEMENT. INDICATE ACCEPTANCE BY
SELECTING THE "ACCEPT" BUTTON AT THE BOTTOM OF THE
AGREEMENT. IF YOU ARE NOT WILLING TO BE BOUND BY ALL THE
TERMS, SELECT THE "DECLINE" BUTTON AT THE BOTTOM OF THE
AGREEMENT AND THE DOWNLOAD OR INSTALL PROCESS WILL NOT
CONTINUE.

1. DEFINITIONS. "Software" means the identified above in
binary form, any other machine readable materials
(including, but not limited to, libraries, source files,
header files, and data files), any updates or error
corrections provided by Sun, and any user manuals,
programming guides and other documentation provided to you

Do you agree to the above license terms? [yes or no]
yes
}}}

{{op1{4. 以 root (sudo) 身份, 編輯 /etc/profile 檔案 (設定 JAVA_HOME 及 PATH 環境變數)}}}
{{{
tobala@tobalaking:/opt$ sudo nano /etc/profile

# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).

if [ -d /etc/profile.d ]; then
  for i in /etc/profile.d/*.sh; do
    if [ -r $i ]; then
      . $i
    fi
  done
  unset i
fi

if [ "$PS1" ]; then
  if [ "$BASH" ]; then
    PS1='\u@\h:\w\$ '
    if [ -f /etc/bash.bashrc ]; then
        . /etc/bash.bashrc
    fi
  else
    if [ "`id -u`" -eq 0 ]; then
      PS1='# '
    else
      PS1='$ '
    fi
  fi
fi

umask 022

export JAVA_HOME=/opt/jdk1.6.0_14
export PATH=$PATH:$JAVA_HOME/bin

}}}

{{op1{5. 登出然後再登入}}}
{{{
tobala@tobalaking:/opt$ logout
}}}

{{op1{6. 測試是否安裝成功}}}
{{{
tobala@tobalaking:~$ java -version
java version "1.6.0_14"
Java(TM) SE Runtime Environment (build 1.6.0_14-b08)
Java HotSpot(TM) Client VM (build 14.0-b16, mixed mode, sharing)
tobala@tobalaking:~$
}}}

<<toBalaNotes "jdk1.6">>

{{item1{SUN JDK1.6 套件安裝}}} 
從 Ubuntu 10.04 版開始, Sun Java 開發套件已移到 Partner repository, 安裝說明如下 : 

For Ubuntu 10.04 LTS, the ''sun-java6-jdk'' packages have been dropped from the Multiverse section of the Ubuntu archive. It is recommended that you use ''openjdk-6'' instead.

If you can not switch from the proprietary Sun JDK/JRE to OpenJDK, you can install ''sun-java6-jdk'' packages from the Canonical Partner Repository. You can configure your system to use this repository via command-line:
{{{
$ add-apt-repository "deb http://archive.canonical.com/ lucid partner"
}}}
執行完上述命令後, 在 /etc/apt/source.list 檔案的最後, 會自動加入下式 : 
{{{
$ deb http://archive.canonical.com/ lucid partner
}}}
重新更新套件資料庫
{{{
$ sudo apt-get update
}}}
安裝 SUN JDK6
{{{
$ apt-get install sun-java6-jdk
}}}
檢視 JDK 版本代號
{{{
$ java -version
}}}

///%jdk1.6
//%/
{{item1{啟動 MySQL}}}

''$ sudo /opt/lampp/lampp startmysql''
{{{
[sudo] password for tobala:
XAMPP: Starting MySQL...
}}}

{{item1{登入 MySQL, 檢視 mysql 帳號資訊}}}

''$ cd /opt/lampp/bin''

''$ sudo ./mysql''
{{{
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.1.37 Source distribution

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> use mysql;
Database changed
mysql> select host,user,password from user;
+-----------+------+----------+
| host      | user | password |
+-----------+------+----------+
| localhost | root |          |
| linux     | root |          |
| localhost |      |          |
| linux     |      |          |
| localhost | pma  |          |
+-----------+------+----------+
5 rows in set (0.00 sec)

mysql> \q
Bye
}}}
''參考文章''
1. Ubuntu Server Guide
https://help.ubuntu.com/12.04/serverguide/index.html

The purpose of ''IP Masquerading'' is to allow machines with private, non-routable IP addresses on your network to access the Internet through the machine doing the masquerading. Traffic from your private network destined for the Internet must be manipulated for replies to be routable back to the machine that made the request. To do this, the kernel must modify the source IP address of each packet so that replies will be routed back to it, rather than to the private IP address that made the request, which is impossible over the Internet. Linux uses Connection Tracking (conntrack) to keep track of which connections belong to which machines and reroute each return packet accordingly. Traffic leaving your private network is thus "masqueraded" as having originated from your Ubuntu gateway machine. This process is referred to in Microsoft documentation as Internet Connection Sharing.

This can be accomplished with a single iptables rule, which may differ slightly based on your network configuration:
{{{
    sudo iptables -t nat -A POSTROUTING -s 192.168.0.0/16 -o ppp0 -j MASQUERADE
}}}
The above command assumes that your private address space is 192.168.0.0/16 and that your Internet-facing device is ppp0. The syntax is broken down as follows:
{{{
* -t nat -- the rule is to go into the nat table
* -A POSTROUTING -- the rule is to be appended (-A) to the POSTROUTING chain
* -s 192.168.0.0/16 -- the rule applies to traffic originating from the specified address space
* -o ppp0 -- the rule applies to traffic scheduled to be routed through the specified network device
* -j MASQUERADE -- traffic matching this rule is to "jump" (-j) to the MASQUERADE target to be manipulated as described above
}}}
Each chain in the filter table (the default table, and where most or all packet filtering occurs) has a default policy of ACCEPT, but if you are creating a firewall in addition to a gateway device, you may have set the policies to DROP or REJECT, in which case your masqueraded traffic needs to be allowed through the FORWARD chain for the above rule to work:
{{{
    sudo iptables -A FORWARD -s 192.168.0.0/16 -o ppp0 -j ACCEPT
    sudo iptables -A FORWARD -d 192.168.0.0/16 -m state --state ESTABLISHED,RELATED -i ppp0 -j ACCEPT
}}}
The above commands will allow all connections from your local network to the Internet and all traffic related to those connections to return to the machine that initiated them. 

{{{
# sudo su

# echo  "1"  >/proc/sys/net/ipv4/ip_forward

# iptable  -t nat  -A POSTROUTING  -s 192.168.200.0/24  -o  eth1 -j MASQUERADE

}}}

<<toBalaNotes "nat">>



///%nat
//%/
''參考文章''
1. Linux Frequently Asked Questions
https://www.apachefriends.org/faq_linux.html

XAMPP 官方網站 : http://www.apachefriends.org/zh_tw/xampp-linux.html

{{item1{下載 XAMPP}}}

''$ wget http://downloads.sourceforge.net/project/xampp/XAMPP%20Linux/1.8.3/xampp-linux-x64-1.8.3-4-installer.run''
{{{
--2014-07-06 11:40:23--  http://downloads.sourceforge.net/project/xampp/XAMPP%20Linux/1.8.3/xampp-linux-x64-1.8.3-4-installer.run
正在查找主機 downloads.sourceforge.net (downloads.sourceforge.net)... 216.34.181.59
正在連接 downloads.sourceforge.net (downloads.sourceforge.net)|216.34.181.59|:80... 連上了。
已送出 HTTP 要求,正在等候回應... 302 Found
位置:http://jaist.dl.sourceforge.net/project/xampp/XAMPP%20Linux/1.8.3/xampp-linux-x64-1.8.3-4-installer.run [跟隨至新的 URL]
--2014-07-06 11:40:24--  http://jaist.dl.sourceforge.net/project/xampp/XAMPP%20Linux/1.8.3/xampp-linux-x64-1.8.3-4-installer.run
正在查找主機 jaist.dl.sourceforge.net (jaist.dl.sourceforge.net)... 150.65.7.130, 2001:df0:2ed:feed::feed
正在連接 jaist.dl.sourceforge.net (jaist.dl.sourceforge.net)|150.65.7.130|:80... 連上了。
已送出 HTTP 要求,正在等候回應... 200 OK
長度: 128613473 (123M) [application/x-makeself]
Saving to: `xampp-linux-x64-1.8.3-4-installer.run'

100%[======================================>] 128,613,473  353K/s   in 6m 3s   

2014-07-06 11:46:27 (346 KB/s) - `xampp-linux-x64-1.8.3-4-installer.run' saved [128613473/128613473]
}}}

{{item1{安裝 XAMPP}}}
''1. 設定安裝程式的執行權限''
''$ chmod 755 xampp-linux-*-installer.run''

''2. 開始安裝''
''$ sudo ./xampp-linux-*-installer.run''

[img[img/xampp/xamppinst01.png]]

[img[img/xampp/xamppinst02.png]]

[img[img/xampp/xamppinst03.png]]

{{item1{啟動 XAMPP 圖形管理工具}}}
''
$ cd /opt/lampp
$ sudo ./manager-linux.run (or manager-linux-x64.run)
''
[img[img/xampp/xamppman01.png]]

[img[img/xampp/xamppman01.png]]

使用 lampp 命令啟動所有服務, 命令如下 :
''$ sudo /opt/lampp/lampp start''
{{{
Starting XAMPP for Linux 1.8.3-4...
XAMPP: Starting Apache...ok.
XAMPP: Starting MySQL...ok.
XAMPP: Starting ProFTPD...ok.
}}}

使用 lampp 命令停止所有服務, 命令如下 :
''$ sudo /opt/lampp/lampp stop''
{{{
Stopping XAMPP for Linux 1.8.3-4...
XAMPP: Stopping Apache...ok.
XAMPP: Stopping MySQL...ok.
XAMPP: Stopping ProFTPD...ok.
}}}

{{op1{自動啟動 XAMPP}}}
在 Ubuntu Server 系統中編輯 /etc/rc.local, 編輯內容如下 :
{{{
                                 :
/opt/lampp/lampp start
exit
}}}

{{item1{XAMPP 安全設定}}}
執行以下安全設定時, 如已啟動 XAMPP 平台, 此時會一併設定 MySQL 的帳號

''$ sudo /opt/lampp/lampp security''
XAMPP: Quick security check...
XAMPP: Your XAMPP pages are NOT secured by a password.
XAMPP: Do you want to set a password? [yes] ''Enter''
XAMPP: Password: ''student''
XAMPP: Password (again): ''student''
XAMPP: Password protection active. Please use 'lampp' as user name!
XAMPP: MySQL is accessable via network.
XAMPP: Normaly that's not recommended. Do you want me to turn it off? [yes] ''yes''
XAMPP: Turned off.
XAMPP: Stopping MySQL...
XAMPP: Starting MySQL...
XAMPP: The MySQL/phpMyAdmin user pma has no password set!!!
XAMPP: Do you want to set a password? [yes] ''yes''
XAMPP: Password: ''student''
XAMPP: Password (again): ''student''
XAMPP: Setting new MySQL pma password.
XAMPP: Setting phpMyAdmin's pma password to the new one.
XAMPP: MySQL has no root passwort set!!!
XAMPP: Do you want to set a password? [yes] ''yes''
XAMPP: Write the passworde somewhere down to make sure you won't forget it!!!
XAMPP: Password: ''student''
XAMPP: Password (again): ''student''
XAMPP: Setting new MySQL root password.
XAMPP: Setting phpMyAdmin's root password to the new one.
XAMPP: The FTP password for user 'nobody' is still set to 'lampp'.
XAMPP: Do you want to change the password? [yes] ''yes''
XAMPP: Password: ''student''
XAMPP: Password (again): ''student''
XAMPP: Reload ProFTPD...
XAMPP: Done.

{{op1{連接測試}}}
1. 啟動瀏覽器, 在 URL 欄位中, 輸入 "http://xampp server ip"

2. 輸入帳號及密碼, 帳號名稱為 lampp

3. 檢視安全設定

[img[img/xampp/xamppsecurity.png]]

''[注意]'' 上圖中 MySQL, phpMyAdmin 安全並沒設定

{{item1{停止 XAMPP}}}
{{{
# /opt/lampp/lampp stop
Stopping XAMPP for Linux 1.7.3a...
XAMPP: Stopping Apache with SSL...
XAMPP: Stopping MySQL...
XAMPP: Stopping ProFTPD...
XAMPP stopped.
}}}
<<toBalaNotes "xamppsec">>


///%xamppsec
//%/
<<forEachTiddler 
 where
   'tiddler.tags.contains("toBalaMacro")'
>>
''參考文章''
1. Setting up an Ubuntu System as an Email Server
https://help.ubuntu.com/community/MailServer
2. Mail Server on Ubuntu:postfix、courier-pop、courier-imap
http://kuster.pixnet.net/blog/post/17839922
3.Outlook Express 常見的錯誤訊息
http://www.sdtv.net.tw/mailerror.htm

{{item1{安裝 postfix}}}

''$ sudo apt-get install postfix''
{{{
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following extra packages will be installed:
  ssl-cert
Suggested packages:
  procmail postfix-mysql postfix-pgsql postfix-ldap postfix-pcre sasl2-bin
  resolvconf postfix-cdb mail-reader
The following NEW packages will be installed:
  postfix ssl-cert
0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
Need to get 1,332kB of archives.
After this operation, 3,367kB of additional disk space will be used.
Do you want to continue [Y/n]? 
}}}

[img[img/linux/mail/Postfix01.png]]

[img[img/linux/mail/Postfix02.png]]

[img[img/linux/mail/Postfix03.png]]

{{item1{手動設定 Postfix 設定檔}}}
{{{
$ sudo nano /etc/postfix/main.cf 
# See /usr/share/postfix/main.cf.dist for a commented, more complete version

# Debian specific:  Specifying a file name will cause the first
# line of that file to be used as the name.  The Debian default
# is /etc/mailname.
#myorigin = it49.kvm

smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
biff = no

# appending .domain is the MUA's job.
append_dot_mydomain = no

# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h

readme_directory = no

# TLS parameters
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.

myhostname = myds.it49.kvm
mydomain = it49.kvm
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = $myhostname
mydestination = it49.kvm
relayhost = 
mynetworks = 127.0.0.0/8, 10.0.3.0/24
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
home_mailbox = Maildir/
inet_protocols = ipv4
}}}

{{item1{重新啟動 Postfix}}}
{{{
$ sudo service postfix restart
}}}

<<toBalaNotes "1">>
{{item1{telnet 寄送郵件}}}

{{op1{1. 測通 SMTP : 寄給外網}}}
{{{
# telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 it99ns.it99.sese ESMTP Postfix (Ubuntu)
helo 192.168.200.132
250 it99ns.it99.sese
mail from:admin@it99.sese
250 2.1.0 Ok
rcpt to:168@gmail.com
250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
zzzzzz

.
250 2.0.0 Ok: queued as 1C32F68355
quit
221 2.0.0 Bye
Connection closed by foreign host.
}}}

''[註]'' 2010 年測試, GMail, Yahoo 等均會收上述操作, 所寄出的郵件

{{op1{2. 寄給本機網域的使用者}}}
{{{
$ telnet localhost 25
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 US104-66-DM ESMTP Postfix (Ubuntu)
helo 172.30.66.5
250 US104-66-DM
mail from:admin@gmail.com
250 2.1.0 Ok
rcpt to:student@it66.kvm
250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
Hi Student
.
250 2.0.0 Ok: queued as A099D5934
quit
221 2.0.0 Bye
Connection closed by foreign host.
}}}

{{item1{郵件處理命令 : Heirloom Mailx}}}

''1. 安裝 heirloom-mailx 套件''
{{{
$ sudo apt-get install heirloom-mailx
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following NEW packages will be installed:
  heirloom-mailx
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 298kB of archives.
After this operation, 717kB of additional disk space will be used.
Get:1 http://tw.archive.ubuntu.com/ubuntu/ lucid/universe heirloom-mailx 12.4-1.1 [298kB]
Fetched 298kB in 0s (912kB/s)    
Selecting previously deselected package heirloom-mailx.
(Reading database ... 43562 files and directories currently installed.)
Unpacking heirloom-mailx (from .../heirloom-mailx_12.4-1.1_i386.deb) ...
Processing triggers for man-db ...
Setting up heirloom-mailx (12.4-1.1) ...
update-alternatives: error: no alternatives for mailx.
update-alternatives: using /usr/bin/heirloom-mailx to provide /usr/bin/mailx (mailx) in auto mode.
}}}

''2. 寄信''
{{{
student@US104-66-DM:~$ mailx student@it99.kvm
Subject: 第一名
zzzzzz

.

EOT
}}}

''3. 讀取信件''
{{{
$ mailx -f Maildir/
Heirloom mailx version 12.4 7/29/08.  Type ? for help.
"Maildir/": 4 messages 2 unread
 O  1 admin@gmail.com    Sun Aug 15 20:54   13/433   
>U  2 admin@gmail.com    Sun Aug 15 21:03   16/429   Hi
 U  3 student@it99.kvm   Sun Aug 15 21:15   19/600   Hi 66
 O  4 student            Sun Aug 15 21:49   21/712  第一名
? 
}}}

<<toBalaNotes "2">>
{{item1{IPv6 設定範例}}}
設定 ''/etc/postfix/main.cf''
''1.修改以下三行''
{{{
myhostname = USMS02.big200.dos

mydestination = big200.dos,USMS02.big200.dos

mynetworks = [babe::]/64
}}}
''加入以下二行''
{{{
inet_protocols = all
home_mailbox = Maildir/
}}}

''完整範例檔''
''# cat /etc/postfix/main.cf ''
{{{
                          ::
smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
biff = no

# appending .domain is the MUA's job.
append_dot_mydomain = no

# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h

readme_directory = no

# TLS parameters
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.

myhostname = USMS02.big200.dos
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = big200.dos,USMS02.big200.dos
relayhost = 
mynetworks = [babe::]/64 192.168.122.0/24
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = all
home_mailbox = maildir/
}}}

///%1
//%/

///%2
//%/
參考文章
1. SSL VPN的改變 
http://www.ithome.com.tw/itadm/article.php?c=68006
2. Using openvpn to bridge networks
http://ubuntuforums.org/showthread.php?t=752127
3. The Five Minute VPN Guide
http://tuxnetworks.blogspot.com/2011/05/howto-easiest-vpn-setup-ever.html
4. connecting and copying files with scp — ubuntu 10.04
http://ubuntu.stackexchange.com/questions/2424/connecting-and-copying-files-with-scp-ubuntu-10-04
5. Ubuntu 12.04 LTS Precise Pangolin: Networking tips and tricks (很重要)
http://www.sitepoint.com/ubuntu-12-04-lts-precise-pangolin-networking-tips-and-tricks/
6. Ubuntu Desktop 12.04 LTS security configuration guide  (很重要)
http://www.rationallyparanoid.com/articles/ubuntu-12-lts-security.html

{{item1{網路架構圖}}}

[img[img/TCPIPNAT.png]]
<<toBalaNotes "1">>

{{item1{VMware 網路設定注意事項}}}

''以設定 Host Only 網路為例, 如下 : ''

[img[img/vmware/VMNet02.png]]

上圖中有提供 DHCP 服務 (DHCP Settings), 請看下圖中的設定

[img[img/vmware/VMNet03.png]]

上圖中的 IP 配置範圍 192.168.233.128 - 254, 請將 ''254'' 改成 ''250'', 這時 DHCP 服務會使用 ''192.168.233.250'' 這 IP 位址, 來配置 IP 位址給 Client, ''所以 192.168.233.250 這位址是無法被虛擬主機使用''
<<toBalaNotes "2">>


///%1
//%/

///%2
//%/
<<forEachTiddler
    script '
        window.fetItemsPerPage = 20;

        function getHeader(context,count) {
            if (!window.fetStartIndex || window.fetStartIndex < 0) 
                window.fetStartIndex = 0;

            // ensure not to page behind the last page
            if (window.fetStartIndex >= count)
                window.fetStartIndex = Math.min(Math.max(window.fetStartIndex-window.fetItemsPerPage,0),count-1);

            createTiddlyButton(context.place,"<",null,
                    function(e) {
                        window.fetStartIndex -= window.fetItemsPerPage;
                        story.refreshTiddler(context.viewerTiddler.title,null,true);
                    });
            createTiddlyButton(context.place,">",null,
                    function(e) {
                        window.fetStartIndex += window.fetItemsPerPage;
                        story.refreshTiddler(context.viewerTiddler.title,null,true);
                    });

            var startNo = window.fetStartIndex+1;
            var endNo = Math.min(count,window.fetStartIndex+window.fetItemsPerPage);

            return "("+startNo+" - "+endNo+ " of "+ count + " items)\n";
        }
    '

    write
            '(index >= window.fetStartIndex) && (index < window.fetStartIndex + 20) ? "* [["+tiddler.title+"]]\n" : ""'

        begin
            'getHeader(context,count)'
>>

// /%
With a little scripting you can use the ~ForEachTiddlerPlugin to display the result "by pages". I.e. you don't display the full result list, but (e.g.) 10 at a time. 
Using a "pagewise" display may be useful when the result may get very large. This way you avoid scrolling the window to see the result. It also speeds up things since less items need to be display at a time.

''Code''
{{{
<<forEachTiddler
    script '
        window.fetItemsPerPage = 10;

        function getHeader(context,count) {
            if (!window.fetStartIndex || window.fetStartIndex < 0) 
                window.fetStartIndex = 0;

            // ensure not to page behind the last page
            if (window.fetStartIndex >= count)
                window.fetStartIndex = Math.min(Math.max(window.fetStartIndex-window.fetItemsPerPage,0),count-1);

            createTiddlyButton(context.place,"<",null,
                    function(e) {
                        window.fetStartIndex -= window.fetItemsPerPage;
                        story.refreshTiddler(context.viewerTiddler.title,null,true);
                    });
            createTiddlyButton(context.place,">",null,
                    function(e) {
                        window.fetStartIndex += window.fetItemsPerPage;
                        story.refreshTiddler(context.viewerTiddler.title,null,true);
                    });

            var startNo = window.fetStartIndex+1;
            var endNo = Math.min(count,window.fetStartIndex+window.fetItemsPerPage);

            return "("+startNo+" - "+endNo+ " of "+ count + " items)\n";
        }
    '

    write
            '(index >= window.fetStartIndex) && (index < window.fetStartIndex + 10) ? "* [["+tiddler.title+"]]\n" : ""'

        begin
            'getHeader(context,count)'
>>
}}}
// %/
{{item1{Apache 目錄結構}}}
先來瞭解一下 XAMPP 中的 Apache 2.2.X 這個版本的相關目錄結構,這樣才能夠知道如何處理我們的網頁資料啊!

{{op1{/opt/lampp/htdocs}}}
這就是預設的『首頁』所在目錄啦!當你輸入『http://localhost』時所顯示的資料所在。

{{op1{/opt/lampp/etc/httpd.conf (主要設定檔)}}}
最主要的設定檔,其實整個 Apache 也不過就是這個設定檔啦!裡面真是包山包海啊! 不過很多其他的 distribution 都將這個檔案拆成數個小檔案分別管理不同的參數。 但是主要設定檔還是以這個檔名為主的!你只要找到這個檔名就知道如何設定啦!

{{op1{/opt/lampp/modules}}}
Apache 支援很多的模組,所有你想要使用的模組預設是放置在這個目錄當中的!

{{op1{/opt/lampp/error/}}}
如果因為主機設定錯誤,或者是瀏覽器端要求的資料錯誤時,在瀏覽器上出現的錯誤訊息就以這個目錄的預設訊息為主!

{{op1{/opt/lampp/cgi-bin/}}}
預設給一些可執行的 CGI (網頁程式) 程式放置的目錄;當你輸入『http://localhost/cgi-bin/』 時所顯示的資料所在。

{{item1{Apache 設定檔關連圖}}}
{{{
/opt/lampp/etc/httpd.conf
                 |
                 |--- extra/httpd-default.conf
                 |
                 |--- extra/httpd-multilang-errordoc.conf
                 |
                 |--- extra/httpd-autoindex.conf
                 |
                 |--- extra/httpd-xampp.conf
}}}

<<toBalaNotes "apachedir">>
{{item1{httpd.conf 設定檔內容}}}

''$ cat /opt/lampp/etc/httpd.conf''
{{{
#
# This is the main Apache HTTP server configuration file.  It contains the
# configuration directives that give the server its instructions.
# See <URL:http://httpd.apache.org/docs/2.2> for detailed information.
# In particular, see
# <URL:http://httpd.apache.org/docs/2.2/mod/directives.html>
# for a discussion of each configuration directive.
#
# Do NOT simply read the instructions in here without understanding
# what they do.  They're here only as hints or reminders.  If you are unsure
# consult the online docs. You have been warned.
#
# Configuration and logfile names: If the filenames you specify for many
# of the server's control files begin with "/" (or "drive:/" for Win32), the
# server will use that explicit path.  If the filenames do *not* begin
# with "/", the value of ServerRoot is prepended -- so "logs/foo.log"
# with ServerRoot set to "/opt/lampp" will be interpreted by the
# server as "/opt/lampp/logs/foo.log".

#
# ServerRoot: The top of the directory tree under which the server's
# configuration, error, and log files are kept.
#
# Do not add a slash at the end of the directory path.  If you point
# ServerRoot at a non-local disk, be sure to point the LockFile directive
# at a local disk.  If you wish to share the same ServerRoot for multiple
# httpd daemons, you will need to change at least LockFile and PidFile.
#
ServerRoot "/opt/lampp"

#
# Listen: Allows you to bind Apache to specific IP addresses and/or
# ports, instead of the default. See also the <VirtualHost>
# directive.
#
# Change this to Listen on specific IP addresses as shown below to
# prevent Apache from glomming onto all bound IP addresses.
#
#Listen 12.34.56.78:80
Listen 80
}}}

''Dynamic Shared Object (DSO) Support''
{{{
#
# Dynamic Shared Object (DSO) Support
#
# To be able to use the functionality of a module which was built as a DSO you
# have to place corresponding `LoadModule' lines at this location so the
# directives contained in it are actually available _before_ they are used.
# Statically compiled modules (those listed by `httpd -l') do not need
# to be loaded here.
#
# Example:
# LoadModule foo_module modules/mod_foo.so
#
LoadModule authn_file_module modules/mod_authn_file.so
LoadModule authn_dbm_module modules/mod_authn_dbm.so
LoadModule authn_anon_module modules/mod_authn_anon.so
LoadModule authn_dbd_module modules/mod_authn_dbd.so
LoadModule authn_default_module modules/mod_authn_default.so
                                                :       
LoadModule alias_module modules/mod_alias.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule apreq_module modules/mod_apreq2.so
LoadModule ssl_module modules/mod_ssl.so

<IfDefine JUSTTOMAKEAPXSHAPPY>
LoadModule php4_module        modules/libphp4.so
LoadModule php5_module        modules/libphp5.so
</IfDefine>

<IfModule !mpm_winnt_module>
<IfModule !mpm_netware_module>
#
# If you wish httpd to run as a different user or group, you must run
# httpd as root initially and it will switch.
#
# User/Group: The name (or #number) of the user/group to run httpd as.
# It is usually good practice to create a dedicated user and group for
# running httpd, as with most system services.
#
User nobody
Group nogroup
</IfModule>
</IfModule>
}}}

''Main server configuration''
{{{
# 'Main' server configuration
#
# The directives in this section set up the values used by the 'main'
# server, which responds to any requests that aren't handled by a
# <VirtualHost> definition.  These values also provide defaults for
# any <VirtualHost> containers you may define later in the file.
#
# All of these directives may appear inside <VirtualHost> containers,
# in which case these default settings will be overridden for the
# virtual host being defined.
#

#
# ServerAdmin: Your address, where problems with the server should be
# e-mailed.  This address appears on some server-generated pages, such
# as error documents.  e.g. admin@your-domain.com
#
ServerAdmin you@example.com

#
# ServerName gives the name and port that the server uses to identify itself.
# This can often be determined automatically, but we recommend you specify
# it explicitly to prevent problems during startup.
#
# If your host doesn't have a registered DNS name, enter its IP address here.
#
#ServerName www.example.com:80
# XAMPP
ServerName localhost

#
# DocumentRoot: The directory out of which you will serve your
# documents. By default, all requests are taken from this directory, but
# symbolic links and aliases may be used to point to other locations.
#
DocumentRoot "/opt/lampp/htdocs"

#
# Each directory to which Apache has access can be configured with respect
# to which services and features are allowed and/or disabled in that
# directory (and its subdirectories).
#
# First, we configure the "default" to be a very restrictive set of
# features.
#
<Directory />
    Options FollowSymLinks
    AllowOverride None
    #XAMPP
    #Order deny,allow
    #Deny from all
</Directory>

#
# Note that from this point forward you must specifically allow
# particular features to be enabled - so if something's not working as
# you might expect, make sure that you have specifically enabled it
# below.
#

#
# This should be changed to whatever you set DocumentRoot to.
#
<Directory "/opt/lampp/htdocs">
    #
    # Possible values for the Options directive are "None", "All",
    # or any combination of:
    #   Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
    #
    # Note that "MultiViews" must be named *explicitly* --- "Options All"
    # doesn't give it to you.
    #
    # The Options directive is both complicated and important.  Please see
    # http://httpd.apache.org/docs/2.2/mod/core.html#options
    # for more information.
    #
    #Options Indexes FollowSymLinks
    # XAMPP
    Options Indexes FollowSymLinks ExecCGI Includes

    #
    # AllowOverride controls what directives may be placed in .htaccess files.
    # It can be "All", "None", or any combination of the keywords:
    #   Options FileInfo AuthConfig Limit
    #
    #AllowOverride None
    # since XAMPP 1.4:
    AllowOverride All

    #
    # Controls who can get stuff from this server.
    #
    Order allow,deny
    Allow from all

</Directory>

#
# DirectoryIndex: sets the file that Apache will serve if a directory
# is requested.
#
<IfModule dir_module>
    #DirectoryIndex index.html
    # XAMPP
    DirectoryIndex index.html index.html.var index.php index.php3 index.php4
</IfModule>
}}}

{{{
#
# The following lines prevent .htaccess and .htpasswd files from being
# viewed by Web clients.
#
<FilesMatch "^\.ht">
    Order allow,deny
    Deny from all
</FilesMatch>

#
# ErrorLog: The location of the error log file.
# If you do not specify an ErrorLog directive within a <VirtualHost>
# container, error messages relating to that virtual host will be
# logged here.  If you *do* define an error logfile for a <VirtualHost>
# container, that host's errors will be logged there and not here.
#
ErrorLog logs/error_log

#
# LogLevel: Control the number of messages logged to the error_log.
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
#
LogLevel warn

<IfModule log_config_module>
    #
    # The following directives define some format nicknames for use with
    # a CustomLog directive (see below).
    #
    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
    LogFormat "%h %l %u %t \"%r\" %>s %b" common

    <IfModule logio_module>
      # You need to enable mod_logio.c to use %I and %O
      LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
    </IfModule>

    #
    # The location and format of the access logfile (Common Logfile Format).
    # If you do not define any access logfiles within a <VirtualHost>
    # container, they will be logged here.  Contrariwise, if you *do*
    # define per-<VirtualHost> access logfiles, transactions will be
    # logged therein and *not* in this file.
    #
    CustomLog logs/access_log common

    #
    # If you prefer a logfile with access, agent, and referer information
    # (Combined Logfile Format) you can use the following directive.
    #
    #CustomLog logs/access_log combined
</IfModule>

<IfModule alias_module>
    #
    # Redirect: Allows you to tell clients about documents that used to
    # exist in your server's namespace, but do not anymore. The client
    # will make a new request for the document at its new location.
    # Example:
    # Redirect permanent /foo http://www.example.com/bar

    #
    # Alias: Maps web paths into filesystem paths and is used to
    # access content that does not live under the DocumentRoot.
    # Example:
    # Alias /webpath /full/filesystem/path
    #
    # If you include a trailing / on /webpath then the server will
    # require it to be present in the URL.  You will also likely
    # need to provide a <Directory> section to allow access to
    # the filesystem path.

    #
    # ScriptAlias: This controls which directories contain server scripts.
    # ScriptAliases are essentially the same as Aliases, except that
    # documents in the target directory are treated as applications and
    # run by the server when requested rather than as documents sent to the
    # client.  The same rules about trailing "/" apply to ScriptAlias
    # directives as to Alias.
    #
    ScriptAlias /cgi-bin/ "/opt/lampp/cgi-bin/"

</IfModule>

<IfModule cgid_module>
    #
    # ScriptSock: On threaded servers, designate the path to the UNIX
    # socket used to communicate with the CGI daemon of mod_cgid.
    #
    #Scriptsock logs/cgisock
</IfModule>

#
# "/opt/lampp/cgi-bin" should be changed to whatever your ScriptAliased
# CGI directory exists, if you have that configured.
#
<Directory "/opt/lampp/cgi-bin">
    AllowOverride None
    Options None
    Order allow,deny
    Allow from all
</Directory>

#
# DefaultType: the default MIME type the server will use for a document
# if it cannot otherwise determine one, such as from filename extensions.
# If your server contains mostly text or HTML documents, "text/plain" is
# a good value.  If most of your content is binary, such as applications
# or images, you may want to use "application/octet-stream" instead to
# keep browsers from trying to display binary files as though they are
# text.
#
DefaultType text/plain

<IfModule mime_module>
    #
    # TypesConfig points to the file containing the list of mappings from
    # filename extension to MIME-type.
    #
    TypesConfig etc/mime.types

    #
    # AddType allows you to add to or override the MIME configuration
    # file specified in TypesConfig for specific file types.
    #
    #AddType application/x-gzip .tgz
    #
    # AddEncoding allows you to have certain browsers uncompress
    # information on the fly. Note: Not all browsers support this.
    #
    #AddEncoding x-compress .Z
    #AddEncoding x-gzip .gz .tgz
    #
    # If the AddEncoding directives above are commented-out, then you
    # probably should define those extensions to indicate media types:
    #
    AddType application/x-compress .Z
    AddType application/x-gzip .gz .tgz

    #
    # AddHandler allows you to map certain file extensions to "handlers":
    # actions unrelated to filetype. These can be either built into the server
    # or added with the Action directive (see below)
    #
    # To use CGI scripts outside of ScriptAliased directories:
    # (You will also need to add "ExecCGI" to the "Options" directive.)
    #
    #AddHandler cgi-script .cgi
    # XAMPP, since LAMPP 0.9.8:
    AddHandler cgi-script .cgi .pl

    # For files that include their own HTTP headers:
    #AddHandler send-as-is asis

    # For server-parsed imagemap files:
    #AddHandler imap-file map

    # For type maps (negotiated resources):
    #AddHandler type-map var

    #
    # Filters allow you to process content before it is sent to the client.
    #
    # To parse .shtml files for server-side includes (SSI):
    # (You will also need to add "Includes" to the "Options" directive.)
    #
    # XAMPP
    AddType text/html .shtml
    AddOutputFilter INCLUDES .shtml
</IfModule>

#
# The mod_mime_magic module allows the server to use various hints from the
# contents of the file itself to determine its type.  The MIMEMagicFile
# directive tells the module where the hint definitions are located.
#
#MIMEMagicFile etc/magic

#
# Customizable error responses come in three flavors:
# 1) plain text 2) local redirects 3) external redirects
#
# Some examples:
#ErrorDocument 500 "The server made a boo boo."
#ErrorDocument 404 /missing.html
#ErrorDocument 404 "/cgi-bin/missing_handler.pl"
#ErrorDocument 402 http://www.example.com/subscription_info.html
#

#
# EnableMMAP and EnableSendfile: On systems that support it,
# memory-mapping or the sendfile syscall is used to deliver
# files.  This usually improves server performance, but must
# be turned off when serving from networked-mounted
# filesystems or if support for these functions is otherwise
# broken on your system.
#
EnableMMAP off
EnableSendfile off

# Supplemental configuration
#
# The configuration files in the etc/extra/ directory can be
# included to add extra features or to modify the default configuration of
# the server, or you may simply copy their contents here and change as
# necessary.

# Server-pool management (MPM specific)
#Include etc/extra/httpd-mpm.conf

# Multi-language error messages
Include etc/extra/httpd-multilang-errordoc.conf

# Fancy directory listings
Include etc/extra/httpd-autoindex.conf

# Language settings
#Include etc/extra/httpd-languages.conf

# User home directories
#Include etc/extra/httpd-userdir.conf

# Real-time info on requests and configuration
#Include etc/extra/httpd-info.conf

# Virtual hosts
#Include etc/extra/httpd-vhosts.conf

# Local access to the Apache HTTP Server Manual
#Include etc/extra/httpd-manual.conf

# Distributed authoring and versioning (WebDAV)
#Include etc/extra/httpd-dav.conf

# Various default settings
Include etc/extra/httpd-default.conf

# Secure (SSL/TLS) connections
<IfModule ssl_module>
# XAMPP
<IfDefine SSL>
Include etc/extra/httpd-ssl.conf
</IfDefine>
</IfModule>
#
# Note: The following must must be present to support
#       starting without SSL on platforms with no /dev/random equivalent
#       but a statically compiled-in mod_ssl.
#
<IfModule ssl_module>
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
</IfModule>

# XAMPP
Include etc/extra/httpd-xampp.conf
}}}

///%apachedir
//%/
''參考文章''
1. Router 和 Switch的差異 
http://www.ithome.com.tw/itadm/article.php?c=72872

{{item1{備份網路設定檔}}}
Issue the following command to take a backup of your current network configuration:
{{{
# sudo cp /etc/network/interfaces /etc/network/interfaces.bak
}}}

{{item1{Setting up External Network Interface}}}
Here, we configure the Ubuntu networking system to bring the the local loopback and external network interfaces up by editing ''/etc/networking/interfaces''. The primary goal here is to set up your external network interface (eth0, or whatever you're using in place of it) to be brought up by the networking subsystem. The examples below are only for the most basic setups. If your setup requires additional configuration, for example you need to setup ADSL with PPPoE, adapt the following examples so that the end result is your external network interface connected to the Internet.

''For Dynamic IP Addresses (DHCP) Only''
Open ''/etc/network/interfaces'' with your favourite editor. Delete everything and paste in what is below. Follow the commented out instructions carefully.
{{{
# Set up the local loopback interface
auto lo
iface lo inet loopback

# Set up the external interface
#
# Don't forget to change eth0 to the proper name of the external
# interface if applicable.
#
auto eth0
iface eth0 inet dhcp
}}}

''For Static IP Address Only''
Open ''/etc/network/interfaces'' with your favourite editor. Delete everything and paste in what is below. Follow the commented out instructions carefully.
{{{
# Set up the local loopback interface
auto lo
iface lo inet loopback

# Set up the External interface
#
# For every xxx.xxx.xxx.xxx, enter the numeric address given to you
# by your Internet provider. Don't forget to change eth0 to the proper
# name of the external interface if applicable.
#
auto eth0
iface eth0 inet static
address xxx.xxx.xxx.xxx
netmask xxx.xxx.xxx.xxx
gateway xxx.xxx.xxx.xxx
}}}

''[注意] 一定要設定 Gateway''

Now, set up your DNS servers as given to you by your service provider in ''/etc/resolv.conf'', which should look something like this
{{{
nameserver xxx.xxx.xxx.xxx
nameserver xxx.xxx.xxx.xxx
}}}

{{op1{Testing Connectivity}}}
Reload the network configuration and test for connectivity,
{{{
# sudo /etc/init.d/networking restart
# ping -c 3 -W 10 ubuntu.com
PING ubuntu.com (82.211.81.166) 56(84) bytes of data.
64 bytes from signey.ubuntu.com (82.211.81.166): icmp_seq=1 ttl=43 time=99.9 ms
64 bytes from signey.ubuntu.com (82.211.81.166): icmp_seq=2 ttl=43 time=109 ms
64 bytes from signey.ubuntu.com (82.211.81.166): icmp_seq=3 ttl=43 time=100 ms

--- ubuntu.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2001ms
rtt min/avg/max/mdev = 99.982/103.450/109.419/4.254 ms
}}}
<<toBalaNotes "External">>

{{item1{Configuring the Internal Network Interfaces}}}

{{op1{Wired Only}}}
Append the following to /etc/network/interfaces and follow the commented out instructions carefully.
{{{
# Set up the internal wired network
#
# Don't forget to change eth1 to the proper name of the internal
# wired network interface if applicable.
#
auto eth1
iface eth1 inet static
    address 192.168.0.1
    network 192.168.0.0
    netmask 255.255.255.0
    broadcast 192.168.0.255
}}}
Your internal network interface is: eth1 (or whatever you're using in place of it)

{{op1{Wireless Only}}}
If you plan on using WEP, generate a network key,
{{{
$ dd if=/dev/random bs=1 count=13 2>/dev/null | xxd -p
}}}

Append the following to /etc/network/interfaces and follow the commented out instructions carefully.
{{{
# Set up the internal wireless network
#
# Don't forget to change wlan0 to the proper name of the internal
# wireless network interface if applicable.
#
# If you would like to use WEP, uncomment the line 'wireless-key'
# and replace '<key goes here>' with a WEP key.
# 
# You may also change the network essid and channel.
#
auto wlan0
iface wlan0 inet static
          wireless-mode master
          wireless-essid "UbuntuWireless"
          wireless-channel 1
          #wireless-key <key goes here>
          address 192.168.0.1
          network 192.168.0.0
          netmask 255.255.255.0
          broadcast 192.168.0.255
}}}
Your internal network interface is: wlan0 (or whatever you're using in place of it)

{{op1{Both Wired and Wireless}}}
First install the necessary tools to create a network bridge,
{{{
$ sudo apt-get install bridge-utils
}}}

If you plan on using WEP, generate a network key,
{{{
$ dd if=/dev/random bs=1 count=13 2>/dev/null | xxd -p
}}}

Append the following to /etc/network/interfaces and follow the commented out instructions carefully.
{{{
# Set up the internal wireless network
#
# Don't forget to change wlan0 to the proper name of the internal
# wireless network interface if applicable.
#
# If you would like to use WEP, uncomment the line 'wireless-key'
# and replace '<key goes here>' with a WEP key.
# 
# You may also change the network essid and channel.
#
auto wlan0
iface wlan0 inet manual
    wireless-mode master
    wireless-essid "UbuntuWireless"
    wireless-channel 1
    # wireless-key <key goes here>

# Set up the internal wired network
#
# It's not necessary to bring this interface up as the bridge
# we are about to create does this. Leave these lines commented.
#
#auto eth1
# iface eth1 inet manual


# Set up the internal wired/wireless network bridge
#
# Don't forget to change wlan0 and eth1 to the proper name of
# the internal wired and wireless interfaces if applicable.
#
auto br0
iface br0 inet static
    address 192.168.0.1
    network 192.168.0.0
    netmask 255.255.255.0
    broadcast 192.168.0.255
    bridge-ports eth1 wlan0
}}}
Your internal network interface is: br0

{{item1{Restart Networking}}}
Now, if the following command is executed successfully, your networking devices should have been properly configured.
{{{
$ sudo /etc/init.d/networking restart
}}}
<<toBalaNotes "internal">>

///%External
//%/

///%internal
//%/
Ubuntu 本文網址 : http://doc.ubuntu.com/ubuntu/serverguide/C/dhcp.html

The Dynamic Host Configuration Protocol (DHCP) is a network service that enables host computers to be automatically assigned settings from a server as opposed to manually configuring each network host. Computers configured to be DHCP clients have no control over the settings they receive from the DHCP server, and the configuration is transparent to the computer's user.

The most common settings provided by a DHCP server to DHCP clients include:
{{{
* IP-Address and Netmask
* DNS
* WINS
}}}
However, a DHCP server can also supply configuration properties such as:
{{{
* Host Name
* Domain Name
* Default Gateway
* Time Server
* Print Server
}}}
The advantage of using DHCP is that changes to the network, for example a change in the address of the DNS server, need only be changed at the DHCP server, and all network hosts will be reconfigured the next time their DHCP clients poll the DHCP server. As an added advantage, it is also easier to integrate new computers into the network, as there is no need to check for the availability of an IP address. Conflicts in IP address allocation are also reduced.

A DHCP server can provide configuration settings using two methods:

''MAC Address''
This method entails using DHCP to identify the unique hardware address of each network card connected to the network and then continually supplying a constant configuration each time the DHCP client makes a request to the DHCP server using that network device.

''Address Pool''
This method entails defining a pool (sometimes also called a range or scope) of IP addresses from which DHCP clients are supplied their configuration properties dynamically and on a "first come, first served" basis. When a DHCP client is no longer on the network for a specified period, the configuration is expired and released back to the address pool for use by other DHCP Clients.

Ubuntu is shipped with both DHCP server and client. The server is dhcpd (dynamic host configuration protocol daemon). The client provided with Ubuntu is dhclient and should be installed on all computers required to be automatically configured. Both programs are easy to install and configure and will be automatically started at system boot. 

<<toBalaNotes "dhcp">>


///%dhcp
//%/
Also known as a namespace, a domain namespace is a name service provided by the  Internet for Transmission Control Protocol networks/Internet Protocol (TCP/IP). DNS is broken up into domains, a logical organization of computers that exist in a larger network.

[img[img/linux/bind/dnsstruct.gif]]

{{op1{Fully qualified domain name}}}
A fully qualified domain name (FQDN), sometimes also referred as an absolute domain name,[1] is a domain name that specifies its exact location in the tree hierarchy of the Domain Name System (DNS). It specifies all domain levels, including the top-level domain and the root domain. A fully qualified domain name is distinguished by its unambiguity; it can only be interpreted one way.

For example, given a device with a local hostname myhost and a parent domain name example.com, the fully qualified domain name is myhost.example.com. The FQDN therefore uniquely identifies the device —while there may be many hosts in the world called myhost, there can only be one myhost.example.com. In the Domain Name System, and most notably, in DNS zone files, a fully qualified domain name is specified with a trailing dot. For example,
{{{
    somehost.example.com.
}}}
specifies an absolute domain name that ends with an empty top level domain label.

The DNS root domain is unnamed, which is expressed by an empty label, resulting in a domain name ending with the dot separator. However, many DNS resolvers process a domain name that contains a dot in any position as being fully qualified or add the final dot needed for the root of the DNS tree. Resolvers process a domain name without a dot as unqualified and automatically append the system's default domain name and the final dot.

Some applications, such as web browsers try to resolve the domain name part of a Uniform Resource Locator (URL) if the resolver cannot find the specified domain or if it is clearly not fully qualified by appending frequently used top-level domains and testing the result. Some applications, however, never use trailing dots to indicate absoluteness, because the underlying protocols require the use of FQDNs, such as Simple Mail Transfer Protocol (e-mail).

''The root of the tree and DNS''
As a special case to the FQDN, a single dot should represent the root of the directory tree, which in turn would mean that a hypothetical computer system would be called the root server. There is no such thing as a root server on the global Internet, however, since there is no A record for the "." domain.

There are 13 authoritative root nameservers which contain the DNS records for root name lookups. Each name server knows the IP addresses of the name servers of first or "top level domains" (TLDs). The "com." and "uk." domains are TLDs.

Just like the root domain, most TLDs do not resolve to an IP address, but usually have three or more distinct name servers which answer queries for the TLD. (e.g. There is no server known by the FQDN "net." nor "uk." but there are 13 name servers listed for "net." and 11 name servers "uk.")

An example of a TLD which resolves is "uz.", meaning that the .uz domain is an example of the shortest resolving FQDN with a URL of http://uz/ for web access and is notable because no dot appears in the URL. Due to the scarcity of domains without a dot, not all browsers will permit this to work

<<toBalaNotes "dnsname">>

{{item1{Internet Network Information center(InterNIC)}}}
官方網站 : http://internic.net/

InterNIC 是美國政府商務部的一個註冊服務標章,授權給 ICANN 使用,用以提供有關網際網路「網域名稱註冊服務」的有用資料:
{{{
* 搜尋 註冊管理機構層級 WHOIS 主機 內的「網域名稱註冊資料」‧
* 提供 ICANN 認可的受理註冊機構名單,及其連絡資料‧
* 提供網頁界面 受理註冊機構障礙報告表,讓註冊人提出對受理註冊機構的抱怨‧
* 提供網頁界面 WHOIS 資料障礙報告表,提報不精確的「網域名稱註冊資料」‧
}}}
「註冊管理機構層級 WHOIS 主機」,可以搜尋 .aero, .arpa, .biz, .cat, .com, .coop, .edu, .info, .int, .jobs, .mobi, .museum, .name, .net, .org, .pro, 或 .travel 等等「全球 (屬性) 網域名稱」‧搜尋結果依網域名稱的種類而定‧例如,對於 .com 及 .net,只是簡單的得到名稱主機名稱、受理註冊機構、註冊日期、到期日‧詳細的連絡資料須要進入「受理註冊機構層級 WHOIS 主機」去搜尋取得‧Mintac 提供中文的網頁界面 WHOIS 查詢系統 能夠自行連結 InterNIC 和「受理註冊機構」的 WHOIS 主機,一次取得所有的「網域名稱註冊資料」‧

''WHOIS'' 是一種網際網路服務,它提供註冊的「網域名稱註冊資料」的公示服務‧「網域名稱註冊資料」含有「網域名稱註冊人」的連絡資料‧在全球網域名稱 (屬性網域名稱,gTLDs,generic top-level domains) 註冊之際,「網域名稱註冊資料」收集的內容,及這些資料的使用方式,由 ICANN 規範在相關的註冊約定書之中‧舉例說明,ICANN 要求經其認可的「受理註冊機構」(Registrars)

必須收集並且提供免費取用的方式對大眾公開,被註冊的網域名稱的名字,其專責名稱主機、受理註冊機構、註冊日期、到期日期、以及註冊所有人 (註冊人)、其行政管理人 (業務承辦人)、技術管理人等的連絡資料‧

{{item1{TWNIC}}}
官方網站 : http://www.twnic.net.tw/about/about_01.htm

1998 年 4 月行政院 NII 推動小組決議由交通部電信總局為台灣網路資訊中心之主管機關,編列預算輔導該中心轉型成為財團法人,至 1999 年 12 月 29 日台灣網路資訊中心正式完成財團法人設立登記。

TWNIC 是目前國內唯一統籌網域名稱註冊及 IP 位址發放之超然中立之非營利性組織,除提供國內完整之網路服務外,更積極參與各項國際相關網路會議。期盼更多人的參與及不斷檢討改進,為我國網際網路事業提供最佳服務,是 TWNIC 成立為財團法人之最大目的,希望我們團隊能進最大努力,各界也能不斷給予 TWNIC 更多的支持予鼓勵,使我國網際網路事業能更健全、更快速的發展。

{{item1{Root DNS Server}}}
A Cisco 7301 router, part of the AMS-IX mirror of the K root-server.

[img[img/linux/800px-Ams-ix.k.root-servers.net.jpg]]

{{item1{Whois 查詢}}}
在 [[InterNIC|http://internic.net/]] 網站的首頁, 點選 Whois, 執行 Whois 查詢

[img[img/linux/bind/whois.png]]

查詢結果如下圖 :

[img[img/linux/bind/whois01.png]]



///%dnsname
//%/
''參考文章''
1. Configuring IPv6 Router Advertisements and a Static Address
http://www.telecom.otago.ac.nz/tele301/student_html/postinst-router-advertisements.html
2. Providing IPv6 DNS resolver data with radvd
http://www.systemajik.com/blog/providing-ipv6-dns-resolver-data-using-radvd/
3. Various DHCPv6 Server and Client Configuration Examples (重要)
http://linux.ardynet.com/ipv6setup.php

{{item1{IPv6 位址類別與格式}}}

''IPv6 格式''
IPv6 (128 bits) 與 IPv4 (32 bits) 在分類與格式上是不同的, IPv6 在格式上是使用 ''[十六進位數字]'' 來表示 128 Bits 位址, 每四個十六進位數字為一組, 共有八組, 各組之間以 ":" 字元作為區隔, 範例如下 :
{{{
fc00:fefe:aba:babe:0001:0002:0003:0004
}}}

''IPv6 類別''
Pv6 的類別分為 Global, Unique Local 及 Link Local 這三類, Global 相當於 IPv4 的公有位址 (Public address), 開頭數字為 2 或 3. Unique Local 相當於 IPv4 的私有位址 (Private address), 開頭數字為 fc 或 fd, 這類位址只能在企業內部的路由器之間傳送. 至於 Link Local 是一個非常特別的類別, 它是採用自動配置, 所配置的 IPv6 Link Local  位址是根據本機網卡的 MAC 位址 (EUI-64) 來產生, 開頭數字為 fe80, 這類位址是無法經由路由器傳送到其他網段.

<<toBalaNotes "1">>

{{item1{IPv6 Anycast Addresses}}}
Anycast addresses are a new, unique type of address that is new to IP in IPv6; the IPv6 implementation is based on the material in RFC 1546, Host Anycasting Service. Anycast addresses can be considered a conceptual cross between unicast and multicast addressing. Where unicast says “send to this one address” and multicast says “send to every member of this group”, anycast says “send to any one member of this group”. Naturally, in choosing which member to send to, we would for efficiency reasons normally send to the closest one—closest in routing terms. So we can normally also consider anycast to mean “send to the closest member of this group”.

The idea behind anycast is to enable functionality that was previously difficult to implement in TCP/IP. Anycast was specifically intended to provide flexibility in situations where we need a service that is provided by a number of different servers or routers but don't really care which one provides it. In routing, anycast allows datagrams to be sent to whichever router in a group of equivalent routers is closest, to allow load sharing amongst routers and dynamic flexibility if certain routers go out of service. Datagrams sent to the anycast address will automatically be delivered to the device that is easiest to reach.

Perhaps surprisingly, there is no special anycast addressing scheme: anycast addresses are the same as unicast addresses. An anycast address is created “automatically” when a unicast address is assigned to more than one interface.

Like multicast, anycast creates more work for routers; it is more complicated than unicast addressing. In particular, the further apart the devices that share the anycast address are, the more complexity is created. Anycasting across the global Internet would be potentially difficult to implement, and IPv6 anycasting was designed for devices that are proximate to each other, generally in the same network. Also, due to the relative inexperience of the Internet community in using anycast, for the present time anycast addresses are used only by routers and not individual hosts.

''Windows''
Anycast IPv6 addresses

An anycast address identifies multiple interfaces. With the appropriate routing topology, packets addressed to an anycast address are delivered to a single interface (the nearest interface that is identified by the address). The nearest interface is defined as being closest in terms of routing distance. A multicast address is used for one-to-many communication, with delivery to multiple interfaces. An anycast address is used for one-to-one-of-many communication, with delivery to a single interface.

In order to facilitate delivery to the nearest anycast group member, the routing infrastructure must be aware of the interfaces that are assigned anycast addresses and their distances in terms of routing metrics. At present, anycast addresses are used only as destination addresses and are assigned only to routers. Anycast addresses are assigned from the unicast address space. The scope of an anycast address is the scope of the type of unicast address from which the anycast address is assigned.
Subnet-router anycast address

The subnet-router anycast address is both predefined and required. It is created from the subnet prefix for a given interface. To construct the subnet-router anycast address, the bits in the subnet prefix are fixed at their appropriate values and the remaining bits are set to 0. All router interfaces attached to a subnet are assigned the subnet-router anycast address for that subnet. The subnet-router anycast address is used for communication with one of multiple routers attached to a remote subnet.

<<toBalaNotes "2">>

{{item1{IPv6 Multicast Addresses}}}
http://www.tcpipguide.com/free/t_IPv6MulticastandAnycastAddressing.htm

{{item1{IPv6 ND General Operational Overview: ND Functions, Functional Groups and Message Types}}}
http://www.tcpipguide.com/free/t_IPv6NDGeneralOperationalOverviewNDFunctionsFunctio.htm

{{item1{Compatibility addresses}}}
To aid in the migration from IPv4 to IPv6 and facilitate the coexistence of both types of hosts, the following addresses are defined:

''IPv4-compatible address''

The IPv4-compatible address, 0:0:0:0:0:0:w.x.y.z or ::w.x.y.z (where w.x.y.z is the dotted decimal representation of a public IPv4 address), is used by dual-stack nodes that are communicating with IPv6 over an IPv4 infrastructure. Dual-stack nodes are nodes with both IPv4 and IPv6 protocols. When the IPv4-compatible address is used as an IPv6 destination, IPv6 traffic is automatically encapsulated with an IPv4 header and sent to the destination by using the IPv4 infrastructure.

''IPv4-mapped address''

The IPv4-mapped address, 0:0:0:0:0:FFFF:w.x.y.z or ::FFFF:w.x.y.z, is used to represent an IPv4-only node to an IPv6 node. It is used only for internal representation. The IPv4-mapped address is never used as a source or destination address for an IPv6 packet. The IPv6 protocol does not support the use of IPv4-mapped addresses.

''6to4 address''

The 6to4 address is used for communicating between two nodes running both IPv4 and IPv6 over the Internet. The 6to4 address is formed by combining the prefix 2002::/16 with the 32 bits of the public IPv4 address of the node, forming a 48-bit prefix. For example, for the IPv4 address of 131.107.0.1, the 6to4 address prefix is 2002:836B:1::/48. For more information about 6to4, see IPv6 traffic between nodes in different sites across the Internet (6to4).

<<toBalaNotes "3">>

{{{
$ sudo apt-get install radvd
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following NEW packages will be installed:
  radvd
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 63.9 kB of archives.
After this operation, 188 kB of additional disk space will be used.
Get:1 http://tw.archive.ubuntu.com/ubuntu/ precise/main radvd i386 1:1.8-1.2 [63.9 kB]
Fetched 63.9 kB in 6s (9,319 B/s)
Selecting previously unselected package radvd.
(Reading database ... 44133 files and directories currently installed.)
Unpacking radvd (from .../radvd_1%3a1.8-1.2_i386.deb) ...
Processing triggers for man-db ...
Processing triggers for ureadahead ...
ureadahead will be reprofiled on next reboot
Setting up radvd (1:1.8-1.2) ...
dpkg-statoverride: warning: --update given but /var/run/radvd does not exist
Starting radvd: 
* /etc/radvd.conf does not exist or is empty.
* See /usr/share/doc/radvd/README.Debian
* radvd will *not* be started.
}}}


{{{
interface eth1
{
    AdvSendAdvert             on;

    prefix fc00:babe:188::/64
    {
        AdvOnLink             on;
        AdvAutonomous         on;
        AdvRouterAddr         on;
    };
};

interface eth0
{
    AdvSendAdvert             off;
};

}}}


{{{
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto eth0
iface eth0 inet static
  address 192.168.100.188
  netmask 255.255.255.0
  gateway 192.168.100.252

iface eth0 inet6 static
  address fc00:babe:100::188
  netmask 64

up ip -6 route add fc00:babe:166::/64 via fc00:babe:100::166 dev eth0

auto eth1
iface eth1 inet static
  address 192.168.188.254
  netmask 255.255.255.0

iface eth1 inet6 static
  address fc00:babe:188::254
  netmask 64
}}}

{{{
$ ip -6 route show
fe80::/64 dev virbr66128  proto kernel  metric 256  mtu 1500 advmss 1440 hoplimit 0
fe80::/64 dev virbr0  proto kernel  metric 256  mtu 1500 advmss 1440 hoplimit 0
fe80::/64 dev net99  proto kernel  metric 256  mtu 1500 advmss 1440 hoplimit 0
fe80::/64 dev virbr88  proto kernel  metric 256  mtu 1500 advmss 1440 hoplimit 0
fe80::/64 dev virbr660  proto kernel  metric 256  mtu 1500 advmss 1440 hoplimit 0
fe80::/64 dev vbr166  proto kernel  metric 256  mtu 1500 advmss 1440 hoplimit 0
fe80::/64 dev virbr100  proto kernel  metric 256  mtu 1500 advmss 1440 hoplimit 0
fe80::/64 dev vbr188  proto kernel  metric 256  mtu 1500 advmss 1440 hoplimit 0
fe80::/64 dev wlan0  proto kernel  metric 256  mtu 1500 advmss 1440 hoplimit 0
}}}

///%1
//%/

///%2
//%/

///%3
//%/
{{item1{Why Private IP Address}}}
為了解決 IP 日漸不足的問題, RFC1918 中定義了一段 Private IP address, 這段 IP 可作為企業或單位內自行運用的 IP Address而無須經過向上游申請的手續.當然使用單位必須負責不讓這些 Private IP Address 的 routing information 流到單位外的網路上, 也就是說這些電腦只能和單位內的電腦連線, 外面的網路看不見單位內這些 Private IP Address 的電腦, 因此這段 Private IP Address 可重覆地被不同單位內部所使用, 進而達到節省 IP 的目的. 

{{item1{Private IP Range}}}

RFC 1918 共定義了三個範圍的 Private IP address
 
|Addr Range|mask|
|10.0.0.0 - 10.255.255.255|10.0.0.0/255.0.0.0|
|172.16.0.0 - 172.31.255.255|172.16.0.0/255.240.0.0|
|192.168.0.0 - 192.168.255.255|192.168.0.0/255.255.255.0|

{{item1{IP Masquerading (冒名頂替)}}}
The purpose of ''IP Masquerading'' is to allow machines with private, ''non-routable IP addresses'' on your network to access the Internet through the machine doing the masquerading. Traffic from your private network destined for the Internet must be manipulated for replies to be routable back to the machine that made the request. To do this, the kernel must modify the source IP address of each packet so that replies will be routed back to it, rather than to the private IP address that made the request, which is impossible over the Internet. Linux uses Connection Tracking (conntrack) to keep track of which connections belong to which machines and reroute each return packet accordingly. Traffic leaving your private network is thus "masqueraded" as having originated from your Ubuntu gateway machine. This process is referred to in Microsoft documentation as Internet Connection Sharing.

<<toBalaNotes "nat">>



///%nat
//%/
官方網站 : http://www.samba.org/

Successfully networking your Ubuntu system with Windows clients involves providing and integrating with services common to Windows environments. Such services assist the sharing of data and information about the computers and users involved in the network, and may be classified under three major categories of functionality:
{{{
* File and Printer Sharing Services. Using the Server Message Block (SMB) protocol to facilitate the sharing of files, folders, volumes, and the sharing of printers throughout the network.

* Directory Services. Sharing vital information about the computers and users of the network with such technologies as the Lightweight Directory Access Protocol (LDAP) and Microsoft Active Directory®.

* Authentication and Access. Establishing the identity of a computer or user of the network and determining the information the computer or user is authorized to access using such principles and technologies as file permissions, group policies, and the Kerberos authentication service.
}}}
Fortunately, your Ubuntu system may provide all such facilities to Windows clients and share network resources among them. One of the principal pieces of software your Ubuntu system includes for Windows networking is the Samba suite of SMB server applications and tools.

This section of the Ubuntu Server Guide will introduce some of the common Samba use cases, and how to install and configure the necessary packages.

{{item1{SAMBA 的執行}}}
SAMBA 透過兩支 daemon 來提供網芳服務,分別是:

{{op1{1. nmbd}}}
這個 daemon 是用來管理工作群組、NetBIOS Name 等等的名稱解析。 主要利用 ''UDP 協定'' 開啟 ''Port 137, 138'' 來負責名稱解析的任務

{{op1{2. smbd}}}
這個 daemon 的主要功能就是用來管理 SAMBA 主機分享的目錄、檔案與印表機等等。 主要利用可靠的 ''TCP 協定''來傳輸資料,開放的埠口為 ''139 (Windows 98 使用)'' 及 ''445 (XP/Vista/7 使用)''。 

<<toBalaNotes "samba">>

///%samba
//%/
Ubuntu 官方網址 : http://doc.ubuntu.com/ubuntu/serverguide/C/firewall.html

''Introduction''
The Linux kernel includes the ''Netfilter'' subsystem, which is used to manipulate or decide the fate of network traffic headed into or through your server. All modern Linux firewall solutions use this system for packet filtering.

The kernel's packet filtering system would be of little use to administrators without a userspace interface to manage it. This is the purpose of iptables. When a packet reaches your server, it will be handed off to the Netfilter subsystem for acceptance, manipulation, or rejection based on the rules supplied to it from userspace via iptables. Thus, ''iptables'' is all you need to manage your firewall if you're familiar with it, but many frontends are available to simplify the task. 

{{item1{ufw - Uncomplicated Firewall}}}
The default firewall configuration tool for Ubuntu is ''ufw''. Developed to ease iptables firewall configuration, ufw provides a user friendly way to create an ''IPv4 or IPv6 host-based firewall''.

''[註]'' ufw by default is initially disabled
{{{
ufw is not intended to provide complete firewall functionality via its command interface, but instead provides an easy way to add or remove simple rules. It is currently mainly used for host-based firewalls. 
}}}

{{op1{UFW in Ubuntu}}}
Ubuntu 8.04 LTS introduced ufw, and it is available by default in all Ubuntu installations after 8.04 LTS.

Available Versions
{{{
* Ubuntu 8.04 LTS: 0.16.2
* Ubuntu 8.10: 0.23.2
* Ubuntu 9.04: 0.27-0ubuntu2
* Ubuntu 9.10: 0.29-1 
}}}

{{op1{Features}}}

|''Feature''|''8.04 LTS''|''8.10''|''9.04''|''9.10''|
|default incoming policy (allow/deny)|yes|yes|yes|yes|
|allow/deny incoming rules|yes|yes|yes|yes|
|ipv6|yes|yes|yes|yes|
|status|yes|yes|yes|yes|
|logging (on/off)|yes|yes|yes|yes|
|extensible framework|yes|yes|yes|yes|
|application integration|--|yes|yes|yes|
|limit incoming rules (rate limiting)|--|yes|yes|yes|
|multiport incoming rules|--|yes|yes|yes|

{{op1{Basic Usage}}}
Getting started with ufw is easy. For example, to enable firewall, allow ssh access, enable logging, and check the status of the firewall, perform:
{{{
$ sudo ufw allow ssh/tcp
$ sudo ufw logging on
$ sudo ufw enable
$ sudo ufw status
Firewall loaded

To                         Action  From
--                         ------  ----
22:tcp                     ALLOW   Anywhere
}}}
This sets up a default deny (DROP) firewall for incoming connections, with all outbound connections allowed with connections tracking.

{{op1{Advanced Functionality}}}
As mentioned, the ufw framework is capable of doing anything that iptables can do. This is achieved by using several sets of rules files, which are nothing more than iptables-restore compatible text files. Fine-tuning ufw and/or adding additional iptables commands not offered via the ufw command is a matter of editing various text files:
{{{
* /etc/default/ufw: high level configuration, such as default policies, IPv6 support and kernel modules to use
* /etc/ufw/before.rules: rules in these files are evaluated before any rules added via the ufw command
* /etc/ufw/after.rules: rules in these files are evaluated after any rules added via the ufw command
* /etc/ufw/sysctl.conf: kernel network tunables
* /var/lib/ufw/user.rules: rules added via the ufw command (should not normally be edited by hand)
* /etc/ufw/ufw.conf: sets whether or not ufw is enabled on boot, and in 9.04 (ufw 0.27) and later, sets the LOGLEVEL 
}}}
After modifying any of the above files, activate the new settings with:
{{{
$ sudo ufw disable
$ sudo ufw enable
}}}

<<toBalaNotes "ufw">>

iptables 是一套含括在最新 Linux 分支套件裡的防火牆,網路上已經有相當多關於它的的教戰守則。
.
它是使用者層級的一套應用,讓系統管理者能夠組態 Linux kernel 防火牆 (會是以各種不同的 Netfilter 模組實作) 所提供的表單,並儲存它的 chains 與 rules。不同的 kernel 模組與程式使用的是不同的協定;iptables 應用在 ipv4 上、ip6tables 應用在 ipv6 上、arptables 應用在 ARP 上,而 ebtables 則特指定為 Ethernet frames 所用。
.
iptables 需要較高權限才能操作,因此必須由 root 使用者的身份執行,否則無法使用。在絕大多數 linux 系統上,iptables 安裝在 /usr/sbin/iptables 裡,且擁有自已的 man page 文件,在已安裝的情況下 man iptables 就能開啟。
.
要瞭解 iptables 的基本用法,建議參考 Ubuntu 指導手冊:
https://help.ubuntu.com/community/IptablesHowTo
.
這裡,我要講的是這個指令的一些特別用法。
.
【任務一:封鎖已知的問題主機,讓它到不了你的機器】
wget -qO – http://infiltrated.net/blacklisted|awk ‘!/#|[a-z]/&&/./{print “iptables -A INPUT -s “$1″ -j DROP”}’
Blacklisted 是編輯過的所有已知問題主機 (僵屍網路botnets、濫發垃圾郵件主機spammer、暴力攻擊主機bruteforcers 等等),會每個小時更新。這個指令會取得清單、幫你建立 rules,若你要它們動階封鎖,在命令列最後加入 |sh 即可。這是一個相當實用的解法,封鎖所有但允許指定的幾個,很多人沒這麼作只是因為手邊沒有一個這樣的 script。
【譯註:此 script 將 rule 寫入正執行中的 iptables,當iptables 重新啟動,這些 rule 將會清除需重新載入】
.
【任務二:有人”敲”了,就打開特定的門(通訊埠)】
knock < host > 3000 4000 5000 && ssh -p
user@host && knock < host > 5000 4000 3000
這個例子裡,看不到直接用到 iptables 什麼,它其實是將 iptables 用在 knockd 組態檔裡,你得安裝它。以下是 sshd (通訊埠22) 的組態範例。
.
[options]
logfile = /var/log/knockd.log
[openSSH]
sequence = 3000,4000,5000
seq_timeout = 5
command = /sbin/iptables -A INPUT -i eth0 -s %IP% -p tcp –dport 22 -j ACCEPT
tcpflags = syn
[closeSSH]
sequence = 5000,4000,3000
seq_timeout = 5
command = /sbin/iptables -D INPUT -i eth0 -s %IP% -p tcp –dport 22 -j ACCEPT
tcpflags = syn
.
【任務三:對通訊埠 80 重導至較高通訊埠】
iptables -t nat -A PREROUTING -p tcp –dport 80 -j REDIRECT –to-port 9001
當你希望一般使用者執行較高通訊埠的 daemon,但服務顯示的是標準通訊埠時,這個規則就很好用了。本例中你可以讓一般使用者啟動/停用聆聽 9001 通訊埠的 apache,但他的網站是顯示通訊埠 80。
.
【任務四:讓 proxy 只用在非本地端 LAN 上】
iptables -t nat -A OUTPUT -d ! 10.0.0.0/8 -p tcp –dport 80 -j DNAT –to-destination 10.1.1.123:3128
把 10.0.0.0/8 換成你最大的那個本地端子網路,然後將 10.1.1.123:3128 改成你的 proxy 設定。不過要注意這個設定只有在 proxy 伺服器組態為 passive 才能運作。
Now your firefox transparently proxy’s stuff destined outside your network.. and Doesn’t proxy stuff inside your network. as well as all your other favorite web applications. curl, wget.
.
【任務五:限制只能有 10 個 ssh 連線】
/sbin/iptables -A INPUT -p tcp –syn –dport 22 -m connlimit –connlimit-above 10 -j REJECT
這個命令可讓你限制存取連線某通訊埠在一定的範圍內,對用來限制連線到 Apache 通訊埠的數量也相當好用。
.
【任務六:限制 ssh 每 15 秒內只能有一個 session】
iptables -A INPUT -p tcp -i eth0 -m state –state NEW –dport 22 -m recent –update –seconds 15 -j DROP
iptables -A INPUT -p tcp -i eth0 -m state –state NEW –dport 22 -m recent –set -j ACCEPT
這兩條規則讓 iptables 命令從相同 IP 連結至通訊埠 22 的兩個新連線中間必須間隔 15 秒。若你的防火牆已有自已的 ssh accept 規則,請用它來取代上面 ACCEPT 這行。
.
【任務七:一個命令指定多重指令】
iptables -A INPUT -p tcp -m multiport –dports 22,80,143,6000:6003 -j ACCEPT
Multiport 擴充元件讓使用者可以指定多個通訊埠與範圍,透過一行指令就能建立複雜的規則。
multiport 指令讓你省掉好幾行-要新增修改時就簡單得多,只有一行所需的系統處理也較少。


 

///%ufw
//%/
Apache2 is configured by placing directives in plain text configuration files. These directives are separated between the following files and directories:

* ''apache2.conf'': the main Apache2 configuration file. Contains settings that are global to Apache2.
* ''conf.d'': contains configuration files which apply globally to Apache2. Other packages that use Apache2 to serve content may add files, or symlinks, to this directory.
* ''envvars'': file where Apache2 environment variables are set.
* ''httpd.conf'': historically the main Apache2 configuration file, named after the httpd daemon. The file can be used for user specific configuration options that globally effect Apache2.
* ''mods-available'': this directory contains configuration files to both load modules and configure them. Not all modules will have specific configuration files, however.
* ''mods-enabled'': holds symlinks to the files in /etc/apache2/mods-available. When a module configuration file is symlinked it will be enabled the next time apache2 is restarted.
* ''ports.conf'': houses the directives that determine which TCP ports Apache2 is listening on.
* ''sites-available'': this directory has configuration files for Apache2 Virtual Hosts. Virtual Hosts allow Apache2 to be configured for multiple sites that have separate configurations.
* ''sites-enabled'': like mods-enabled, sites-enabled contains symlinks to the /etc/apache2/sites-available directory. Similarly when a configuration file in sites-available is symlinked, the site configured by it will be active once Apache2 is restarted.

In addition, other configuration files may be added using the ''Include'' directive, and wildcards can be used to include many configuration files. Any directive may be placed in any of these configuration files. Changes to the main configuration files are only recognized by Apache2 when it is started or restarted.

The server also reads a file containing mime document types; the filename is set by the ''TypesConfig'' directive, and is ''/etc/mime.types'' by default.

{{item1{列出 /etc/apache2 目錄檔案}}}
{{{
$ ls -al /etc/apache2/
總計 88
drwxr-xr-x   7 root root  4096 2010-07-08 18:22 .
drwxr-xr-x 131 root root 12288 2010-07-09 08:52 ..
-rw-r--r--   1 root root  8113 2010-04-14 03:27 apache2.conf
drwxr-xr-x   2 root root  4096 2010-07-09 10:27 conf.d
-rw-r--r--   1 root root   725 2010-04-14 03:27 envvars
-rw-r--r--   1 root root   229 2010-07-08 18:22 httpd.conf
-rw-r--r--   1 root root 31063 2010-04-14 03:27 magic
drwxr-xr-x   2 root root  4096 2010-07-06 16:27 mods-available
drwxr-xr-x   2 root root  4096 2010-07-08 18:18 mods-enabled
-rw-r--r--   1 root root   750 2010-04-14 03:27 ports.conf
drwxr-xr-x   2 root root  4096 2010-07-06 16:27 sites-available
drwxr-xr-x   2 root root  4096 2010-07-06 16:27 sites-enabled
}}}

{{item1{列出 /etc/apache2/mods-available/ 目錄檔案}}}
此目錄存放 Apache 2 可使用的功能模組, [[完整模組說明 (Module Index)|http://httpd.apache.org/docs/2.0/mod/#D]]
{{{
$ ls /etc/apache2/mods-available/
actions.conf          cache.load         filter.load          proxy_http.load
actions.load          cern_meta.load     headers.load         proxy.load
alias.conf            cgid.conf          ident.load           proxy_scgi.load
alias.load            cgid.load          imagemap.load        reqtimeout.conf
asis.load             cgi.load           include.load         reqtimeout.load
auth_basic.load       charset_lite.load  info.conf            rewrite.load
auth_digest.load      dav_fs.conf        info.load            setenvif.conf
authn_alias.load      dav_fs.load        ldap.load            setenvif.load
authn_anon.load       dav.load           log_forensic.load    speling.load
authn_dbd.load        dav_lock.load      mem_cache.conf       ssl.conf
authn_dbm.load        dbd.load           mem_cache.load       ssl.load
authn_default.load    deflate.conf       mime.conf            status.conf
authn_file.load       deflate.load       mime.load            status.load
authnz_ldap.load      dir.conf           mime_magic.conf      substitute.load
authz_dbm.load        dir.load           mime_magic.load      suexec.load
authz_default.load    disk_cache.conf    negotiation.conf     unique_id.load
authz_groupfile.load  disk_cache.load    negotiation.load     userdir.conf
authz_host.load       dump_io.load       proxy_ajp.load       userdir.load
authz_owner.load      env.load           proxy_balancer.load  usertrack.load
authz_user.load       expires.load       proxy.conf           version.load
autoindex.conf        ext_filter.load    proxy_connect.load   vhost_alias.load
autoindex.load        file_cache.load    proxy_ftp.load
}}}

{{item1{列出 /etc/apache2/mods-enabled/ 目錄檔案}}}
此目錄存放 Apache 2 已啟動的模組, 大都以連接檔格式存在
{{{
$ ls /etc/apache2/mods-enabled/
alias.conf            autoindex.conf  env.load          setenvif.load
alias.load            autoindex.load  mime.conf         status.conf
auth_basic.load       cgid.conf       mime.load         status.load
authn_file.load       cgid.load       negotiation.conf  userdir.conf
authz_default.load    deflate.conf    negotiation.load  userdir.load
authz_groupfile.load  deflate.load    reqtimeout.conf
authz_host.load       dir.conf        reqtimeout.load
authz_user.load       dir.load        setenvif.conf
}}}

<<toBalaNotes "module">>

///%module
//%/


{{item1{網路設備基礎知識]}}}

''1.Hub(集線器)''

在星狀拓樸網路(star topology)中,扮演連接或重新建立訊號的角色,可擴大類比或者是數位訊號。在區域網路(LAN)中,電腦與電腦利用網路連接時,如果用Hub 連接,即使有任何一段線路出問題,只會有一台電腦無法運作,不會影響網路中其他電腦的作業。在接收封包(Packet)進來之後,會將這個封包送到其它所有的電腦(即廣播,每一台電腦都會收到該封包),不管誰才是應該收到該封包的電腦。

''2.Bridge(橋接器)''

Bridge是一個用來連接不同的網路區段(segment)的設備,例如﹐可以用一個 bridge 來連接兩個 Ethernet segment、或連接一個 Token Ring segment 到一個 Ethernet segment。其主要功能在於決定是否讓資料訊框(Frame)通過Bridge 到另一端網路上,當Bridge 接收到訊框後,會將訊框目的地的MAC 位址與Bridge 的table 做比對,如果table 中能找到符合的位址,則進一步確認封包與目的地電腦是否為同一區段網路,若是的話,目的地電腦不需透過Bridge 就能收到資料(發揮filter功能);如果不是的話,Bridge 就會把訊框傳至目的地的電腦所在區段網路(發揮forward功能)。
@@color:red;P.S:雖然Bridge被用來分割網路,但是它們並不會隔離廣播或多點傳播的封包。@@

''3.Switch(交換器)''

Switch 的作用是在區域網路中,將網路作連接的動作。Switch 有一個table,記錄著每一台電腦的MAC 位址,當封包進來之後,Switch 會去檢查該封包的目的地的是哪一個MAC 位址的電腦,只將這個封包送給該台電腦,其他電腦則不會收到封包。
Switch的傳輸方式
(1). Cut Through:接收到目的地址後即轉發出去。延時小,但壞的資料一樣轉發。
(2). Store-and-Forward:接收到完整的資料包後,校驗好壞,好的轉發,壞的丟棄重發。傳輸可靠,但延時較長。
(3). Fragment free:接收到資料包後,大於64bytes的轉發,小於64bytes的丟棄。好壞介於上述兩種方式之間。

''4.Router(路由器)''[
路由器是用來將網路的資訊, 使用在電腦之間傳送的基本設備, 路由器的工作在於 OSI 模式第三層(網路層),用來決定資料傳遞路徑的設備. 我們使用的IP協定就是藉由路由器將不同的IP位址連接在一起. 網路上的資料分成一段一段的封包packet, 而這些封包要指向何處便是由路由器來決定的, 路由器會根據資料的目的地, 指示正確的方向, 計算評估最便捷有效率的路徑來傳輸資料, 也就是說路由器要為封包做最佳化的工作, 找出最適當的路徑. 路由器通常最少會有兩個介面, 而這兩個介面分別區隔不同的IP網段. 例如IP分享器有WAN和LAN兩種介面, 區隔WAN的實際IP與LAN的虛擬IP網段.

Router 與 Bridge 的另一個不同點在於:
Bridge 只是單純做為一個決定是否讓封包通過的橋樑,Router 則會執行選徑功能(OSPF,EIGRP,...etc.)。

<<toBalaNotes "1">>
{{item1{啟動封包轉遞}}}
{{{
# sudo nano  /etc/sysctl.conf
net/ipv4/ip_forward=1
}}}

{{item1{設定 Routing Table}}}
{{{
# sudo nano /etc/rc.local
route  add  -net  192.168.200.0  netmask  255.255.255.0  gw  192.168.0.165

# sudo  /etc/init.d/networking  restart
}}}
<<toBalaNotes "router">>

{{item1{Add a Static route using “route” command}}}
{{{
route add [-net|-host] <IP/Net> netmask <Mask> gw <Gateway IP> dev <Int>X
}}}
{{op1{Example}}}
{{{
route add -net 10.10.10.0 netmask 255.255.255.0 gw 192.168.1.1 dev eth0
route add -host 10.10.1.1 netmask 255.255.255.0 gw 192.168.1.1 dev eth0
}}}
This adds the route immediatly to the Kernel IP routing table. To confirm the route has been successfully, simply type the “route” command with no arguements:

{{op1{列印 Routing Table}}}
to print the Kernel IP Routing table.
{{{
# netstat -rn
}}}

{{op1{Kernel IP routing table}}}
{{{
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.1.254 * 255.255.255.0 U 0 0 0 eth0
localnet * 255.255.255.0 U 0 0 0 eth0
10.10.10.0 * 255.255.255.0 U 0 0 0 eth0
10.10.1.1 * 255.255.255.0 U 0 0 0 eth0
default 192.168.1.1 0.0.0.0 UG 0 0 0 eth0
}}}

To keep the Static Route persistent or you want to add the route entries to the network script files (not using the route command) then all you need to do is to edit the file
{{{
/etc/network/interfaces
}}}
and the static routes in the following format:
{{{
    up route add [-net|-host] <host/net>/<mask> gw <host/IP> dev <Interface>
}}}
''Example''
{{{
up route add -net 172.20.11.0/16 gw 172.20.10.254 dev eth1
}}}
And the file will like the following
{{{
sudo cat /etc/network/interfaces
}}}
The output should show something like this
{{{
sudo cat /etc/network/interfaces
}}}
The output should show something like this
{{{
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto eth0 eth1

iface eth0 inet static
address 192.168.1.2
netmask 255.255.255.0
network 192.168.1.0
broadcast 192.168.1.255
gateway 192.168.1.254
up route add -net 172.20.11.0/16 gw 172.20.10.254 dev eth1
}}}

iface eth1 inet static
address 172.20.10.1
netmask 255.255.255.0
broadcast 172.20.10.255
gateway 172.20.10.254

# static route
up route add -net 172.20.11.0/16 gw 172.20.10.254 dev eth1

The above has 2 Ethernet interfaces and the static route is added to the interface eth1.

For the change to /etc/network/interface to take effect. please restart the “networking” service as follows:

sudo /etc/init.d/networking restart

NOTE: If you added the route already using the “route” then there is no need to restart the networking service because, the next time server is restarted this takes effect.

///%router
//%/

///%1
//%/
''參考文章''
''1. Learn Linux, 302 (Mixed environments): NetBIOS and WINS  (重要+必讀)''
http://www.ibm.com/developerworks/linux/library/l-lpic3-314-2/
2. Linux virtualisation performance metrics domain agent
http://manpages.ubuntu.com/manpages/natty/en/man1/pmdasamba.1.html

{{item1{開始安裝}}}

''$ sudo apt-get install samba''
{{{
正在讀取套件清單... 完成
正在重建相依關係
正在讀取狀態資料... 完成
下列的額外套件將被安裝:
  libavahi-client3 libcups2 libfile-copy-recursive-perl libtalloc2
  libwbclient0 samba-common samba-common-bin update-inetd
建議套件:
  cups-common openbsd-inetd inet-superserver smbldap-tools ldb-tools
下列【新】套件將會被安裝:
  libavahi-client3 libcups2 libfile-copy-recursive-perl libtalloc2
  libwbclient0 samba samba-common samba-common-bin update-inetd
升級 0 個,新安裝 9 個,移除 0 個,有 3 個未被升級。
需要下載 11.9MB 的套件檔。
此操作完成之後,會多佔用 32.5MB 的磁碟空間。
是否繼續進行 [Y/n]?y
}}}

{{item1{檢視 daemon}}}

''$ pstree''
{{{
init─┬─cron
     ├─4*[getty]
     ├─login───bash───pstree
     ├─nmbd
     ├─rsyslogd───3*[{rsyslogd}]
     ├─smbd───smbd
     ├─sshd
     ├─udevd
     ├─upstart-socket-
     └─upstart-udev-br
}}}

{{item1{檢視 Port}}}
{{{
$ sudo netstat -lnp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:139             0.0.0.0:*               LISTEN      1731/smbd
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      806/sshd
tcp        0      0 0.0.0.0:445             0.0.0.0:*               LISTEN      1731/smbd
tcp6       0      0 :::22                   :::*                    LISTEN      806/sshd
udp        0      0 0.0.0.0:5353            0.0.0.0:*                           639/avahi-daemon: r
udp        0      0 0.0.0.0:52657           0.0.0.0:*                           639/avahi-daemon: r
udp        0      0 0.0.0.0:68              0.0.0.0:*                           706/dhclient3
                           :
}}}

{{item1{重新啟動系統}}}
{{{
$ sudo reboot
}}}

{{item1{檢視 Netbios 主機資訊}}}

''安裝 nbtscan 套件''
{{{
$ sudo apt-get install nbtscan 
}}}

''[註]'' nbtscan 命令只會檢視有 SMB 通訊協定的主機, 所有微軟視窗系統均有提供 SMB  通訊協定 (可得知 MAC 位址), Linux 系統必須要安裝 SAMBA, 才會提供 SMB  通訊協定 (無法得知 MAC 位址)

''To query netbios info from a specific IP''
{{{
$ nbtscan 192.168.56.1
Doing NBT name scan for addresses from 192.168.56.1

IP address       NetBIOS Name     Server    User             MAC address
------------------------------------------------------------------------------
192.168.56.1     SKYDODO          <server>  <unknown>        00:50:56:c0:00:08
}}}

''To query the entire LAN''
{{{
$ nbtscan 192.168.56.0/24
Doing NBT name scan for addresses from 192.168.56.0/24

IP address       NetBIOS Name     Server    User             MAC address
------------------------------------------------------------------------------
192.168.56.0    Sendto failed: Permission denied
192.168.56.1     SKYDODO          <server>  <unknown>        00:50:56:c0:00:08
192.168.56.255  Sendto failed: Permission denied
}}}

By doing this, you are actually also checking who is connecting the LAN, this is useful to check also whether there are any “unwelcome” visitor login to your WLAN. You can also check whether your boss is still at the office or not. Given that your boss must shutdown the PC before going back or your boss uses laptop.

To query for more detail on a specific IP, it gives you more info.(有包含是不是 Master Browser)
{{{
$ nbtscan -vh 192.168.56.1
Doing NBT name scan for addresses from 192.168.56.1

NetBIOS Name Table for Host 192.168.56.1:

Name             Service          Type
----------------------------------------
SKYDODO          Workstation Service
WORKGROUP        Domain Name
SKYDODO          File Server Service
WORKGROUP        Browser Service Elections
WORKGROUP        Master Browser
__MSBROWSE__  Master Browser      #  這筆資料指出這部電腦是 Master Browser

Adapter address: 00:50:56:c0:00:08     # 還可以得到 MAC 位址
----------------------------------------
}}}

''如要查詢此網段, 有多少工作群組 ?, 以及其 Master Browser ? , 請執行以下命令 ''
{{{
$ nbtscan -vh 10.0.3.0/24
Doing NBT name scan for addresses from 10.0.3.0/24

10.0.3.0	Sendto failed: Permission denied

NetBIOS Name Table for Host 10.0.3.6:

Incomplete packet, 281 bytes long.
Name             Service          Type             
----------------------------------------
IT100FS          Workstation Service
IT100FS          Messenger Service
IT100FS          File Server Service
IT100FS          Workstation Service
IT100FS          Messenger Service
IT100FS          File Server Service
IT100            Browser Service Elections
IT100            Domain Name
IT100            Browser Service Elections
IT100            Domain Name

Adapter address: 00:00:00:00:00:00
----------------------------------------

NetBIOS Name Table for Host 10.0.3.5:

Incomplete packet, 335 bytes long.
Name             Service          Type             
----------------------------------------
IT100MB          Workstation Service
IT100MB          Messenger Service
IT100MB          File Server Service
IT100MB          Workstation Service
IT100MB          Messenger Service
IT100MB          File Server Service
__MSBROWSE__  Master Browser
IT100            Master Browser
IT100            Browser Service Elections
IT100            Domain Name
IT100            Master Browser
IT100            Browser Service Elections
IT100            Domain Name

Adapter address: 00:00:00:00:00:00
----------------------------------------
10.0.3.255	Sendto failed: Permission denied
}}}

{{item1{關閉 Windows 系統的 NetBIOS 名稱系統}}}

[img[img/disableNetBIOS2win.png]]

''再執行一次 nbtscan''
{{{
$ nbtscan -vh 192.168.56.1
Doing NBT name scan for addresses from 192.168.56.1      # 看不到任何資訊
}}}

{{item1{A Multi-Homed Server}}}
Let's assume that we have a server with two network interfaces. Say that one interface, eth0 connects to the company network 10.0.0.0/8, and eth1 connects to 192.168.1.0/24, a small private network within the company. For one reason or another, we want shares exported by Samba to be available on the private network eth1, but not visible to the rest of the organisation via eth0. The machine in question is may be a firewall, gateway or plays some other sensitive role. In other configurations, you might want to avoid SMB connections over your PPP or wireless connection, for performance reasons.

The relevant ''smb.conf'' parameters here are both global parameters. They are interfaces and bind interfaces only. From the manual page for smb.conf, we find the following documentation:

{{op1{interfaces (G)}}}
This option allows you to override the default network interfaces list that Samba will use for browsing, name registration and other NBT traffic. By default Samba will query the kernel for the list of all active interfaces and use any interfaces except 127.0.0.1 that are broadcast capable.

{{op1{bind interfaces only (G)}}}
This global parameter allows the Samba admin to limit what interfaces on a machine will serve SMB requests. It affects file service smbd and name service nmbd in a slightly different ways.

(The two parameters kind of overlap a bit, I think. I don't see why it should be necessary to specify bind interfaces only if you have already specified something for the interfaces parameter. One implies the other).

Anyway, if you read the rest of the documentation for these parameters you will discover the gory details about the operation of these two parameters. Some of these details are important, and we'll touch on them later on.
Configuration changes

OK let's set some appropriate values for interfaces and bind interfaces only to the smb.conf for our server described above.
{{{
[global]
    interfaces = eth1 lo
    bind interfaces only = yes
}}}
Don't forget to ''restart Samba'' after making these changes. Sending smbd and nmbd a SIGHUP isn't sufficient in this case.

<<toBalaNotes "sambas">>


///%sambas
//%/
{{op1{下載 Tomcat}}}

[img[img/tomcat/downloadtomcat6.png]]

{{op1{安裝 Tomcat}}}
{{{
tobala@tobalaking:/$ cd /opt
tobala@tobalaking:/opt$ sudo unzip /home/tobala//home/tobala/apache-tomcat-6.0.20.zip
                                         :
  inflating: apache-tomcat-6.0.20/webapps/examples/jsp/chat/chat.jsp.html
  inflating: apache-tomcat-6.0.20/webapps/examples/jsp/chat/login.jsp
  inflating: apache-tomcat-6.0.20/webapps/examples/jsp/chat/login.jsp.html
  inflating: apache-tomcat-6.0.20/webapps/examples/jsp/chat/post.jsp
  inflating: apache-tomcat-6.0.20/webapps/examples/jsp/chat/post.jsp.html
  inflating: apache-tomcat-6.0.20/webapps/examples/jsp/checkbox/CheckTest.html
                                                        :
tobala@tobalaking:/opt$
}}}

{{op1{設定 Tomcat 啟動及關閉程序檔 (*.sh)}}}
{{{
tobala@tobalaking:/opt$ cd apache-tomcat-6.0.20/bin/
tobala@tobalaking:/opt/apache-tomcat-6.0.20/bin$ sudo chmod +x *.sh
tobala@tobalaking:/opt/apache-tomcat-6.0.20/bin$ ls -l *.sh
-rwxr-xr-x 1 root root 13573 2009-05-14 01:15 catalina.sh
-rwxr-xr-x 1 root root  1624 2009-05-14 01:15 digest.sh
-rwxr-xr-x 1 root root  4556 2009-05-14 01:15 setclasspath.sh
-rwxr-xr-x 1 root root  1563 2009-05-14 01:15 shutdown.sh
-rwxr-xr-x 1 root root  1956 2009-05-14 01:15 startup.sh
-rwxr-xr-x 1 root root  3291 2009-05-14 01:15 tool-wrapper.sh
-rwxr-xr-x 1 root root  1567 2009-05-14 01:15 version.sh
tobala@tobalaking:/opt/apache-tomcat-6.0.20/bin$
}}}
<<toBalaNotes "tomcatinstall">>


///%tomcatinstall
//%/
''參考文章''
1. How to Set up the Firewall Using UFW On Ubuntu 10.04 Lucid Lynx Server
http://1000umbrellas.com/2010/04/29/how-to-set-up-the-firewall-using-ufw-on-ubuntu-lucid-lynx-server
2. Ubuntu 12.04 LTS Precise Pangolin: Building a Firewall.
http://www.sitepoint.com/ubuntu-12-04-lts-precise-pangolin-building-a-firewall/
3. Private Subnet with Ubuntu as Router
http://blog.philippklaus.de/blog/2011/01/20/private-subnet-with-ubuntu-as-router/


Create a tool for host-based iptables firewall configuration. This tool should provide an easy to use interface to the user, as well as support package integration and dynamic-detection of open ports.

{{op1{Install UFW in Ubuntu}}}
Currently this firewall package is available in Ubuntu 8.04
{{{
sudo apt-get install ufw
}}}
''[重點]'' Ubuntu 10.04 版, 已內建 ufw 套件, 只是沒有啟動

{{item1{第一次使用}}}
''1. 檢視 ufw 執行狀態''
{{{
$ sudo ufw status
状态:不活动
}}}

''2. 啟動 ufw''
{{{
$ sudo ufw enable
Firewall is active and enabled on system startup
}}}

''[注意]'' 上面命令一執行完成, ssh 連線就會中斷

''3. 再一次檢視 ufw 執行狀態''
{{{
$sudo ufw status verbose
Status : active
Logging : on (low)
Default : deny (incoming), allow (outgoing)
New Profiles : skip
}}}

''4. 開啟 Port 22''
{{{
$ sudo ufw allow 22
Rule added
}}}

''5. 再一次檢視 ufw 執行狀態''
{{{
$ sudo ufw status verbose
Status: active
正在记录日志: on (low)
Default: deny (incoming), allow (outgoing)
新建配置文件: skip

至                          动作          来自
-                          --          --
22                         ALLOW IN    Anywhere
}}}

{{item1{應用伺服與 ufw}}}
UFW also has a list of application presets, for common servers such as Apache, OpenSSH, Lighttpd, and Samba. You can view the list by issuing the command:
{{{
$ sudo ufw app list
Available applications:
  Apache
  Apache Full
  Apache Secure
  CUPS
  OpenSSH
  Postfix
  Postfix Submission
  Samba
}}}

You can implement firewall rules for Samba and Lighttpd by using the commands below, which specify the application name, not the service name. Note that you must enclose in quotation marks any application names that include spaces.
{{{
$ sudo ufw allow Samba
}}}
It’s better to limit Samba access to hosts on your LAN. Using ufw’s more complex syntax, you can do just that. Note that you have to add “app” before the application name in this case.
{{{
$ sudo ufw allow from 10.0.0.0/8 to 140.137.214.33 app Samba
$ sudo ufw allow to 10.0.0.0/8 from 140.137.214.33 app Samba
}}}
The following commands open the ports required by my Transmission-Daemon server. Here I must specify port numbers explicitly. Note that you use a colon instead of a dash to specify port ranges. Plus, when creating rules for port ranges, you must specify whether they apply to TCP or UDP.
{{{
$ sudo ufw allow 9091
$ sudo ufw allow 20500:20599/tcp
$ sudo ufw allow 20500:20599/udp
}}}
The following command opens up ports needed for MySQL, but only to hosts within the local network.
{{{
$ sudo ufw allow from 10.0.0.0/8 to any port 3306/tcp
}}}
If you wish to open up MySQL to the world, you could use a simpler syntax.
{{{
$ sudo ufw allow mysql
}}}

{{item1{Deleting Rules}}}
Deleting rules is pretty simple. Just use the following syntax, and replace <…> with the entire rule that you wish to delete.
{{{
$ sudo ufw delete <...>
}}}
For example:
{{{
$ sudo ufw delete allow ssh
$ sudo ufw delete allow 10000
}}}
You can also delete all the rules with a single command.
{{{
$ sudo ufw reset
}}}

<<toBalaNotes "ufw01">>

{{item1{How to add an iptables rule that UFW can't create}}}
網址 : http://serverfault.com/questions/198398/ubuntu-how-to-add-an-iptables-rule-that-ufw-cant-create

According to this Ubuntu wiki page (scroll down to "Advanced Functionality"), you can achieve what you want by putting your own iptables rules into the following files:
{{{
* /etc/ufw/before.rules
* /etc/ufw/after.rules
}}}
The before file is evaluated before any ufw rules are applied; the after file is evaluated after. (There are also corresponding before6 and after6 rules files, for your ip6tables rules.)

These rules files are expected to be in iptables-restore-compatible syntax, presumably because ufw simply loads them using iptables-restore. Finally, note that you need to stop and restart ufw after you make any changes to the rules files.





///%ufw01
//%/
<<forEachTiddler 
 where
   'tiddler.tags.contains("toBala")'
>>
''參考文章''
1. Quick and easy pop or imap server with Dovecot
http://www.ghacks.net/2010/02/25/quick-and-easy-pop-or-imap-server-with-dovecot/

Dovecot is a Mail Delivery Agent, written with security primarily in mind. It supports the major mailbox formats: mbox or Maildir. This section explain how to set it up as an imap or pop3 server. 

{{item1{安裝 Dovecot}}}
{{{
$ sudo apt-get install dovecot-pop3d
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following extra packages will be installed:
  dovecot-common libmysqlclient16 libpq5 mysql-common
Suggested packages:
  ntp
The following NEW packages will be installed:
  dovecot-common dovecot-imapd dovecot-pop3d libmysqlclient16 libpq5
  mysql-common
0 upgraded, 6 newly installed, 0 to remove and 0 not upgraded.
Need to get 9,551kB of archives.
After this operation, 19.5MB of additional disk space will be used.
Do you want to continue [Y/n]? 
}}}

{{item1{設定 Dovecot}}}
''1. nano /etc/dovecot/dovecot.conf''
{{{
# A config file can also tried to be included without giving an error if
# it's not found:
!include_try local.conf

# 加入以下三行
mail_location = maildir:~/maildir
disable_plaintext_auth = no
ssl = no
}}}

''2. 重新啟動 Dovecot'''
{{{
sudo /etc/init.d/dovecot restart
}}}

''3. 測試 Dovecot''
{{{
bhuvan@rainbow:~$ telnet localhost pop3
Trying 127.0.0.1...
Connected to localhost.localdomain.
Escape character is '^]'.
+OK Dovecot ready.

quit
Connection closed by foreign host.
}}}
<<toBalaNotes "dovecot">>

{{item1{Outlook Express}}}

[img[img/linux/mail/OutlookExpress.png]]


///%dovecot
//%/
''參考文章''
1. How to set up a dhcp server on Ubuntu Server 12.04 LTS
http://comtech247.net/2012/05/01/how-to-set-up-a-dhcp-server-on-ubuntu-server-12-04-lts/
2. Pushing static routes with ISC DHCP server
http://www.j-schmitz.net/blog/pushing-static-routes-with-isc-dhcp-server

{{item1{取消 VMWare HOST Only 網段 (VM Workstation) 的 DHCP 服務}}}

[img[img/linux/disableVMDHCP.png]]

{{item1{手動設定 DHCP 服務主機的 IP 位址 (一定要作)}}}
{{{
# sudo  nano  /etc/network/interfaces
                        :
iface  eth1  inet  static
      address  192.168.233.6
      netmask  255.255.255.0
      gateway  192.168.233.254
      dns-nameservers  168.95.1.1
}}}

''[註]'' 上面設定的 IP 位址, 從 HOST Only (VM Workstation) 所設定的 Subnet 中選出

{{item1{安裝 DHCP 服務}}}
Ubuntu 本文網址 : https://help.ubuntu.com/12.04/serverguide/dhcp.html

{{{
student@mygw:~$ sudo apt-get install isc-dhcp-server
Reading package lists... Done
Building dependency tree
Reading state information... Done
Suggested packages:
  isc-dhcp-server-ldap apparmor
The following NEW packages will be installed:
  isc-dhcp-server
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 429 kB of archives.
After this operation, 1005 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu/ precise-updates/main isc-dhcp-server amd64 4.1.ESV-R4-0ubuntu5.2 [429 kB]
Fetched 429 kB in 7s (55.9 kB/s)
Preconfiguring packages ...
Selecting previously unselected package isc-dhcp-server.
(Reading database ... 12216 files and directories currently installed.)
Unpacking isc-dhcp-server (from .../isc-dhcp-server_4.1.ESV-R4-0ubuntu5.2_amd64.deb) ...
Processing triggers for ureadahead ...
Setting up isc-dhcp-server (4.1.ESV-R4-0ubuntu5.2) ...
Generating /etc/default/isc-dhcp-server...
isc-dhcp-server start/running, process 447
isc-dhcp-server6 stop/pre-start, process 500
}}}

''DHCP Server 無法正常啟動, 原因如下 :   (因為還沒設定)''
{{{
student@mygw:~$ sudo tail /var/log/syslog
Aug 26 15:52:00 localhost dhcpd:
Aug 26 15:52:00 localhost dhcpd:
Aug 26 15:52:00 localhost dhcpd: No subnet declaration for eth1 (192.168.1.103).
Aug 26 15:52:00 localhost dhcpd: ** Ignoring requests on eth1.  If this is not what
Aug 26 15:52:00 localhost dhcpd:    you want, please write a subnet declaration
Aug 26 15:52:00 localhost dhcpd:    in your dhcpd.conf file for the network segment
Aug 26 15:52:00 localhost dhcpd:    to which interface eth1 is attached. **
Aug 26 15:52:00 localhost dhcpd:
Aug 26 15:52:00 localhost dhcpd:
Aug 26 15:52:00 localhost dhcpd: Not configured to listen on any interfaces!
}}}

You will probably need to change the default configuration by editing ''/etc/dhcp3/dhcpd.conf'' to suit your needs and particular configuration. 

{{item1{指定服務網卡}}}
You also need to edit ''/etc/default/dhcp3-server'' to specify the interfaces dhcpd should listen to. 
{{{
student@mygw:~$ sudo nano /etc/default/isc-dhcp-server
# Defaults for dhcp initscript
# sourced by /etc/init.d/dhcp
# installed at /etc/default/isc-dhcp-server by the maintainer scripts

#
# This is a POSIX shell fragment
#

# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
#       Separate multiple interfaces with spaces, e.g. "eth0 eth1".
INTERFACES="eth0"
}}}

{{item1{DHCP 服務簡易設定}}}
"/etc/dhcp3/dhcpd.conf" 設定檔中, 一定要包含此 DHCP Server 所連接 LAN 的 subnet 設定, 這樣 DHCP Server 才會啟動. 

''1. 編輯 DHCP 設定檔''
{{{
student@mygw:~$ sudo nano /etc/dhcp/dhcpd.conf
                             :
subnet 10.0.3.0 netmask 255.255.255.0 {
   range 10.0.3.50 10.0.3.127;
}
}}}

''2. 重新啟動 DHCP Server''
{{{
student@mygw:~$ sudo service isc-dhcp-server restart
stop: Unknown instance:                                                 # 因第一次啟動
isc-dhcp-server start/running, process 614
}}}

''3. 檢視系統資訊''
{{{
student@mygw:~$ sudo tail /var/log/syslog
Aug 26 16:08:49 localhost dhcpd: Wrote 0 leases to leases file.
Aug 26 16:08:58 localhost dhcpd: Internet Systems Consortium DHCP Server 4.1-ESV-R4
Aug 26 16:08:58 localhost dhcpd: Copyright 2004-2011 Internet Systems Consortium.
Aug 26 16:08:58 localhost dhcpd: All rights reserved.
Aug 26 16:08:58 localhost dhcpd: For info, please visit https://www.isc.org/software/dhcp/
Aug 26 16:08:58 localhost dhcpd: Internet Systems Consortium DHCP Server 4.1-ESV-R4
Aug 26 16:08:58 localhost dhcpd: Copyright 2004-2011 Internet Systems Consortium.
Aug 26 16:08:58 localhost dhcpd: All rights reserved.
Aug 26 16:08:58 localhost dhcpd: For info, please visit https://www.isc.org/software/dhcp/
Aug 26 16:08:58 localhost dhcpd: Wrote 0 leases to leases file.
}}}

''[註]'' TurnKey Core 11 版沒有提供 dhclient 命令, 請在 TurnKey 系統安裝 dhcp-client 套件, 命令如下 :
{{{
$ sudo apt-get install dhcp-client
}}}

{{item1{Making permanent changes to resolv.conf under Ubuntu}}}
After googling some more. I think i found a better way to solve this problem. And probably the only way to solve this. No need to install any extra software. 
Just edit the dhclient config file.

change the following lines in ''/etc/dhcp3/dhclient.conf''
{{{
supersede domain-name “example.com”
prepend domain-name-server xxx.xxx.xxx.1, xxx.xxx.xxx.2
}}}

{{item1{DHCP 服務進階設定 : 根據 MAC 配置 IP 位址}}}

''1. 編輯 DHCP 設定檔''
{{{
$ sudo nano  /etc/dhcp/dhcpd.conf
# Sample /etc/dhcpd.conf
# (add your comments here) 

default-lease-time 600;
max-lease-time 7200;
option subnet-mask 255.255.255.0;
option routers 192.168.1.254;
option domain-name-servers 192.168.1.1, 192.168.1.2;

subnet 192.168.1.0 netmask 255.255.255.0 {
       range 192.168.1.11 192.168.1.127;
} 

subnet  10.152.187.0 netmask 255.255.255.0 {
        option routers                  10.152.187.1;
        option subnet-mask              255.255.255.0;
        option domain-name-servers      194.168.4.100;
        option ntp-servers              10.152.187.1;
        option netbios-name-servers     10.152.187.1;
        option netbios-node-type 8;

        default-lease-time 86400;
        max-lease-time 86400;

        host mys2 {
                hardware ethernet 00:KK:HD:66:55:9B;
                fixed-address 10.152.187.2;
        }
}
}}}
This will result in the DHCP server giving a client an IP address from the range 192.168.1.10-192.168.1.100 or 192.168.1.150-192.168.1.200. It will lease an IP address for 600 seconds if the client doesn't ask for a specific time frame. Otherwise the maximum (allowed) lease will be 7200 seconds. The server will also "advise" the client that it should use 255.255.255.0 as its subnet mask, 192.168.1.255 as its broadcast address, 192.168.1.254 as the router/gateway and 192.168.1.1 and 192.168.1.2 as its DNS servers.

''2. 檢視租約資訊''
{{{
# cat /var/lib/dhcp/dhcpd.lease
}}}

[img[img/linux/dhcpserverlease.png]]

{{item1{設定 Client 端路由表}}}

{{{
student@mygw:~$ sudo nano /etc/dhcp/dhcpd.conf
                                :
option rfc3442-classless-static-routes code 121 = array of integer 8;

subnet 10.0.3.0 netmask 255.255.255.0 {
   range 10.0.3.50 10.0.3.127;
   option rfc3442-classless-static-routes 24, 192, 168, 123, 10, 0, 3,254;
}
}}}
<<toBalaNotes "1">>

{{item1{使用 TShark 取得 DHCP 封包命令}}}
{{{
$ sudo tshark -i eth0 -R 'bootp.dhcp'
}}}

{{item1{使用 WireShark 取得 DHCP 封包命令}}}
 
[img[img/linux/dhcprelaypacket.png]]

<<toBalaNotes "2">>



///%1
//%/

///%2
//%/
<<timeline>>
刪除所有匿名帳號, 然後設定 pma 帳號的密碼, 此帳號是 XAMPP phpMyAdmin 內定使用帳號, 不具建立資料庫權限, 最後產生一個備用管理帳號 (tobala)

''$ sudo ./mysql -u root -p''
{{{
[sudo] password for tobala:
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.1.37 Source distribution

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> use mysql;
Database changed
mysql> delete from user where user='';
Query OK, 2 rows affected (0.00 sec)

mysql> set password for pma@localhost=password('a$12345');
Query OK, 0 rows affected (0.00 sec)

mysql> grant all on * to tobala identified by 'tobala';
Query OK, 0 rows affected (0.00 sec)

mysql> select host,user,password from user;
+-----------+--------+-------------------------------------------+
| host      | user   | password                                  |
+-----------+--------+-------------------------------------------+
| localhost | root   |                                            |
| linux     | root   | |
| localhost | pma    |  *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B |
| %         | tobala | *7D3F1D44FA543B1B410090CE651FDBBBC1FD3C35 |
+-----------+--------+-------------------------------------------+
4 rows in set (0.00 sec)

mysql> \q
}}}
''參考文章''
1. Bandwidth Monitoring Tools for Ubuntu Users (非常完整)
http://www.ubuntugeek.com/bandwidth-monitoring-tools-for-ubuntu-users.html
2. 20 Linux System Monitoring Tools Every SysAdmin Should Know
http://www.cyberciti.biz/tips/top-linux-monitoring-tools.html

{{item1{安裝 bmon 命令}}}
{{{
sudo apt-get install bmon
}}}
This will complete the installation.

If you want to open the application you need to enter the following command
{{{
bmon
}}}
you should see the following output

[img[img/linux/bmon01.png]]

If i select the eth0 i should see all the traffic details

[img[img/linux/bmon02.png]]

<<toBalaNotes "1">>


///%1
//%/
''參考文章''
1. Forwarding ports to guests in libvirt / KVM
http://serverfault.com/questions/170079/forwarding-ports-to-guests-in-libvirt-kvm
2. 25 Most Frequently Used Linux IPTables Rules Examples (必讀)
http://www.thegeekstuff.com/2011/06/iptables-rules-examples/

{{item1{測試 NAT 功能 (暫時)}}}

''1. 啟動 NAT 功能''
{{{
$ sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
}}}

''2. 啟動封包轉遞''
{{{
$ sudo bash -c "echo 1 > /proc/sys/net/ipv4/ip_forward" 
}}}

''3. 重新啟動網路''
{{{
$ sudo /etc/init.d/networking restart
}}}

''4. 這時候只要將 Client 端的 Default Gateway 設到 NAT 主機, 就能上網了''

{{item1{如何讓主機在開機就執行 NAT 功能?}}}

''1. 啟動 NAT 功能''
在 /etc/rc.local 加入下式 :
{{{
$ nano /etc/rc.local
               :
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

exit 0
}}}

''[註]'' eth0 對外連接網路介面

''2. 啟動封包轉遞''
{{{
# sudo nano /etc/sysctl.conf
net.ipv4.ip_forward=1         (請取消此行註解)
}}}

''3. 重新啟動網路''
{{{
$ sudo /etc/init.d/networking restart
}}}

{{item1{刪除 NAT 設定}}}
{{{
$ sudo iptables -t nat -L -n --line-numbers
Chain PREROUTING (policy ACCEPT)
num  target     prot opt source               destination         

Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination         

Chain POSTROUTING (policy ACCEPT)
num  target     prot opt source               destination         
1    MASQUERADE  tcp  --  192.168.122.0/24    !192.168.122.0/24     masq ports: 1024-65535
2    MASQUERADE  udp  --  192.168.122.0/24    !192.168.122.0/24     masq ports: 1024-65535
3    MASQUERADE  all  --  192.168.122.0/24    !192.168.122.0/24    
4    MASQUERADE  all  --  172.16.10.0/24       0.0.0.0/0      
     
$ sudo iptables -t nat -D POSTROUTING 4

$ sudo iptables -t nat -L -n --line-numbers
Chain PREROUTING (policy ACCEPT)
num  target     prot opt source               destination         

Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination         

Chain POSTROUTING (policy ACCEPT)
num  target     prot opt source               destination         
1    MASQUERADE  tcp  --  192.168.122.0/24    !192.168.122.0/24     masq ports: 1024-65535
2    MASQUERADE  udp  --  192.168.122.0/24    !192.168.122.0/24     masq ports: 1024-65535
3    MASQUERADE  all  --  192.168.122.0/24    !192.168.122.0/24    
}}}

{{item1{進階應用}}}
{{{
iptables -t nat -A PREROUTING -p tcp -i ppp0 --dport 21 -j DNAT --to 192.168.1.56:21
}}}

有需要可以把他加到 /etc/rc.local 裡面,功用是將來自 internet 的 port 21 服務, 轉向到 192.168.1.56:21,而 port 是 4662,則指令如下:
{{{
iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 4662 -j DNAT --to 192.168.1.56:4662

}}}
<<toBalaNotes "MASQUERADE">>

This can be accomplished with a single iptables rule, which may differ slightly based on your network configuration:
{{{
sudo iptables -t nat -A POSTROUTING -s 192.168.0.0/16 -o ppp0 -j MASQUERADE
}}}
The above command assumes that your private address space is 192.168.0.0/16 and that your Internet-facing device is ppp0. The syntax is broken down as follows:
{{{
* -t nat -- the rule is to go into the nat table

* -A POSTROUTING -- the rule is to be appended (-A) to the POSTROUTING chain
    
* -s 192.168.0.0/16 -- the rule applies to traffic originating from the specified address space
    
* -o ppp0 -- the rule applies to traffic scheduled to be routed through the specified network device
    
* -j MASQUERADE -- traffic matching this rule is to "jump" (-j) to the MASQUERADE (偽裝) target to be manipulated as described above
}}}

Each chain in the filter table (the default table, and where most or all packet filtering occurs) has a default policy of ACCEPT, but if you are creating a firewall in addition to a gateway device, you may have set the policies to DROP or REJECT, in which case your masqueraded traffic needs to be allowed through the FORWARD chain for the above rule to work:
{{{
sudo iptables -A FORWARD -s 192.168.0.0/16 -o ppp0 -j ACCEPT
sudo iptables -A FORWARD -d 192.168.0.0/16 -m state --state ESTABLISHED,RELATED -i ppp0 -j ACCEPT
}}}

The above commands will allow all connections from your local network to the Internet and all traffic related to those connections to return to the machine that initiated them. 


///%MASQUERADE
//%/
''參考文章''
1. How to enable IP Forwarding in Linux
http://www.ducea.com/2006/08/01/how-to-enable-ip-forwarding-in-linux/

{{item1{Check if IP Forwarding is enabled}}}
We have to query the sysctl kernel value net.ipv4.ip_forward to see if forwarding is enabled or not:
Using sysctl:
{{{
$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 0
}}}
or just checking out the value in the /proc system:
{{{
$ cat /proc/sys/net/ipv4/ip_forward
0
}}}
As we can see in both the above examples this was disabled (as show by the value 0).

{{item1{啟動封包轉遞}}}
{{{
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
}}}

{{{
$ sudo nano /etc/sysctl.conf
net.ipv4.ip_forward=1         (請取消此行註解)
}}}

To enable the changes made in sysctl.conf you will need to run the command:
{{{
$ sysctl -p /etc/sysctl.conf
}}}

{{item1{設定 Routing Table}}}

''1. 新增路由表資訊''
{{{
$ sudo nano /etc/network/interfaces
    :
    :
auto eth1
iface eth1 inet static
  address 172.16.1.1
  netmask 255.255.0.0
  broadcast 172.16.255.255
  up route add -net 192.168.160.0/24 gw 172.16.1.4 dev eth1
}}}

''[注意]'' 上述設定, 務必要正確設定傳送網路介面 (dev eth1 or dev eth0)

''2. 重新啟動網路''
{{{
# sudo /etc/init.d/networking restart
}}}

''3. 檢視路由表''
{{{
$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.56.0    0.0.0.0         255.255.255.0   U     0      0        0 eth0
0.0.0.0         192.168.56.2    0.0.0.0         UG    100    0        0 eth0
}}}

''4. 刪除路由表資訊 (暫時)''
{{{
$ route del -net 192.168.100.0 netmask 255.255.255.0
}}}

<<toBalaNotes "router">>

///%router
//%/
A ''zone'' can hold the resource records for one or more contiguous domain names, connected by a direct parent-child relationship. DNS allows a ''DNS namespace to be divided into zones''. For each DNS domain name include in a zone, the zone becomes the authoritative source for information about that domain. Zone files are maintained on DNS servers. You can configure a single DNS server to host zero, one, or multiple zones.

{{item1{DNS Zone Types}}}
{{op1{1. Primary}}}
Read/write copoy of a DNS database

{{op1{2. Secondary}}}
Read-only copy of a DNS database

<<toBalaNotes "dnszone">>


///%dnszone
//%/
預設首頁放置在 /opt/lampp/htdocs 這個目錄嗎? 為什麼呢?因為 DocumentRoot 這個設定值的關係啦!此外,由於 Apache 允許 Internet 對我們的資料進行瀏覽, 所以你當然必須要針對可被瀏覽的目錄進行權限的相關設定,那就是 <Directory> 這個設定值的重要特色!先讓我們來看看預設的主網頁設定吧!

''$ sudo nano /opt/lampp/etc/httpd.conf''
{{{
DocumentRoot "/opt/lampp/htdocs"           放置首頁的目錄!
}}}
這個設定值重要到不行,因為他規範了 WWW 伺服器主網頁所放置的『目錄』所在。這個設定值是可以被隨意更動的,不過更動之後你必須要針對該目錄進行權限設定,也就是底下要講到的 Directory 這個設定值來規範目錄的權限才行喔!
{{{
<Directory />
    Options FollowSymLinks
    AllowOverride None
</Directory>
}}}

''[重要]'' 以最嚴格設定值, 設定 ''@@color:red;Linux 檔案系統根目錄 (/)@@'', 不是指網站的根目錄

{{item1{首頁目錄設定說明}}}
{{op1{1. 首頁目錄的設定內容}}}
{{{
<Directory "/opt/lampp/htdocs">
    #
    # Possible values for the Options directive are "None", "All",
    # or any combination of:
    #   Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
    #
    # Note that "MultiViews" must be named *explicitly* --- "Options All"
    # doesn't give it to you.
    #
    # The Options directive is both complicated and important.  Please see
    # http://httpd.apache.org/docs/2.2/mod/core.html#options
    # for more information.
    #
    #Options Indexes FollowSymLinks
    # XAMPP
    Options Indexes FollowSymLinks ExecCGI Includes

    #
    # AllowOverride controls what directives may be placed in .htaccess files.
    # It can be "All", "None", or any combination of the keywords:
    #   Options FileInfo AuthConfig Limit
    #
    #AllowOverride None
    # since XAMPP 1.4:
    AllowOverride All

    #
    # Controls who can get stuff from this server.
    #
    Order allow,deny
    Allow from all

</Directory>
}}}
{{op1{2. AllowOverride}}}
是否允許額外設定檔 .htaccess 的權限複寫?我們可以在 httpd.conf 內設定好所有的權限,不過如此一來若使用者自己的個人網頁想要修改權限時將會對管理員造成困擾。因此 Apache 預設可以讓使用者以目錄底下的 .htaccess 檔案內複寫 <Directory> 內的權限設定。 這個項目則是在規定 .htaccess 可以複寫的權限類型有哪些。常見的有:
{{{
* ALL:全部的權限均可被複寫;
* AuthConfig:僅有網頁認證 (帳號密碼) 可複寫;
* Indexes:僅允許 Indexes 方面的複寫;
* Limits:允許使用者利用 Allow, Deny 與 Order 管理可瀏覽的權限;
* None:不可複寫,亦即 .htaccess 檔案失效去!
}}}
{{op1{3. Order}}}
''The Order directive, along with the Allow and Deny directives, controls a @@color:red;three-pass@@ access control system''. The first pass processes either all Allow or all Deny directives, as specified by the Order directive. The second pass parses the rest of the directives (Deny or Allow). The third pass applies to all requests which do not match either of the first two.

''[註]'' that all Allow and Deny directives are processed, unlike a typical firewall, where only the first match is used. The last match is effective (also unlike a typical firewall). Allow 及 Deny 命令均要檢查, 最後一個符合條件生效

Additionally, the order in which lines appear in the configuration files is not significant -- all Allow lines are processed as one group, all Deny lines are considered as another, and the default state is considered by itself.

Ordering is one of: (以下說明一定要看)

''Allow,Deny''
First, all Allow directives are evaluated; at least one must match, or the request is rejected. Next, all Deny directives are evaluated. If any matches, the request is rejected. Last, any requests which do not match an Allow or a Deny directive are denied by default.

''Deny,Allow''
First, all Deny directives are evaluated; if any match, the request is denied unless it also matches an Allow directive. Any requests which do not match any Allow or Deny directives are permitted.

''Mutual-failure''
This order has the same effect as Order Allow,Deny and is deprecated in its favor. 

In the following example, all hosts in the apache.org domain are allowed access; all other hosts are denied access.
{{{
Order Deny,Allow
Deny from all
Allow from apache.org
}}}
In the next example, all hosts in the apache.org domain are allowed access, except for the hosts which are in the foo.apache.org subdomain, who are denied access. All hosts not in the apache.org domain are denied access because the default state is to Deny access to the server.
{{{
Order Allow,Deny
Allow from apache.org
Deny from foo.apache.org
}}}
On the other hand, if the Order in the last example is changed to Deny,Allow, all hosts will be allowed access. This happens because, regardless of the actual ordering of the directives in the configuration file, the Allow from apache.org will be evaluated last and will override the Deny from foo.apache.org. All hosts not in the apache.org domain will also be allowed access because the default state is Allow.

The presence of an Order directive can affect access to a part of the server even in the absence of accompanying Allow and Deny directives because of its effect on the default access state. For example,
{{{
<Directory /www>
   Order Allow,Deny
</Directory> 
}}}
will Deny all access to the /www directory because the default access state is set to Deny.

The Order directive controls the order of access directive processing only within each phase of the server's configuration processing. This implies, for example, that an Allow or Deny directive occurring in a <Location> section will always be evaluated after an Allow or Deny directive occurring in a <Directory> section or .htaccess file, regardless of the setting of the Order directive. For details on the merging of configuration sections, see the documentation on How Directory, Location and Files sections work.

{{op1{練習 : 限制首頁目錄的連接對象}}}
''1. 修改 /opt/lampp/etc/httpd.conf 設定檔''
{{{
                       :
<Directory "/opt/lampp/htdocs">
                                        ::
    Options Indexes FollowSymLinks ExecCGI Includes
                                        ::
    AllowOverride All
                                        ::
    Order deny,allow
    Deny from 192.168.1.1 192.168.1.2

</Directory>
}}}

''2. 重新啟動 Apache''

<<toBalaNotes "home">>
{{item1{啟動首頁目錄檔案瀏覽功能}}}

{{op1{1. Appache 根目錄設定}}}

''$ sudo nano /opt/lampp/etc/httpd.conf''
{{{
                       :
<Directory "/opt/lampp/htdocs">
    Options Indexes FollowSymLinks  <==建議拿掉 Indexes 比較妥當!
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>
}}}

__''Options 設定項目''__
表示這個目錄內能夠進行的動作,亦即是權限設定啦!主要的設定值:

'' Indexes''
如果在此目錄下找不到『首頁檔案』時, 就顯示整個目錄下的檔案名稱,『首頁檔案』與 DirectoryIndex 設定值有關。

''FollowSymLinks''
讓在此目錄下的連結檔可以連結出此目錄外。 在預設的情況下,你在 /opt/lampp/htdocs 底下的連結檔只要連結到非此目錄的其他地方,則該連結檔預設是失效的。 但使用此設定即可讓連結檔有效的離開本目錄。

''ExecCGI''
讓此目錄具有執行 CGI 程式的權限。注意,不要讓所有目錄均可使用 ExecCGI !

''Includes''
讓一些 Server-Side Include 程式可以運作。建議可以加上去!

''MultiViews''
這玩意兒有點像是多國語言的支持,與語系資料 (LanguagePriority) 有關。最常見在錯誤訊息的回報內容,在同一部主機當中, 可以依據用戶端的語系而給予不同的語言顯示呢!預設在錯誤回報訊息當中存在, 你可以檢查一下 /opt/lampp/error/ 目錄下的資料喔!

{{op1{2. 請將 /opt/lampp/htdocs目錄中的 index.php 更名為 index.xyz}}}

{{op1{3. 啟動瀏覽器, 瀏覽根目錄檔案}}}

[img[img/xampp/xampphttpd01.png]]

///%home
//%/

{{item1{檢視 apache2.conf 檔案 (必讀)}}}
{{{
$ cat /etc/apache2/apache2.conf
#
# Based upon the NCSA server configuration files originally by Rob McCool.
#
# This is the main Apache server configuration file.  It contains the
# configuration directives that give the server its instructions.
# See http://httpd.apache.org/docs/2.2/ for detailed information about
# the directives.
#
# Do NOT simply read the instructions in here without understanding
# what they do.  They're here only as hints or reminders.  If you are unsure
# consult the online docs. You have been warned.
#
# The configuration directives are grouped into three basic sections:
#  1. Directives that control the operation of the Apache server process as a
#     whole (the 'global environment').
#  2. Directives that define the parameters of the 'main' or 'default' server,
#     which responds to requests that aren't handled by a virtual host.
#     These directives also provide default values for the settings
#     of all virtual hosts.
#  3. Settings for virtual hosts, which allow Web requests to be sent to
#     different IP addresses or hostnames and have them handled by the
#     same Apache server process.
#
# Configuration and logfile names: If the filenames you specify for many
# of the server's control files begin with "/" (or "drive:/" for Win32), the
# server will use that explicit path.  If the filenames do *not* begin
# with "/", the value of ServerRoot is prepended -- so "/var/log/apache2/foo.log"
# with ServerRoot set to "" will be interpreted by the
# server as "//var/log/apache2/foo.log".
#

### Section 1: Global Environment
#
# The directives in this section affect the overall operation of Apache,
# such as the number of concurrent requests it can handle or where it
# can find its configuration files.
#

#
# ServerRoot: The top of the directory tree under which the server's
# configuration, error, and log files are kept.
#
# NOTE!  If you intend to place this on an NFS (or otherwise network)
# mounted filesystem then please read the LockFile documentation (available
# at <URL:http://httpd.apache.org/docs-2.1/mod/mpm_common.html#lockfile>);
# you will save yourself a lot of trouble.
#
# Do NOT add a slash at the end of the directory path.
#
ServerRoot "/etc/apache2"

#
# The accept serialization lock file MUST BE STORED ON A LOCAL DISK.
#
#<IfModule !mpm_winnt.c>
#<IfModule !mpm_netware.c>
LockFile /var/lock/apache2/accept.lock
#</IfModule>
#</IfModule>

#
# PidFile: The file in which the server should record its process
# identification number when it starts.
# This needs to be set in /etc/apache2/envvars
#
PidFile ${APACHE_PID_FILE}

#
# Timeout: The number of seconds before receives and sends time out.
#
Timeout 300

#
# KeepAlive: Whether or not to allow persistent connections (more than
# one request per connection). Set to "Off" to deactivate.
#
KeepAlive On

#
# MaxKeepAliveRequests: The maximum number of requests to allow
# during a persistent connection. Set to 0 to allow an unlimited amount.
# We recommend you leave this number high, for maximum performance.
#
MaxKeepAliveRequests 100

#
# KeepAliveTimeout: Number of seconds to wait for the next request from the
# same client on the same connection.
#
KeepAliveTimeout 15

##
## Server-Pool Size Regulation (MPM specific)
##

# prefork MPM
# StartServers: number of server processes to start
# MinSpareServers: minimum number of server processes which are kept spare
# MaxSpareServers: maximum number of server processes which are kept spare
# MaxClients: maximum number of server processes allowed to start
# MaxRequestsPerChild: maximum number of requests a server process serves
<IfModule mpm_prefork_module>
    StartServers          5
    MinSpareServers       5
    MaxSpareServers      10
    MaxClients          150
    MaxRequestsPerChild   0
</IfModule>

# worker MPM
# StartServers: initial number of server processes to start
# MaxClients: maximum number of simultaneous client connections
# MinSpareThreads: minimum number of worker threads which are kept spare
# MaxSpareThreads: maximum number of worker threads which are kept spare
# ThreadsPerChild: constant number of worker threads in each server process
# MaxRequestsPerChild: maximum number of requests a server process serves
<IfModule mpm_worker_module>
    StartServers          2
    MinSpareThreads      25
    MaxSpareThreads      75
    ThreadLimit          64
    ThreadsPerChild      25
    MaxClients          150
    MaxRequestsPerChild   0
</IfModule>

# event MPM
# StartServers: initial number of server processes to start
# MaxClients: maximum number of simultaneous client connections
# MinSpareThreads: minimum number of worker threads which are kept spare
# MaxSpareThreads: maximum number of worker threads which are kept spare
# ThreadsPerChild: constant number of worker threads in each server process
# MaxRequestsPerChild: maximum number of requests a server process serves
<IfModule mpm_event_module>
    StartServers          2
    MaxClients          150
    MinSpareThreads      25
    MaxSpareThreads      75
    ThreadLimit          64
    ThreadsPerChild      25
    MaxRequestsPerChild   0
</IfModule>

# These need to be set in /etc/apache2/envvars   (內定執行 CGI 程式的 User 及 Group)
User ${APACHE_RUN_USER}
Group ${APACHE_RUN_GROUP}

#
# AccessFileName: The name of the file to look for in each directory
# for additional configuration directives.  See also the AllowOverride
# directive.
#

AccessFileName .htaccess

#
# The following lines prevent .htaccess and .htpasswd files from being
# viewed by Web clients.
#
<Files ~ "^\.ht">
    Order allow,deny
    Deny from all
    Satisfy all
</Files>

#
# DefaultType is the default MIME type the server will use for a document
# if it cannot otherwise determine one, such as from filename extensions.
# If your server contains mostly text or HTML documents, "text/plain" is
# a good value.  If most of your content is binary, such as applications
# or images, you may want to use "application/octet-stream" instead to
# keep browsers from trying to display binary files as though they are
# text.
#
DefaultType text/plain

#
# HostnameLookups: Log the names of clients or just their IP addresses
# e.g., www.apache.org (on) or 204.62.129.132 (off).
# The default is off because it'd be overall better for the net if people
# had to knowingly turn this feature on, since enabling it means that
# each client request will result in AT LEAST one lookup request to the
# nameserver.
#
HostnameLookups Off

# ErrorLog: The location of the error log file.
# If you do not specify an ErrorLog directive within a <VirtualHost>
# container, error messages relating to that virtual host will be
# logged here.  If you *do* define an error logfile for a <VirtualHost>
# container, that host's errors will be logged there and not here.
#
ErrorLog /var/log/apache2/error.log

#
# LogLevel: Control the number of messages logged to the error_log.
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
#
LogLevel warn

# Include module configuration:  (會啟動 /etc/apache2/mods-enabled 目錄中所有模組)
Include /etc/apache2/mods-enabled/*.load
Include /etc/apache2/mods-enabled/*.conf

# Include all the user configurations:   (管理者主要設定檔)
Include /etc/apache2/httpd.conf

# Include ports listing
Include /etc/apache2/ports.conf

#
# The following directives define some format nicknames for use with
# a CustomLog directive (see below).
# If you are behind a reverse proxy, you might want to change %h into %{X-Forwarded-For}i
#
LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %O" common
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent

#
# Define an access log for VirtualHosts that don't define their own logfile
CustomLog /var/log/apache2/other_vhosts_access.log vhost_combined

# Include of directories ignores editors' and dpkg's backup files,
# see README.Debian for details.

# Include generic snippets of statements
Include /etc/apache2/conf.d/

# Include the virtual host configurations:
Include /etc/apache2/sites-enabled/
}}}

''@@color:red;[問題]@@'' 上述設定檔是否有設定, 網站根目錄所在的目錄 (/var/www) ?

{{item1{檢視  /etc/apache2/sites-enabled/000-default 設定檔 (網站根目錄, cgi-bin 目錄)}}}

這個設定檔, 定義 Apache 2 網站根目錄所在的目錄 (DocumentRoot /var/www), 還有定義 /cgi-bin 目錄, 執行 CGI 程式
{{{
<VirtualHost *:80>
	ServerAdmin webmaster@localhost

	DocumentRoot /var/www

	<Directory />
		Options FollowSymLinks
		AllowOverride None
	</Directory>

	<Directory /var/www/>
		Options Indexes FollowSymLinks MultiViews
		AllowOverride None
		Order allow,deny
		allow from all
	</Directory>

	ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
	<Directory "/usr/lib/cgi-bin">
		AllowOverride None
		Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
		Order allow,deny
		Allow from all
	</Directory>

	ErrorLog /var/log/apache2/error.log

	# Possible values include: debug, info, notice, warn, error, crit,
	# alert, emerg.
	LogLevel warn

	CustomLog /var/log/apache2/access.log combined

    Alias /doc/ "/usr/share/doc/"
    <Directory "/usr/share/doc/">
        Options Indexes MultiViews FollowSymLinks
        AllowOverride None
        Order deny,allow
        Deny from all
        Allow from 127.0.0.0/255.0.0.0 ::1/128
    </Directory>

</VirtualHost>
}}}

網站根目錄放置在 /var/www 這個目錄嗎? 為什麼呢?因為 DocumentRoot 這個設定值的關係啦!此外,由於 Apache 允許 Internet 對我們的資料進行瀏覽, 所以你當然必須要針對可被瀏覽的目錄進行權限的相關設定,那就是 <Directory> 這個設定值的重要特色!先讓我們來看看預設的主網頁設定吧!
{{{
DocumentRoot "/var/www"           放置首頁的目錄!
}}}
這個設定值重要到不行,因為他規範了 WWW 伺服器主網頁所放置的『目錄』所在。這個設定值是可以被隨意更動的,不過更動之後你必須要針對該目錄進行權限設定,也就是底下要講到的 Directory 這個設定值來規範目錄的權限才行喔!
{{{
<Directory />
    Options FollowSymLinks
    AllowOverride None
</Directory>
}}}
以最嚴格設定值, 設定系統根目錄 (/)

<<toBalaNotes "apache2">>


///%apache2
//%/
本文網址 : http://www.savvyadmin.com/virtualbox-wireless-bridging-with-dhcp/

DHCP Relay Agents are commonly used on routed networks with centralized DHCP services. The relay agent is a service that is typically configured on a router and converts DHCP broadcasts into unicast messages directed at the DHCP servers IP address. For more detailed explanations on the matter, check out RFC 3046 and 1542.

{{item1{Simon Kelley’s DHCP Helper (Option A)}}}
I selected to discuss Simon Kelley’s DHCP Helper first because it really is a brilliantly simple and intuitive application. The primary advantage it has over ISC’s DHCP Relay is that you do not have to configure the application with the IP address of the DHCP server. You simply tell dhcp-helper which interface on which you want it to automatically discover the dhcp server via broadcast, and it does the rest for you!

Install dhcp-helper from your repositories, or download the latest source code here.
{{{
# sudo apt-get install dhcp-helper
}}}
The service starts on installation automatically, listening on interface eth0. You’ll want to configure it in the file /etc/default/dhcp-helper. I am adding “-i wlan0” because by default it will listen on all other interfaces as well. This way, we limit the test to your Virtual guest.
{{{
DHCPHELPER_OPTS="-b wlan0 -i tap0"
}}}
Restart the service.
{{{
# sudo /etc/init.d/dhcp-helper restart
}}}
Configure your Virtual guest to use tap0 as it’s network interface, and watch it pull an IP address from your DHCP server!

{{item1{ISC’s DHCP Relay (Option B)}}}
First of all, if you would rather use ISC’s DHCP Relay, you must remove dhcp-helper discussed in the previous section. It’s not as transparent as dhcp-helper, so I’m just mentioning it here for the sake of completeness.

Ubuntu and Debian repositories provide ISC’s DHCP relay agent in the dhcp3-relay package. For other distros, check your repositories accordingly.
{{{
# sudo apt-get install dhcp3-relay
}}}
The installer will prompt you to add the IP address of your DHCP server and the interface you wish to listen on, etc. Simply leave them blank for now, as for this example, we’ll be testing things out from a command line. To test things out, run the following command from a separate terminal window, where the IP address is that of your DHCP server.
{{{
# sudo dhcrelay3 -d -i wlan0 -i tap0 192.168.1.1
}}}
Configure your VirtualBox guest to use tap0 as it’s network interface, and watch it pull an IP address from your DHCP server!
<<toBalaNotes "dhcprelay">>

{{item1{安裝與設定 ISC’s DHCP Relay}}}

''tobala@tobalaking:~$ sudo dpkg -l | grep dhcp''
{{{
ii  dhcp3-client                              3.1.1-5ubuntu8                    DHCP client
ii  dhcp3-common                          3.1.1-5ubuntu8                    common files used by all the dhcp3* packages
}}}

''tobala@tobalaking:~$ sudo apt-get install dhcp3-relay''
{{{
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
  isc-dhcp-relay
The following NEW packages will be installed:
  dhcp3-relay isc-dhcp-relay
0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
Need to get 230 kB of archives.
After this operation, 657 kB of additional disk space will be used.
Do you want to continue [Y/n]? y
}}}

[img[img/linux/dhcprelay01.png]]

''必須輸入對外及對內網卡, 對內網卡會傳送 Discover 及 Request 封包到 DHCP Server, 對外網卡會傳送 Offer 及 ACK 封包到 DHCP Client.''
 
[img[img/linux/dhcprelay02.png]]

[img[img/linux/dhcprelay03.png]]

{{op1{檢視 DHCP Relay 版本代號}}}
''tobala@tobalaking:~$ sudo dpkg -l | grep dhcp''
{{{
ii  dhcp3-client                              3.1.1-5ubuntu8                    DHCP client
ii  dhcp3-common                              3.1.1-5ubuntu8                    common files used by all the dhcp3* packages
ii  dhcp3-relay                               3.1.1-5ubuntu8                    DHCP relay daemon
}}}

{{op1{檢視 DHCP Relay 設定檔}}}
''tobala@tobalaking:~$ sudo cat /etc/default/dhcp3-relay''
{{{
# Defaults for dhcp3-relay initscript
# sourced by /etc/init.d/dhcp3-relay
# installed at /etc/default/dhcp3-relay by the maintainer scripts

#
# This is a POSIX shell fragment
#

# What servers should the DHCP relay forward requests to?
SERVERS="192.168.100.1"

# On what interfaces should the DHCP relay (dhrelay) serve DHCP requests?
INTERFACES="eth0 eth1"

# Additional options that are passed to the DHCP relay daemon?
OPTIONS=""
}}}

{{item1{移除 DHCP Relay}}}
{{{
student@mygw:~$ sudo apt-get purge dhcp3-relay
}}}

{{item1{Broadcast Relay}}}
Okay, so I’d love to take the credit for this one, but a reader from a previous post, Nick Knight, pointed me to a utility called bcrelay. Now this application is cool! It totally mitigates the need for a DHCP relay agent (so kill that process if you are running it), as bcrelay simply rewrites the layer-2 header and forwards broadcast messages between network interfaces. In the case of DHCP, the source MAC address of the packet is changed to your host machines address, but the DHCP header is untouched. So the DHCP server will still offer a brand new IP address to the guest.

Install and run the application from a separate terminal window. As a reminder, you still need to use parprouted though in another window.
{{{
sudo apt-get install bcrelay
sudo bcrelay -i tap0 -o wlan0
}}}
Configure your VirtualBox guest to use tap0 as it’s network interface, and watch it pull an IP address from your DHCP server!

{{op1{Troubleshooting}}}
If you really want to see all the action, use ''wireshark'' or ''tcpdump'' to inspect traffic. The following capture filter works well, in two separate terminals of course.
{{{
# sudo tcpdump -eni tap0 udp port 67 or udp port 68 or arp or icmp
# sudo tcpdump -eni wlan0 udp port 67 or udp port 68 or arp or icmp
}}}
Also, these commands are useful as well.
{{{
# watch -n1 route -n
# watch -n1 arp -an
}}}
If you need to figure out what is going wrong, be sure to stop all the components of the appropriate method and run them in the foreground in separate terminals. e.g. parprouted, bcrelay, dhcp-helper, dhcp3-relay. Most will give you clues as to what is failing.

Now.. I should mention, I ran into all sorts of issues when trying to get all of this to work. The methods that gave me the most trouble were the DHCP relay agents.

I have an Actiontec MI424WR router that royally screws up my DHCP relay agent’s packet exchange. I wasn’t getting any DHCP offers with unicast packets sent to the router. Apparently, during a typical non-relayed DHCP exchange, I was able to see that the router’s source MAC address was completely different in broadcast DHCP offer packets than what it’s IP address is actually associated with, so my unicast packets were probably being dropped by the router. I’m assuming this is some type of internal bridge interface dedicated for DHCP services or something, so I ended up having to install a separate DHCP server for this to work. ISC’s DHCP server worked completely normal, and I suspect this is entirely the routers fault.

{{item1{Conclusion}}}
If you do want to use this configuration regularly, I recommend the combination of parprouted and bcrelay or dhcp-helper. Both can be run in the background easily, and requires almost zero configuration if traveling between multiple networks.

However, as you have probably gathered, both methods described above are a bit complicated, and I don’t necessarily recommend it for every day use. I did it because I’m a geek, and I wanted to prove it could be done. While the process of setting up the entire environment could be made simpler with scripts, the challenges you will face on each wireless network might make the process of troubleshooting counterproductive. Many of the headaches you will face will be related to the wireless network hardware, such as centralized wireless solutions that restrict the number of MAC to IP addresses in order to prevent MITM attacks, and of course in some cases, charge you appropriately.

The best solution for public hostspots and corporate networks is still good old fashioned NAT. :-) But this way sure is is a lot of fun and a good way to waste your weekend to impress all your other nerd buddies.

///%dhcprelay
//%/
A query is a request for name resolution and is directed to a DNS server.

{{item1{查詢方式}}}
''1. Recursive''
{{{
A recursive query is a query made to a DNS server, in which the DNS client asks the DNS server to provide a complete answer to the query. The only acceptable response to a recursive query is either the full answer or a reply that the name cannot be resolved.
}}}
''2. Iterative (Root Hints)''
{{{
Iterative queries allow a DNS server to locate an authoritative DNS server through the DNS hierarchy in response to a client's request. Iterative queries are also sometimes called nonrecursive queries.
}}}

''[註]'' 上述二種查詢方式均用 UDP 53

{{item1{DNS 伺服器回應方式}}}
''1. Authoritative''
{{{
- Return the requested IP Address
- Return an authoritative "No"
}}}
''2. Nonauthoritative''
{{{
- Check its cache
- Use forwarders
- Use root hints
}}}

{{item1{設定 DNS Client}}}

''Step # 1: Open /etc/resolv.conf file:''
{{{
# nano /etc/resolv.conf
}}}

''Step #2: Add your ISP nameserver as follows:''
{{{
search isp.com
nameserver 202.54.1.110
nameserver 202.54.1.112
nameserver 202.54.1.115
}}}

''[註]'' Max. three nameserver can be used/defined at a time.

''Step # 3:Test setup nslookup or dig command:''
{{{
$ dig www.nixcraft.com

or

$ nslookup www.nixcraft.com
}}}

{{item1{dig}}}
在 unix 和 linux 下,建議大家使用 dig 命令來代替 nslookup。 dig 命令的功能比 nslookup 強大很多,不像 nslookkup 還得 set 來 set 去的,怪麻煩的。下面是 dig 的一些比較常用的命令: 

''dig 最基本的用法''
{{{
$ dig www.microsoft.com
; <<>> DiG 9.7.0-P1 <<>> www.microsoft.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 36399
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 9, ADDITIONAL: 9

;; QUESTION SECTION:
;www.microsoft.com.             IN      A

;; ANSWER SECTION:
www.microsoft.com.      2186    IN      CNAME   toggle.www.ms.akadns.net.
toggle.www.ms.akadns.net. 53    IN      CNAME   g.www.ms.akadns.net.
g.www.ms.akadns.net.    53      IN      CNAME   lb1.www.ms.akadns.net.
lb1.www.ms.akadns.net.  85      IN      A       207.46.19.254

;; AUTHORITY SECTION:
akadns.net.             43546   IN      NS      zd.akadns.org.
akadns.net.             43546   IN      NS      use3.akadns.net.
akadns.net.             43546   IN      NS      usw2.akadns.net.
akadns.net.             43546   IN      NS      eur1.akadns.net.
akadns.net.             43546   IN      NS      za.akadns.org.
akadns.net.             43546   IN      NS      zc.akadns.org.
akadns.net.             43546   IN      NS      asia9.akadns.net.
akadns.net.             43546   IN      NS      zb.akadns.org.
akadns.net.             43546   IN      NS      use4.akadns.net.

;; ADDITIONAL SECTION:
za.akadns.org.          12916   IN      A       96.6.112.198
zb.akadns.org.          12916   IN      A       64.211.42.194
zc.akadns.org.          12916   IN      A       124.40.52.133
zd.akadns.org.          12916   IN      A       72.246.46.4
eur1.akadns.net.        38392   IN      A       195.59.44.134
use3.akadns.net.        44241   IN      A       72.246.46.4
use4.akadns.net.        38306   IN      A       208.44.108.137
usw2.akadns.net.        41869   IN      A       64.211.42.194
asia9.akadns.net.       39138   IN      A       222.122.64.133

;; Query time: 96 msec
;; SERVER: 168.95.1.1#53(168.95.1.1)
;; WHEN: Tue Aug  2 22:46:54 2011
;; MSG SIZE  rcvd: 441

}}}

''查一個網域 (Domain) 的授權 DNS 伺服器''
{{{
$ dig hinet.net +nssearch
SOA hntp1.hinet.net. hostmaster.hinet.net. 201008060 3600 7200 3600000 86400 from server ans2.hinet.net in 1 ms.
SOA hntp1.hinet.net. hostmaster.hinet.net. 201008060 3600 7200 3600000 86400 from server ans1.hinet.net in 1 ms.
}}}

''從根伺服器開始追蹤一個網域名的解析過程''
在 Root Hinet 查詢, 得到的資訊是由 140.137.202.20 這部 Root DNS 所提供, 至於它的名稱, 可由 ''反向解析'' 得知

''追蹤 microsoft.com 解析過程''
{{{
$ dig microsoft.com +trace                #  微軟網域名稱

; <<>> DiG 9.7.0-P1 <<>> microsoft.com +trace
;; global options: +cmd
.                       28434   IN      NS      g.root-servers.net.
.                       28434   IN      NS      h.root-servers.net.
.                       28434   IN      NS      i.root-servers.net.
.                       28434   IN      NS      j.root-servers.net.
.                       28434   IN      NS      k.root-servers.net.
.                       28434   IN      NS      l.root-servers.net.
.                       28434   IN      NS      m.root-servers.net.
.                       28434   IN      NS      a.root-servers.net.
.                       28434   IN      NS      b.root-servers.net.
.                       28434   IN      NS      c.root-servers.net.
.                       28434   IN      NS      d.root-servers.net.
.                       28434   IN      NS      e.root-servers.net.
.                       28434   IN      NS      f.root-servers.net.
;; Received 449 bytes from 140.137.202.20#53(140.137.202.20) in 0 ms

com.                    172800  IN      NS      a.gtld-servers.net.
com.                    172800  IN      NS      b.gtld-servers.net.
com.                    172800  IN      NS      c.gtld-servers.net.
com.                    172800  IN      NS      d.gtld-servers.net.
com.                    172800  IN      NS      e.gtld-servers.net.
com.                    172800  IN      NS      f.gtld-servers.net.
com.                    172800  IN      NS      g.gtld-servers.net.
com.                    172800  IN      NS      h.gtld-servers.net.
com.                    172800  IN      NS      i.gtld-servers.net.
com.                    172800  IN      NS      j.gtld-servers.net.
com.                    172800  IN      NS      k.gtld-servers.net.
com.                    172800  IN      NS      l.gtld-servers.net.
com.                    172800  IN      NS      m.gtld-servers.net.
;; Received 494 bytes from 199.7.83.42#53(l.root-servers.net) in 138 ms

microsoft.com.          172800  IN      NS      ns1.msft.net.
microsoft.com.          172800  IN      NS      ns2.msft.net.
microsoft.com.          172800  IN      NS      ns3.msft.net.
microsoft.com.          172800  IN      NS      ns4.msft.net.
microsoft.com.          172800  IN      NS      ns5.msft.net.
;; Received 209 bytes from 192.41.162.30#53(l.gtld-servers.net) in 204 ms

microsoft.com.          3600    IN      A       207.46.197.32
microsoft.com.          3600    IN      A       207.46.232.182
;; Received 63 bytes from 65.55.226.140#53(ns5.msft.net) in 208 ms
}}}

''追蹤 sce.pccu.edu.tw 解析過程''
{{{
$ dig sce.pccu.edu.tw +trace                 #  文大網域名稱

; <<>> DiG 9.7.0-P1 <<>> sce.pccu.edu.tw +trace
;; global options: +cmd
.                       28332   IN      NS      h.root-servers.net.
.                       28332   IN      NS      i.root-servers.net.
.                       28332   IN      NS      j.root-servers.net.
.                       28332   IN      NS      k.root-servers.net.
.                       28332   IN      NS      l.root-servers.net.
.                       28332   IN      NS      m.root-servers.net.
.                       28332   IN      NS      a.root-servers.net.
.                       28332   IN      NS      b.root-servers.net.
.                       28332   IN      NS      c.root-servers.net.
.                       28332   IN      NS      d.root-servers.net.
.                       28332   IN      NS      e.root-servers.net.
.                       28332   IN      NS      f.root-servers.net.
.                       28332   IN      NS      g.root-servers.net.
;; Received 449 bytes from 140.137.202.20#53(140.137.202.20) in 0 ms

tw.                     172800  IN      NS      e.dns.tw.
tw.                     172800  IN      NS      c.dns.tw.
tw.                     172800  IN      NS      g.dns.tw.
tw.                     172800  IN      NS      b.dns.tw.
tw.                     172800  IN      NS      ns.twnic.net.
tw.                     172800  IN      NS      f.dns.tw.
tw.                     172800  IN      NS      h.dns.tw.
tw.                     172800  IN      NS      d.dns.tw.
tw.                     172800  IN      NS      a.dns.tw.
;; Received 475 bytes from 192.228.79.201#53(b.root-servers.net) in 147 ms

edu.tw.                 86400   IN      NS      b.twnic.net.tw.
edu.tw.                 86400   IN      NS      c.twnic.net.tw.
edu.tw.                 86400   IN      NS      d.twnic.net.tw.
edu.tw.                 86400   IN      NS      moevax.edu.tw.
edu.tw.                 86400   IN      NS      moemoon.edu.tw.
edu.tw.                 86400   IN      NS      moestar.edu.tw.
edu.tw.                 86400   IN      NS      a.twnic.net.tw.
;; Received 396 bytes from 210.201.138.58#53(b.dns.tw) in 1 ms

pccu.edu.tw.            86400   IN      NS      dns1.pccu.edu.tw.
pccu.edu.tw.            86400   IN      NS      dns2.pccu.edu.tw.
pccu.edu.tw.            86400   IN      NS      wombat.pccu.edu.tw.
;; Received 140 bytes from 163.28.6.21#53(moestar.edu.tw) in 0 ms

sce.pccu.edu.tw.        86400   IN      NS      dns.sce.pccu.edu.tw.
;; Received 83 bytes from 140.137.100.50#53(wombat.pccu.edu.tw) in 0 ms

sce.pccu.edu.tw.        3600    IN      A       140.137.200.241
;; Received 49 bytes from 140.137.200.20#53(dns.sce.pccu.edu.tw) in 0 ms
}}}

''用 dig 查看反向解析''
{{{
$ dig -x 168.95.1.1

; <<>> DiG 9.7.0-P1 <<>> -x 168.95.1.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30792
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;1.1.95.168.in-addr.arpa.       IN      PTR

;; ANSWER SECTION:
1.1.95.168.in-addr.arpa. 86376  IN      PTR     dns.hinet.net.

;; Query time: 0 msec
;; SERVER: 140.137.202.20#53(140.137.202.20)
;; WHEN: Sat Aug  7 19:42:31 2010
;; MSG SIZE  rcvd: 68
}}}

''[問題一]'' 請問 210.201.138.58 這部主機名稱 ?

<<toBalaNotes "dnsquery">>

{{item1{DNS Client cache}}}
''Ubuntu Desktop/Server 內定沒有啟動 DNS Client Cache'', 可由 dig 查詢資料的回應時間得知, 因每次查詢時間都一樣, 並沒有縮短. 如要啟動 DNS Client Cache, 請安裝 nscd (Name Service Cache Daemon) 套件

''Name Service Cache Daemon''
Most Microsoft DNS clients will cache the results of name resolution request to speed up multiple lookups to the same URL. Just think about how many requests are made to the same domain when visiting a single web page. Every file, image, style sheet, etc. that is on that page and served from the same domain requires a DNS lookup.

So if you have an invalid DNS entry cached on your local client you’ll need to flush it out of the cache so your client can do a new lookup and get the correct information. Or your other option is to wait until that DNS entry expires and the cache flushes it automatically… which typically takes about 24 hours.

In ubuntu if you want to flush DNS cache you need to restart nscd daemon

Install nscd using the following command
{{{
$ sudo aptitude install nscd
}}}
Flush DNS Cache in Ubuntu Using the following command
{{{
$ sudo /etc/init.d/nscd restart
}}}

''[註]'' Ubuntu Server 不需要安裝此套件, 因 DNS Server 有自己 Cache 功能, 但 Ubuntu Desktop 則建議安裝此套件, 以增加網際網路應用軟體 (Firefox, Empathy,...) 的效能

<<toBalaNotes "cc">>



///%dnsquery
//%/

///%cc
//%/

本文網址 : http://www.ubuntugeek.com/gufw-simple-gui-for-ufw-uncomplicated-firewall.html

We have already discussed how to use UFW from command line. ''Gufw'' is an easy to use Ubuntu / Linux firewall, powered by ufw.Gufw is an easy, intuitive, way to manage your Linux firewall. It supports common tasks such as allowing or blocking pre-configured, common p2p, or individual ports port(s), and many others! Gufw is powered by ufw, runs on Ubuntu, and anywhere else Python, GTK, and Ufw are available.

iptables is already a very powerful tool by itself, but it’s syntax can get awkward at times and hard to figure out, so Ubuntu developers decided to make ufw (”The reason ufw was developed is that we wanted to create a server-level firewalling utility that was a little bit more for `human beings`.”), which was to be simpler. Now, on the graphical side of things, Firestarer already existed. But why not make an even easier to use GUI for desktop `human beings`, powered by ufw? This is where Gufw comes in.

{{item1{Install Gufw in Ubuntu}}}
First you need to download latest .deb package from here .Now you should be having gufw_0.0.7c-all.deb package.You need to install this using the following command
{{{
$ sudo apt-get install gufw
}}}
This will complete the installation.

[img[img/linux/gufw.png]]

<<toBalaNotes "gufw">>


///%gufw
//%/
''參考文章''
1. howto capture and dissect network traffic
http://www.codealias.info/technotes/the_tshark_capture_and_filter_example_page
2. CaptureFilters
http://wiki.wireshark.org/CaptureFilters
3. DisplayFilters
http://wiki.wireshark.org/DisplayFilters

Wireshark 官方網址 : http://www.wireshark.org/
tshark 文件網址 : http://www.wireshark.org/docs/man-pages/tshark.html

{{item1{認識 TShark}}}
''TShark is a network protocol analyzer''. It lets you capture packet data from a live network, or read packets from a previously saved capture file, either printing a decoded form of those packets to the standard output or writing the packets to a file. ''TShark's native capture file format is libpcap format'', which is also the format used by tcpdump and various other tools.

Without any options set, TShark will work much like tcpdump. It will use the pcap library to capture traffic from the first available network interface and displays a summary line on stdout for each received packet.

TShark is able to detect, read and write the same capture files that are supported by Wireshark. The input file doesn't need a specific filename extension; the file format and an optional gzip compression will be automatically detected. Near the beginning of the DESCRIPTION section of wireshark or http://www.wireshark.org/docs/man-pages/wireshark.html is a detailed description of the way Wireshark handles this, which is the same way Tshark handles this.

Compressed file support uses (and therefore requires) the zlib library. If the zlib library is not present, TShark will compile, but will be unable to read compressed files.

If the ''-w option'' is not specified, TShark writes to the standard output the text of a decoded form of the packets it captures or reads. If the -w option is specified, TShark writes to the file specified by that option the raw data of the packets, along with the packets' time stamps.

''[註]'' 如沒使用 -w 選項, tshark 會在畫面以文字格式, 顯示封包內容, 如使用 -w 選項, 會將封包完整內容 (raw data of the packet) 寫入指定檔案

When writing a decoded form of packets, TShark writes, by default, a summary line containing the fields specified by the preferences file (which are also the fields displayed in the packet list pane in Wireshark), although if it's writing packets as it captures them, rather than writing packets from a saved capture file, it won't show the "frame number" field. If the -V option is specified, it writes instead a view of the details of the packet, showing all the fields of all protocols in the packet.

If you want to write the decoded form of packets to a file, run TShark without the -w option, and redirect its standard output to the file (do not use the -w option).

When writing packets to a file, TShark, by default, writes the file in libpcap format, and writes all of the packets it sees to the output file. The -F option can be used to specify the format in which to write the file. This list of available file formats is displayed by the -F flag without a value. However, you can't specify a file format for a live capture.

Read filters in TShark, which allow you to select which packets are to be decoded or written to a file, are very powerful; more fields are filterable in TShark than in other protocol analyzers, and the syntax you can use to create your filters is richer. As TShark progresses, expect more and more protocol fields to be allowed in read filters.

Packet capturing is performed with the pcap library. The capture filter syntax follows the rules of the pcap library. This syntax is different from the read filter syntax. A read filter can also be specified when capturing, and only packets that pass the read filter will be displayed or saved to the output file; note, however, that capture filters are much more efficient than read filters, and it may be more difficult for TShark to keep up with a busy network if a read filter is specified for a live capture.

A capture or read filter can either be specified with the -f or -R option, respectively, in which case the entire filter expression must be specified as a single argument (which means that if it contains spaces, it must be quoted), or can be specified with command-line arguments after the option arguments, in which case all the arguments after the filter arguments are treated as a filter expression. Capture filters are supported only when doing a live capture; read filters are supported when doing a live capture and when reading a capture file, but require TShark to do more work when filtering, so you might be more likely to lose packets under heavy load if you're using a read filter. If the filter is specified with command-line arguments after the option arguments, it's a capture filter if a capture is being done (i.e., if no -r option was specified) and a read filter if a capture file is being read (i.e., if a -r option was specified).

{{item1{安裝 tshark}}}
{{{
cloudwalker@oncloud9:~$ sudo apt-get install tshark
[sudo] password for cloudwalker:
正在讀取套件清單... 完成
正在重建相依關係
正在讀取狀態資料... 完成
下列的額外套件將被安裝:
  libc-ares2 libcap2-bin liblua5.1-0 libsmi2ldbl wireshark-common
建議套件:
  libcap-dev snmp-mibs-downloader
下列【新】套件將會被安裝:
  libc-ares2 libcap2-bin liblua5.1-0 libsmi2ldbl tshark wireshark-common
升級 0 個,新安裝 6 個,移除 0 個,有 17 個未被升級。
需要下載 12.2MB 的套件檔。
此操作完成之後,會多佔用 47.0MB 的磁碟空間。
是否繼續進行 [Y/n]?
}}}

{{item1{Packet Sniffing and Monitoring with Tshark}}}
WireShark Display Filter Reference (所有封包名稱) : http://www.wireshark.org/docs/dfref/

''抓取 ICMP 封包''
{{{
$ sudo tshark -i eth0 -R 'icmp'
Running as user "root" and group "oc9admin". This could be dangerous.
Capturing on eth0
  3.363754 140.137.214.252 -> 140.137.214.253 ICMP Echo (ping) request
  3.363773 140.137.214.253 -> 140.137.214.252 ICMP Echo (ping) reply
  4.362842 140.137.214.252 -> 140.137.214.253 ICMP Echo (ping) request
  4.362847 140.137.214.253 -> 140.137.214.252 ICMP Echo (ping) reply
  5.362777 140.137.214.252 -> 140.137.214.253 ICMP Echo (ping) request
  5.362781 140.137.214.253 -> 140.137.214.252 ICMP Echo (ping) reply
}}}

''[註]'' 按 ctrl + c 停止執行 tshark

''抓取 10 秒封包, 然後自動停止''
{{{
$ sudo tshark -i eth0 -a duration:10
}}}

Sniff the traffic and show it on the screen
{{{
$ sudo tshark -i eth0 -S
}}}

''[註]'' 按 ctrl + c 停止執行 tshark

Sniff 1000 packets and show it on the screen
{{{
tshark -S -c 1000
}}}

tshark can be used to dump network traffic into capture files for later processing. For this, we need to tell tshark which interface to listen to and which traffic to capture. This is an example.
{{{
$ tshark -f "udp port 1812" -i eth0 -w /tmp/capture.cap
}}}

1. The ''-f flag'' is used to specify a network capture filter (more on filters later). Packets that do not verify the condition following the -f flag will not be captured. In this example, only IP packets that are coming from or going to UDP port 1812 are captured.

2. The ''-i flag'' is used to specify the interface from which we expect to see packets. Change 'eth0' to what ever your interface name is.

3. The ''-w flag'' is used to specify a file where the captured traffic will be saved for later processing.

capture the traffic for 300 seconds and save it in output_file and exit
{{{
$ sudo tshark -a duration:300 -i eth0 -q -w /tmp/output_file
}}}

read the dumpfile 'output_file'
{{{
tshark -r output_file
}}}

read output_file and show only http connections from the ip 1.2.3.4
{{{
tshark -r output_file -R "ip.addr == 1.2.3.4 && tcp.port == 80"
}}}

Show only http GET requests from the output_file
{{{
tshark -r output_file -R "http.request.method==GET"
}}}

Show IP's mit incoming & outgoing traffic
{{{
tshark -r output_file -q -z conv,ip
}}}

Save the smtp network connection for 300 seconds and also displays realtime the connections.
{{{
tshark -w smtp-network-connections -a duration:300 -S -q -R "smtp"
}}}

IO Stats - How many packets and frames has been transfered in 60 seconds?
{{{
tshark -a duration:60 -z io,stat,60
}}}

<<toBalaNotes "tshark">>
{{item1{參數 -a <capture autostop condition>}}}

Specify a criterion that specifies when TShark is to stop writing to a capture file. The criterion is of the form test:value, where test is one of:

''duration:value'' Stop writing to a capture file after value seconds have elapsed.

''filesize:value'' Stop writing to a capture file after it reaches a size of value kilobytes (where a kilobyte is 1024 bytes). If this option is used together with the -b option, TShark will stop writing to the current capture file and switch to the next one if filesize is reached. When reading a capture file, TShark will stop reading the file after the number of bytes read exceeds this number (the complete packet will be read, so more bytes than this number may be read).

''files:value'' Stop writing to capture files after value number of files were written.

{{item1{參數 -b <capture ring buffer option>}}}

Cause TShark to run in "multiple files" mode. In "multiple files" mode, TShark will write to several capture files. When the first capture file fills up, TShark will switch writing to the next file and so on.

The created filenames are based on the filename given with the -w option, the number of the file and on the creation date and time, e.g. outfile_00001_20050604120117.pcap, outfile_00001_20050604120523.pcap, ...

With the files option it's also possible to form a "ring buffer". This will fill up new files until the number of files specified, at which point TShark will discard the data in the first file and start writing to that file and so on. If the files option is not set, new files filled up until one of the capture stop conditions match (or until the disk if full).

The criterion is of the form ''key:value'', where key is one of:

''duration:value'' switch to the next file after value seconds have elapsed, even if the current file is not completely filled up.

''filesize:value'' switch to the next file after it reaches a size of value kilobytes (where a kilobyte is 1024 bytes).

''files:value'' begin again with the first file after value number of files were written (form a ring buffer).

{{item1{Packet display rules}}}
Packet display rules or filters as their name imply, allow you to control which packets are displayed by tshark when performing live network capture or when tshark is reading a capture file. The selection criteria is specified using the -R flag and a display filter expression. This is a simple example :
{{{
tshark -R "ip.addr == 192.168.0.1" -r /tmp/capture.cap
}}}
This example displays only IP packets that are issued by or in destination to the IP address 192.168.0.1.

The filter expression can be a logical combination of other filter expressions. Here is a list of various display filters for your reference (do man wireshark-filters for more details of display filters):
|“Ethernet address 00:08:15:00:08:15”|eth.addr == 00:08:15:00:08:15|
|“Ethernet type 0×0806 (ARP)”|eth.type == 0×0806|
|“Ethernet broadcast”|eth.addr == ff:ff:ff:ff:ff:ff|
|“No ARP”|not arp|
|“IP only” |ip|
|“IP address 192.168.0.1”|ip.addr == 192.168.0.1|
|“IP address isn't 192.168.0.1, don't use != for this!”|&iexcl;(ip.addr == 192.168.0.1)|
|“IPX only” |ipx|
|“TCP only” |tcp|
|“UDP only” |udp|
|“UDP port isn't 53 (not DNS), don't use != for this!” |&iexcl;(tcp.port == 53)|
|“TCP or UDP port is 80 (HTTP)” |tcp.port == 80 &brvbar;&brvbar; udp.port == 80|
|“HTTP” |http|
|“No ARP and no DNS” |not arp and not (udp.port == 53)|
|“Non-HTTP and non-SMTP to/from 192.168.0.1”|not (tcp.port == 80) and not (tcp.port == 25) and ip.addr == 192.168.0.1|

{{{
# tshark -i eth0 -R "ip.addr == 140.137.214.254"
Running as user "root" and group "root". This could be dangerous.
Capturing on eth0
  0.248375 140.137.214.254 -> 224.0.0.9    RIPv2 Response
  0.248430 140.137.214.254 -> 224.0.0.9    RIPv2 Response
  8.459866 140.137.214.254 -> 224.0.0.13   PIMv2 Hello
  8.899398 140.137.214.254 -> 224.0.0.5    OSPF Hello Packet
 12.053389 140.137.214.254 -> 224.0.0.1    IGMP V2 Membership Query, general
 18.611548 140.137.214.254 -> 224.0.0.5    OSPF Hello Packet
}}}

{{item1{Editcap}}}
Editcap is a program that reads some or all of the captured packets from the infile, optionally converts them in various ways and writes the resulting packets to the capture outfile (or outfiles).

By default, it reads all packets from the infile and writes them to the outfile in libpcap file format.

A list of packet numbers can be specified on the command line; ranges of packet numbers can be specified as start-end, referring to all packets from start to end. The selected packets with those numbers will not be written to the capture file. If the -r flag is specified, the whole packet selection is reversed; in that case only the selected packets will be written to the capture file.

Editcap is able to detect, read and write the same capture files that are supported by Ethereal. The input file doesn't need a specific filename extension, the file format and an optional gzip compression will be automatically detected. The capture file format section of ethereal(1) or http://www.ethereal.com/docs/man-pages/ethereal.1.html provides a detailed description.

Editcap can write the file in several output formats. The -F flag can be used to specify the format in which to write the capture file, editcap -F provides a list of the available output formats.

{{op1{簡易 TShark 手冊}}}
{{{
$ tshark --help
TShark 1.2.7
Dump and analyze network traffic.
See http://www.wireshark.org for more information.

Copyright 1998-2010 Gerald Combs <gerald@wireshark.org> and contributors.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Usage: tshark [options] ...

Capture interface:
  -i <interface>           name or idx of interface (def: first non-loopback)
  -f <capture filter>      packet filter in libpcap filter syntax
  -s <snaplen>             packet snapshot length (def: 65535)
  -p                       don't capture in promiscuous mode
  -y <link type>           link layer type (def: first appropriate)
  -D                       print list of interfaces and exit
  -L                       print list of link-layer types of iface and exit

Capture stop conditions:
  -c <packet count>        stop after n packets (def: infinite)
  -a <autostop cond.> ...  duration:NUM - stop after NUM seconds
                           filesize:NUM - stop this file after NUM KB
                              files:NUM - stop after NUM files
Capture output:
  -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs
                           filesize:NUM - switch to next file after NUM KB
                              files:NUM - ringbuffer: replace after NUM files
Input file:
  -r <infile>              set the filename to read from (no pipes or stdin!)

Processing:
  -R <read filter>         packet filter in Wireshark display filter syntax
  -n                       disable all name resolutions (def: all enabled)
  -N <name resolve flags>  enable specific name resolution(s): "mntC"
  -d <layer_type>==<selector>,<decode_as_protocol> ...
                           "Decode As", see the man page for details
                           Example: tcp.port==8888,http
Output:
  -w <outfile|->           set the output filename (or '-' for stdout)
  -C <config profile>      start with specified configuration profile
  -F <output file type>    set the output file type, default is libpcap
                           an empty "-F" option will list the file types
  -V                       add output of packet tree        (Packet Details)
  -S                       display packets even when writing to a file
  -x                       add output of hex and ASCII dump (Packet Bytes)
  -T pdml|ps|psml|text|fields
                           format of text output (def: text)
  -e <field>               field to print if -Tfields selected (e.g. tcp.port);
                           this option can be repeated to print multiple fields
  -E<fieldsoption>=<value> set options for output when -Tfields selected:
     header=y|n            switch headers on and off
     separator=/t|/s|<char> select tab, space, printable character as separator
     quote=d|s|n           select double, single, no quotes for values
  -t ad|a|r|d|dd|e         output format of time stamps (def: r: rel. to first)
  -l                       flush standard output after each packet
  -q                       be more quiet on stdout (e.g. when using statistics)
  -X <key>:<value>         eXtension options, see the man page for details
  -z <statistics>          various statistics, see the man page for details

Miscellaneous:
  -h                       display this help and exit
  -v                       display version info and exit
  -o <name>:<value> ...    override preference setting
  -K <keytab>              keytab file to use for kerberos decryption
}}}

///%tshark
//%/
{{op1{1. sudo 的環境變數區}}}
/etc/profile 檔案中所設定的 JAVA_HOME 及 PATH 這二個環境變數, 不會出現在 sudo 的環境變數區中, 如下討論 :
{{{
am having a bit of a problem with setting environment variables on my web server. I need to set the following, for all users, including root.

i have added the following to /etc/profile, /etc/bash.bashrc, / root/.profile and /root/.bashrc:

export PATH=$PATH:/usr/local/java/j2sdk/bin
export JAVA_HOME=/usr/local/java/j2sdk
export CATALINA_HOME=/usr/local/java/apache-tomcat

this works fine for normal users (and for root when using su, which i had disabled), but apparently not for root (via sudo).

the output from a 'sudo env' is this:

TERM=vt100

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/ usr/X11R6/bin

LOGNAME=root
USER=root
SUDO_COMMAND=/usr/bin/env
SUDO_USER=tim
SUDO_UID=1000
SUDO_GID=1000

}}}

{{op1{2. 在執行 sudo 命令中, 以參數方式設定所需的環境變數 (JAVA_HOME)}}}

{{{
tobala@tobalaking:/opt/apache-tomcat-6.0.20/bin$ sudo JAVA_HOME=/opt/jdk1.6.0_14 ./startup.sh
Using CATALINA_BASE:   /opt/apache-tomcat-6.0.20
Using CATALINA_HOME:   /opt/apache-tomcat-6.0.20
Using CATALINA_TMPDIR: /opt/apache-tomcat-6.0.20/temp
Using JRE_HOME:       /opt/jdk1.6.0_14
tobala@tobalaking:/opt/apache-tomcat-6.0.20/bin$
}}}

{{op1{3. 檢測 Tomcat}}}
{{{
tobala@tobalaking:/opt/apache-tomcat-6.0.20/bin$ netstat -an | head -n 20
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.1:6010          0.0.0.0:*               LISTEN
tcp        0     52 192.168.200.140:22      192.168.200.1:1502      ESTABLISHED
tcp6       0      0 127.0.0.1:8005          :::*                    LISTEN
tcp6       0      0 :::8009                 :::*                    LISTEN
tcp6       0      0 :::8080                 :::*                    LISTEN
tcp6       0      0 :::22                   :::*                    LISTEN
tcp6       0      0 ::1:6010                :::*                    LISTEN
tcp6       0      0 ::1:34958               ::1:50862               TIME_WAIT
udp        0      0 0.0.0.0:68              0.0.0.0:*
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags       Type       State         I-Node   Path
unix  2      [ ]         DGRAM                    2717     @/com/ubuntu/upstart
unix  7      [ ]         DGRAM                    5702     /dev/log
unix  2      [ ACC ]     STREAM     LISTENING     6147     @/var/run/hald/dbus-GNnQmbwK9a
unix  2      [ ]         DGRAM                    2892     @/org/kernel/udev/udevd
unix  2      [ ]         DGRAM                    6191     @/org/freedesktop/hal/udev_event
unix  2      [ ACC ]     STREAM     LISTENING     6169     @/var/run/hald/dbus-BcG4WA75SB
tobala@tobalaking:/opt/apache-tomcat-6.0.20/bin$
}}}

{{op1{4. 連接網站}}}

[img[img/tomcat/tomcat01.png]]

{{op1{5. 停止執行 Tomcat}}}
{{{
tobala@tobalaking:/opt/apache-tomcat-6.0.20/bin$ sudo JAVA_HOME=/pt/jdk1.6.0_14 ./shutdown.sh
Using CATALINA_BASE:   /opt/apache-tomcat-6.0.20
Using CATALINA_HOME:   /opt/apache-tomcat-6.0.20
Using CATALINA_TMPDIR: /opt/apache-tomcat-6.0.20/temp
Using JRE_HOME:       /opt/jdk1.6.0_14
tobala@tobalaking:/opt/apache-tomcat-6.0.20/bin$
}}}

''參考文章''
1. Wireshark圖解教程(簡介、抓包、過濾器)配置 
http://wfeng520.blog.hexun.com.tw/47990031_d.html
	

For WireShark there's a better way. The bit that normally needs root is the packet collection application and this can be configured to allow certain people to use it without sudo, gksu, etc.

In a terminal (very important that you're in a terminal, not just the Alt+F2 dialogue) run this:
{{{
sudo dpkg-reconfigure wireshark-common
}}}
This will ask you if you want to allow non-root user to be able to sniff. That's what we're aiming for, so select Yes and hit return.

This adds a wireshark group. Anybody in that group will be able to sniff without being root. This is obviously more secure than just letting anybody sniff but does mean there's no password checking. Technically any person with access to a computer logged in with a wireshark account will be able to sniff. If that's acceptable to you, carry on.

If not, run that again and select no.

Then you just need to add the user to that group. Run this:
{{{
sudo adduser $USER wireshark
}}}
And restart or log out. When you're back in it should let you start sniffing without any fuss about being root.
<<toBalaNotes "1">>

///%1
//%/
{{item1{帳號設定}}}

{{op1{1. 搜尋 config.inc.php 這檔案的所在目錄}}}

''$ sudo find /opt/lampp/ -name config.inc.php''
{{{
/opt/lampp/phpmyadmin/config.inc.php
/opt/lampp/phpmyadmin/setup/frames/config.inc.php
}}}

{{op1{2. 修改 config.inc.php}}}
將 "Authentication Type and Info" 這段程式整個備註, 然後設定 pma 帳號的密碼

''$ sudo nano /opt/lampp/phpmyadmin/config.inc.php''

[img[img/xampp/xamppmysql05.png]]

{{op1{3. 重新啟動 XAMPP}}}

''$ sudo ./lampp restart''

{{item1{透過 phpMyAdmin 管理帳號}}}

{{op1{1. 勾選 帳號}}}

[img[img/xampp/xamppmysql01.png]]

{{op1{2. 設定密碼}}}

[img[img/xampp/xamppmysql02.png]]

''[注意]'' 請不要點選 "產生" 按鈕

<<toBalaNotes "xamppmysql">>




///%xamppmysql
//%/
此設定檔 (httpd-xampp.conf) 是在 /opt/lampp/etc/httpd.conf 中被 include 進來, 如下式 :
{{{
# XAMPP
Include etc/extra/httpd-xampp.conf
}}}

{{item1{設定可連接主機}}}
修改 httpd-xampp.conf 設定檔, 修改如下 :
{{{
#
# New XAMPP security concept
#
<LocationMatch "^/(?i:(?:xampp|security|licenses|phpmyadmin|webalizer|server-status|server-info))">
	Order deny,allow
	Deny from all
	Allow from ::1 127.0.0.0/8 \
		fc00::/7 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 \     內定所有私有 IP 均能連接
		fe80::/10 169.254.0.0/16 \
                140.137.217.0/24               增加此行

	ErrorDocument 403 /error/XAMPP_FORBIDDEN.html.var
</LocationMatch>
}}}

''[註]'' ::1, fc00::/7 及 fe80::/10 是 IP v6 的格式, ErrorDocument 403 /error/XAMPP_FORBIDDEN.html.var 是指不合法主機, 連接時會回傳的網頁

<<toBalaNotes "xamppweb">>
{{item1{/opt/lampp/etc/extra/httpd-xampp.conf 設定檔內容}}}
{{{
<IfDefine PHP4>
LoadModule php4_module        modules/libphp4.so
</IfDefine>
<IfDefine PHP5>
LoadModule php5_module        modules/libphp5.so
</IfDefine>
# since LAMPP 0.9.8:
LoadModule perl_module        modules/mod_perl.so

Alias /phpmyadmin "/opt/lampp/phpmyadmin"
Alias /phpsqliteadmin "/opt/lampp/phpsqliteadmin"

# since XAMPP 1.4.3
<Directory "/opt/lampp/phpmyadmin">
    AllowOverride AuthConfig Limit
    Order allow,deny
    Allow from all
</Directory>

<Directory "/opt/lampp/phpsqliteadmin">
    AllowOverride AuthConfig Limit
    Order allow,deny
    Allow from all
</Directory>

# since LAMPP 1.0RC1
AddType application/x-httpd-php .php .php3 .php4

XBitHack on

# since 0.9.8 we've mod_perl
<IfModule mod_perl.c>
        AddHandler perl-script .pl
	PerlHandler ModPerl::PerlRunPrefork
	PerlOptions +ParseHeaders
        PerlSendHeader On
</IfModule>

# demo for mod_perl responsehandler
#PerlModule Apache::CurrentTime
#<Location /time>
#      SetHandler modperl
#      PerlResponseHandler Apache::CurrentTime
#</Location>

# AcceptMutex sysvsem is default but on some systems we need this
# thanks to jeff ort for this hint
#AcceptMutex flock
#LockFile /opt/lampp/logs/accept.lock

# this makes mod_dbd happy - oswald, 02aug06
# mod_dbd doesn't work in Apache 2.2.3: getting always heaps of "glibc detected *** corrupted double-linked list" on shutdown - oswald, 10sep06
#DBDriver sqlite3

#
# New XAMPP security concept
#
<LocationMatch "^/(?i:(?:xampp|security|licenses|phpmyadmin|webalizer|server-status|server-info))">
	Order deny,allow
	Deny from all
	Allow from ::1 127.0.0.0/8 \
		fc00::/7 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 \
		fe80::/10 169.254.0.0/16

	ErrorDocument 403 /error/XAMPP_FORBIDDEN.html.var
</LocationMatch>
}}}

///%xamppweb
//%/
<<forEachTiddler 
 where
   'tiddler.tags.contains("plugin")'
>>
''參考文章''
''1. Learn Linux, 302 (Mixed environments): NetBIOS and WINS  (重要+必讀)''
http://www.ibm.com/developerworks/linux/library/l-lpic3-314-2/
2. Name Resolution and Browsing in Samba, Part 2 (主要談 Master Browser)
http://onlamp.com/pub/a/onlamp/excerpt/samba_chap7/index2.html?page=1
3. Name Resolution with Samba
http://oreilly.com/catalog/samba/chapter/book/ch07_03.html
4. Samba Network Browsing (必讀)
http://www.redhat.com/docs/manuals/enterprise/RHEL-4-Manual/ref-guide/s1-samba-network-browsing.html

{{item1{微軟網路芳鄰}}}
To keep things simple, we will first describe network browsing in a network that contains only Windows systems and then show you how to add a Samba server.

The basic way browsing works is that one computer in the network takes on the role of the master browser (also called local master browser, browse master, or browse server) and keeps a list of all the computers on the local subnet that are acting as SMB servers. The list of computers is called the browse list and includes all Samba servers, Windows NT/2000/XP systems, and any Windows 95/98/Me systems that have the "File and printer sharing for Microsoft Networks" networking component installed. The browse list also contains the names of all workgroups and domains. At this level, browsing is limited to the local subnet because the browsing protocol depends on broadcast packets, which are typically not forwarded to other subnets by routers.

A user at any ''Windows system'' can view the browse list by opening up the Network Neighborhood (or My Network Places). Or, the net view command can be used from a Windows command prompt:

''C:\>net view''
{{{
Server Name            Remark

-------------------------------------------------------------------------------
\\MAYA                 Windows 98
\\MIXTEC               Samba 2.2.5
\\OLMEC                Windows XP Pro on Pentium/ASUS
\\TOLTEC               Samba 2.2.5
\\YAQUI                Windows 95 on mixtec/VMware
\\ZAPOTEC
The command completed successfully.
}}}
Then, net view can be used with a computer name as an argument to contact a server directly and list the resources it is sharing:

''C:\>net view \\maya''
{{{
Shared resources at \\maya

Windows 98

Share name   Type         Used as  Comment

-------------------------------------------------------------------------------
D            Disk
E            Disk
HP           Print
The command completed successfully.
}}}

The computers on the network involved in browsing are more than just the master browser and its clients. There are also backup browsers, which maintain copies of the browse list and respond to client requests for it. Backup browsers are therefore able to take over the role of master browser seamlessly in case it fails. ''The master browser usually doesn't serve the browse list directly to clients. Instead, its job is mainly to keep the master copy of the browse list up-to-date, and also periodically update the backup browsers. @@color:red;Clients are expected to get their copies of the browse list from backup browsers@@, selecting among them randomly to help to distribute the load on the backup browsers more evenly.'' Ideally, the interaction between any client and the master browser is limited to the client announcing when it joins or leaves the network (if it is a server) and requesting a list of backup browsers.

There can be more than one backup browser. A workgroup will have a backup browser if two or more computers are running Windows 95/98/Me or Windows NT Workstation (or another nonserver version of Windows NT/2000/XP) on the subnet. For every 32 additional computers, another backup browser is added.

In a Windows NT domain, the primary domain controller is always the local master browser, and if it fails, another Windows NT/2000 server (if one exists) will take over the role of local master browser. Other versions of Windows can function as backup browsers, but will never become a master browser if a Windows NT/2000 server is available.

In addition to acting as the local master browser, the primary domain controller also acts as the domain master browser, which ties subnets together and allows browse lists to be shared between master and backup browsers on separate subnets. This is how browsing is extended to function beyond the local subnet. Each subnet functions as a separate browsing entity, and the domain master browser synchronizes the master browsers of each subnet. In a Windows-only network, browsing cannot function across subnets unless a Windows NT/2000 PDC exists on the network. Samba can act as a domain master browser and can perform that task even in a workgroup network, which means that the Windows PDC is not required for this task. (It is also possible to use the remote browse sync parameter to configure a Samba server to synchronize its browse list with a Samba server on another subnet. In this case, each server must be acting as the local master browser of its subnet.)

Unless it is configured never to act as a browser, each computer on the subnet is considered a potential browser and can be ordered by the browse master to become a backup browser, or it can identify itself as a backup browser and accept the role on its own.

{{item1{設定 Samba 為 Master Browser}}}
{{op1{1. 修改設定檔 (/etc/samba/smb.conf)}}}
{{{
[global]
workgroup = IT100
wins support = yes
netbios name = IT100MB
server string = IT100 Master Browser
os level = 255

domain master = no 
preferred master = yes
local master = yes

browse list = yes
dns proxy = no

# 取消印表機共享功能
printcap name = /dev/null
load printers = no
printing = bsd

name resolve order = wins hosts bcast
log file = /var/log/samba/log.%m
# 登錄檔最大僅能到多少 Kbytes ,若大於該數字,則會被 rotate 掉
max log size = 1000
syslog = 2
}}}

''Operating-system values in an election''

|Operating system|Value|
|Windows NT/2000 Server, running as PDC|32|
|Windows NT/2000/XP, if not the PDC|16|
|Windows 95/98/Me|1|
|Windows for Workgroups|1|

''Computer-role settings in an election''

|Role|Value|
|Domain master browser|128|
|WINS client|32|
|Preferred master|8|
|Running master|4|
|Recent backup browser|2|
|Backup browser|1|

{{op1{2. 測試設定檔是否設定正確}}}
{{{
$ testparm -v
Load smb config files from /etc/samba/smb.conf
Processing section "[homes]"
Processing section "[public]"
Loaded services file OK.
Server role: ROLE_STANDALONE
Press enter to see a dump of your service definitions
}}}

{{op1{3. 重新啟動系統}}}
{{{
$ sudo reboot 
}}}

如本機的 Samba 要扮演 Master Browser, 不可取消自動啟動 smbd, 如不啟動 smbd, 會造成 Windows 系統無法取得網路清單

''取消自動啟動 smbd''
{{{
$ mv /etc/init/smbd.conf /etc/init/smbd.conf.disabled
}}}

{{item1{運作測試 : 顯示 Master Browser (在 Windows 系統中執行)}}}
You can tell if a machine is a local master browser by using the Windows nbtstat command. Place the NetBIOS name of the machine you wish to check after the ''-a'' option:
{{{
C:\>nbtstat -a toltec

Local Area Connection:
Node IpAddress: [172.16.1.4] Scope Id: []

           NetBIOS Remote Machine Name Table

       Name               Type         Status
    ---------------------------------------------
    TOLTEC         <00>  UNIQUE      Registered
    TOLTEC         <03>  UNIQUE      Registered
    TOLTEC         <20>  UNIQUE      Registered
    .._  _MSBROWSE_ _.<01>    GROUP       Registered
    METRAN         <00>  GROUP       Registered
    METRAN         <1B>  UNIQUE      Registered
    METRAN         <1C>  GROUP       Registered
    METRAN         <1D>  UNIQUE      Registered
    METRAN         <1E>  GROUP       Registered

    MAC Address = 00-00-00-00-00-00
}}}

The resource entry that you're looking for is ..''_ _MSBROWSE_ _.<01>''. This indicates that the server is currently acting as the ''local master browser'' for the current subnet. If the machine is a Samba server, you can check the ''Samba nmbd log file'' for an entry such as:
{{{
nmbd/nmbd_become_lmb.c:become_local_master_stage2(406)
*****
Samba name server TOLTEC is now a local master browser for
workgroup METRAN on subnet 172.16.1.0
}}}

Or, you can use the nmblookup command with the ''-M'' option and the workgroup or domain name on any ''Samba server'' to find the IP address of the local master:
{{{
$ nmblookup -M it100
querying it100 on 192.168.200.255
192.168.200.5 it100<1d>
}}}

<<toBalaNotes "sambawins">>

{{item1{Name Resolution}}}
TCP/IP networks identify systems by IP addresses and always associate these addresses with more human-readable text names. In Microsoft's earliest networking implementations (for MS-DOS and Windows for Workgroups), the translation of names to network addresses was carried out in a manner that was very simple, yet very inefficient. When a system on the network needed an IP address corresponding to a name, it broadcasted the name to every other system on the network and waited for the system that owned the name to respond with its IP address.

The main problem with performing name resolution using broadcast packets is poor performance of the network as a whole, including CPU time consumed by each host on the network, which has to accept every ''broadcast packet'' and decide whether to respond to it. Also, broadcast packets usually aren't forwarded by routers, limiting name resolution to the local subnet. Microsoft's solution was to add WINS (Windows Internet Name Service) support to Windows NT so that the computers on the network can perform a direct query of the WINS server instead of using broadcast packets.

Modern Windows clients use a variety of methods for translating hostnames into IP addresses. The exact method varies depending on the version of Windows the client is running, how the client is configured (i.e., whether DNS server and/or WINS server IP addresses are provided), and whether the application software is accessing the network through Microsoft's Winsock or TCP/IP API. In general, Windows uses some combination of the following methods:
* Looking up the name in its cache of recently resolved names
* Querying DNS servers
* Using the DNS Hosts file
* Querying WINS servers
* Using the WINS LMHOSTS file
* Performing broadcast name resolution
The first method is pretty much self-explanatory. A hostname is checked against a cache of hostnames that have been recently resolved to IP addresses. This helps to save time and network bandwidth for resolving names that are used frequently.

When a Windows system is configured with the IP address of at least one DNS server, it can use DNS to resolve fully qualified domain names, such as those for sites on the Internet. The DNS servers can be either Windows NT/2000 or Unix systems. You can learn more about DNS and DNS server configuration in the O'Reilly book DNS and BIND.

{{item1{Samba as a WINS server}}}
In addition to Samba options that affect how it resolves NetBIOS names, you can set options that enable a Samba server to function as a WINS server:
WINS replication

As a practical matter, use of options such as dns proxy and wins proxy, along with the fact that most clients now use DNS for most name resolution purposes, makes the lack of WINS replication support unimportant for most installations.
{{{
wins support. Setting this Boolean option to Yes causes it to function as a WINS server. The default value is No.
wins proxy. This Boolean option determines whether Samba will respond to broadcast requests asking about names other than its own. Setting this option to Yes (the default is No) can improve NetBIOS name resolution reliability if your network spans multiple subnets or if some computers are configured to use broadcasts and others to use a WINS server.
dns proxy. If this Boolean option is set to Yes (as it is by default) and your Samba WINS server doesn't have a NetBIOS name on file that matches a lookup request, it performs a DNS lookup using the locally configured DNS settings to try to find a name.
max wins ttl. When working as a WINS server, Samba keeps information on names it has collected for a limited period of time, as determined by the client's request and this parameter. You should specify a time in seconds. The default value is 518400 (6 days).
min wins ttl. This option works much like min wins ttl, except that it sets a minimum time to store the name data. The default value is 21600 (6 hours).
}}}
Ordinarily, setting wins server = Yes is sufficient to configure Samba as a WINS server—at least on the Samba end. There's no automatic method for WINS clients to locate servers, though, so you'll need to configure your clients to tell them about the WINS server. The easiest way to do this, at least for Windows clients, is to adjust your Dynamic Host Configuration Protocol (DHCP) server configuration. The popular named server can be configured through its dhcpd.conf file, which is normally in /etc. You should set two options, which may already be present near the top of the configuration file:
{{{
option netbios-name-servers 192.168.7.2;
option netbios-node-type 8;
}}}

The first of these lines identifies the IP address of your Samba WINS server. The second sets the node type, which determines which name resolution methods are used. The values range from 1 to 8, but only four are meaningful:
{{{
1. Clients should use broadcasts alone; that is, they function as B-nodes.
2. Clients should use the WINS server alone; that is, they function as P-nodes.
4. Clients should use broadcasts first, but, if that fails, use the WINS server. Such a client is sometimes called an M-node.
8. Clients should use the WINS server first, but, if that fails, use broadcasts. Such a client is sometimes called an H-node.
}}}
As a general rule, it makes sense to configure clients as H-nodes, so passing a NetBIOS node type of 8 via the DHCP server is appropriate. 

''[註]''
Windows WINS servers can use a process known as WINS replication to exchange data between WINS servers on different subnets. Unfortunately, Samba version 3 doesn't support WINS replication, although support for this feature is planned for Samba version 4. For a time, a tool called wrepl provided support for WINS replication; however, this program never made it out of the experimental stage and has since been abandoned.

''重新啟動 Samba''
{{{
$ sudo restart nmbd  #  10.04 版的執行命令, restart 命令是由 upstart 啟動模組提供
}}}

''[注意]''
The ''wins support'' and the ''wins server'' parameters are mutually exclusive (只能二選一); you cannot simultaneously offer Samba as the WINS server and use another system as the server! Typically, one Samba server is set up as the WINS server using wins support, and all other Samba servers are configured with the wins server parameter pointing to the Samba WINS server.

{{op1{測試設定檔 (smb.conf) 是否設定正確}}}
{{{
$ testparm -v
Load smb config files from /etc/samba/smb.conf
Processing section "[homes]"
Processing section "[public]"
Loaded services file OK.
Server role: ROLE_STANDALONE
Press enter to see a dump of your service definitions
}}}

{{item1{WINS 資料庫}}}
''1. 檢視 WINS 資料庫''
{{{
$ sudo cat /var/lib/samba/wins.dat 
VERSION 1 0
"IT100#1e" 1347856782 0.0.0.0 e4R
"IT100#00" 1347856782 0.0.0.0 e4R
"IT100FS#20" 1347856782 10.0.3.6 64R
"IT100MB#00" 1347856726 10.0.3.5 66R
"IT100MB#03" 1347856726 10.0.3.5 66R
"IT100FS#03" 1347856782 10.0.3.6 64R
"IT100FS#00" 1347856782 10.0.3.6 64R
"IT100MB#20" 1347856726 10.0.3.5 66R
}}}

Entries in ''wins.dat'' take the form of:
{{{
"NAME#TYPE" TTL ADDRESS+ FLAGS
}}}
where NAME is the NetBIOS name, TYPE is the NetBIOS type, TTL is the time-to-live as an absolute time in seconds, ADDRESS+ is one or more addresses corresponding to the registration and FLAGS are the NetBIOS flags for the registration.

A typical dynamic entry looks like this:
{{{
"MADMAN#03" 1055298378 192.168.1.2 66R
}}}

To make it static, all that has to be done is set the TTL to 0, like this:
{{{
"MADMAN#03" 0 192.168.1.2 66R
}}}

Though this method works with early Samba-3 versions, there is a possibility that it may change in future versions if WINS replication is added. 

''2. 檢視網路芳鄰快取清單''
{{{
$ sudo cat /var/cache/samba/browse.dat 
"IT100"                   c0001000 "IT100MB"                     "IT100"
"IT100MB"                 40859a03 "IT100 Master Browser"        "IT100"
"IT100FS"                 40819a03 "IT100 File Server"           "IT100"
}}}

{{item1{測試 WINS Server 是否正常運作}}}
To test the new configuration you can use nmblookup to perform both ''broadcast queries'' (let’s say you are in 192.168.1.0/24):
{{{
$ nmblookup -B 192.168.1.255 machine-name
}}}

or ''unicast queries'' to your wins server (let’s suppose it is located at 192.168.1.254):
{{{
$ nmblookup -R -U 192.168.1.254 machine-name
}}}

{{item1{清除 WINS 資料庫}}}
wins 是 samba 設定的一個大問題,經常會有錯誤的情況發生,最主要是 wins.dat 這個檔案出錯,以下是除錯的方法。

首先你可以利用以下的指令來查詢 WINS Server 是不是有正常 work
{{{
# nmblookup -R -U WINS_Server_IP 欲查詢電腦名稱
}}}

{{op1{如果你 Samba 的 WINS Server 有不正常的記錄}}}

1. 請先停止 samba 很重要, 否則不會清除原記錄
{{{
$ sudo stop nmbd
nmbd stop/waiting
}}}

2. 再刪除 /var/lib/samba/wins.dat 及 /var/cache/samba/browse.dat
{{{
$ sudo rm /var/lib/samba/wins.dat
$ sudo rm /var/cache/samba/browse.dat  # 網路芳鄰清單
}}}

3. 重新啟動 Samba,則 Samba 會自動建立這兩個檔案

{{item1{使用微軟網路芳鄰}}}

''開啟 網路上的芳鄰, 檢視 網路群組與群組電腦, 如下圖 : ''

[img[img/w2k301.png]]

''如無法快速取得 "網路上的芳鄰" 資源清單, 請執行 "ipconfig /all" 命令, 查看 Node Type 為何 ? 下圖中 Node Type 為 Unknown, 以至取得資源清單非常慢,
可使用 DHCP Server 來設定此部電腦的 NodeType 或直接修改 Windows 系統的機碼'' 

[img[img/w2k3.png]]

''修改 Windows 系統的 NodeType 機碼''
此機碼會決定 NetBT 用於登錄及解析名稱的方法。 B-節點的系統使用廣播 (1) 。P-節點的系統會使用唯一的名稱伺服器 (WINS) 的點對點名稱查詢 (2) 。M-節點系統會先廣播,然後查詢名稱伺服器 (4) 。H-節點系統第一,查詢名稱伺服器,然後會廣播 (8)。

1. Create a file in notepad named NODETYPE.REG with the following contents:

You should have 3 boxes on the bottom in NOTEPAD.
1) Filename : NODETYPE.REG
2) Save as type: all files
3) Encoding: ANSI

2. 編輯 NODETYPE.REG
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NetBT\Parameters]
"NodeType"=8
"DhcpNodeType"=8

3. Double click on the file and say Yes to the merge into registry question.

4. Reboot the computer. 

''[註]'' 如設定 4 或 8, Windows Client 必須指向一部 WINS Server

{{op1{檢視 WINS Client 快取資料}}}
1.清除 client 的 WINS cache
{{{
C:\>nbtstat -R

Successful purge and preload of the NBT Remote Cache Name Table.
}}}

2.列出 client 的 WINS cache
{{{
nbtstat -c
}}}

3. 向 WINS Server 重新註冊一次 Netbios name
{{{
C:\>nbtstat -RR (windows 98 無此功能)
}}}
The NetBIOS names registered by this computer have been refreshed.

<<toBalaNotes "wins">>


///%sambawins
//%/

///%wins
//%/
<<forEachTiddler 
 where
 'tiddler.tags.length == 0'
>>
{{item1{回傳 request 封包內容}}}
1. 啟動瀏覽器, 輸入以下 URL 
{{{
http://192.168.200.132/cgi-bin/test-cgi
}}}
2. 檢視傳回資訊
{{{
CGI/1.0 test script report:

argc is 0. argv is .

SERVER_SOFTWARE = Apache/2.2.12 (Unix) DAV/2 mod_ssl/2.2.12 OpenSSL/0.9.8k PHP/5.3.0 mod_apreq2-20051231/2.6.0 mod_perl/2.0.4 Perl/v5.10.0
SERVER_NAME = 192.168.200.132
GATEWAY_INTERFACE = CGI/1.1
SERVER_PROTOCOL = HTTP/1.1
SERVER_PORT = 80
REQUEST_METHOD = GET
HTTP_ACCEPT = text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
PATH_INFO = 
PATH_TRANSLATED = 
SCRIPT_NAME = /cgi-bin/test-cgi
QUERY_STRING = 
REMOTE_HOST =
REMOTE_ADDR = 192.168.200.1
REMOTE_USER =
AUTH_TYPE =
CONTENT_TYPE =
CONTENT_LENGTH =
}}}

''[註]'' 傳回資訊中, 有詳細的 Apache 運作資訊

{{item1{限制 Apache 傳回的資訊}}}

1. 修改 /opt/lampp/etc/extra/httpd-default.conf 設定檔
{{{
          :
#
# ServerTokens
# This directive configures what you return as the Server HTTP response
# Header. The default is 'Full' which sends information about the OS-Type
# and compiled in modules.
# Set to one of:  Full | OS | Minor | Minimal | Major | Prod
# where Full conveys the most information, and Prod the least.
#
ServerTokens Minimal
              :
}}}

2. 重新啟動 Apache Server

{{item1{回傳網頁}}}
{{{
#!/bin/bash
echo "Content-type: text/html"
echo
echo "<select>"
echo "<option>Buchanan, Steven</option>"
echo "<option>Callahan, Laura</option>"
echo "<option>Davolio, Nancy</option>"
echo "</select>"
}}}

{{item1{回傳 HTTP GET 參數}}}
{{{
#!/bin/sh

# let the browser know that this is html code
echo "Content-type: text/html"
echo ""

# read in our parameters
ID=`echo "$QUERY_STRING" | sed -n 's/^.*id=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`
TEXT=`echo "$QUERY_STRING" | sed -n 's/^.*text=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`

# our html code
echo "<html>"
echo "<head><title>Hello CGI</title></head>"
echo "<body>"
echo "the value of ID is $ID<br>"
echo "the value of TEXT is $TEXT<br>"
echo "</body>"
echo "</html>"


}}}



A DNS database consists of one or more zone files used by the DNS server. Each zone holds a collection of structured resource records, the following of which are supported by the DNS service running in Windows 2000 Server.

{{op1{A}}}
Description: Host address (A) resource record. Maps a DNS domain name to an Internet Protocol (IP) version 4 32-bit address. For more information, see RFC 1035.
Syntax:
owner class  ttl  A  IP_v4_address

Example:
{{{
host1.example.microsoft.com.     IN  A  127.0.0.1
}}}
{{op1{AAAA}}}
Description: IPv6 host address (AAAA) resource record. Maps a DNS domain name to an Internet Protocol (IP) version 6 128-bit address. For more information, see RFC 1886.
Syntax:
owner  class  ttl  AAAA  IP_v6_address

Example:
{{{
ipv6_host1.example.microsoft.com.     IN  AAAA  4321:0:1:2:3:4:567:89ab
}}}
{{op1{AFSDB}}}
Description: Andrew File System Database (AFSDB) resource record. Maps a DNS domain name in the server_host_name field to the host name for a server computer of a server subtype. The subtype field can have either of the following recognized and supported values:
{{{
* A value of 1 to indicate that the server is an AFS version 3.0 volume location server for the named AFS cell.
* A value of 2 to indicate that the server is an authenticated name server holding the cell-root directory node for the server that uses either Open Software Foundation's (OSF) DCE authenticated cell-naming system or HP/Apollo's Network Computing Architecture (NCA).
}}}
For more information, see RFC 1183.
Syntax:
owner  ttl  class  AFSDB  subtype  server_host_name

Example:
{{{
example.microsoft.com.   AFSDB   1 afs-server1.example.microsoft.com.
}}}
{{op1{ATMA}}}
Description: Asynchronous Transfer Mode address (ATMA) resource record. Maps a DNS domain name in the owner field to an ATM address referenced in the atm_address field.

For more information, refer to the technical specification entitled, "ATM Name System Specification Version 1.0" published by the ATM Forum. To obtain this specification, download it from the ATM Forum FTP site.

When downloading, specify the name of the file to transfer as either:
{{{
* af-saa-0069.000.doc for a copy of the document formatted using Microsoft Word
* af-saa-0069.000.rtf for a rich text formatted (RTF) version of the document, which can be opened using WordPad
}}}
note Note
{{{
* Web addresses can change, so you might be unable to connect to the Web site or sites mentioned here.
}}}
Syntax:
owner  ttl  class  ATMA  atm_address

Example:
{{{
atm-host   ATMA   47.0079.00010200000000000000.00a03e000002.00
}}}
{{op1{CNAME}}}
Description: Canonical (規範的) name (CNAME) resource record. Maps an aliased or alternate DNS domain name in the owner field to a canonical or primary DNS domain name specified in the canonical_name field. The canonical or primary DNS domain name used in the data is required and must resolve to a valid DNS domain name in the namespace.
Syntax:
owner  ttl  class  CNAME  canonical_name

Example:
{{{
aliasname.example.microsoft.com.   CNAME   1 truename.example.microsoft.com.
}}}
{{op1{HINFO}}}
Description: Host information (HINFO) resource record. Specifies the type of CPU and operating system in the cpu_type and os_type fields, respectively, for the host DNS domain name in the owner field. Well-known CPU and operating system types that are most often used are noted in RFC 1700. This information can be used by application protocols such as FTP, which use special procedures when communicating with computers of a known CPU and operating system type.
Syntax:
owner  ttl  class  HINFO  cpu_type  os_type

Example:
{{{
my-computer-name.example.microsoft.com.    HINFO   INTEL-386  WIN32
}}}
{{op1{ISDN}}}
Description: Integrated Services Digital Network (ISDN) resource record. Maps a DNS domain name to an ISDN telephone number. Telephone numbers used with this record should follow ITU-T E.163/E.164 international telephone numbering standards, which are compatible with current international phone numbering plans already in use. For more information, see RFC 1183.
Syntax:
owner  ttl  class  ISDN  isdn_address  sub_address

Example:
{{{
my-isdn-host.example.microsoft.com.    ISDN   141555555539699 002
}}}
{{op1{MB}}}
Description: Mailbox (MB) resource record. Maps a specified domain mailbox name in the owner field to a mailbox host name in mailbox_hostname. The mailbox host name must be the same as a valid host address (A) resource record already used by a host in the same zone. Additionally, the specified host must have a domain mailbox that accepts mail for the specified owner. For more information, see RFC 1035.
Syntax:
owner  ttl  class  MB  mailbox_hostname

Example:
{{{
mailbox.example.microsoft.com.    MB   mailhost1.example.microsoft.com
}}}
{{op1{MG}}}
Description: Mail group (MG) resource record. Used to add domain mailboxes, each specified by a mailbox (MB) resource record in the current zone, to the domain mailing group identified by owner in this resource record. Names used in the mailbox_name field must be identical to valid mailbox (MB) resource records already present in the current zone. For more information, see RFC 1035.
Syntax:
owner  ttl  class  MG  mailbox_name

Example:
{{{
administrator.example.microsoft.com.    MG   mailbox1.example.microsoft.com
                                             mailbox2.example.microsoft.com
}}}
{{op1{MINFO}}}
Description: Mailbox mail list information (MINFO) resource record. Specifies (in responsible_mailbox) a domain mailbox name for a responsible person who maintains a mailing list or mailbox specified in the owner field. The error_mailbox field can also be used to specify a domain mailbox that receives error messages related to this mailing list or mailbox. Mailboxes specified for responsible contacts and error forwarding must be the same as valid mailbox (MB) records that already exist in the current zone. For more information, see RFC 1035.
Syntax:
owner  ttl  class  MINFO  responsible_mailbox  error_mailbox

Example:
{{{
administrator.example.microsoft.com.    MINFO  resp-mbox.example.microsoft.com   err-mbox.example.microsoft.com
}}}
{{op1{MR}}}
Description: Mailbox renamed (MR) resource record. Specifies a domain mailbox name in new_renamed_mailbox, the proper rename of an existing mailbox specified in the owner field. An MR resource record is often used as a forwarding entry for a user who has moved to a different mailbox. MR records do not cause additional section processing. For more information, see RFC 1035.
Syntax:
owner  ttl  class  MR  new_renamed_mailbox

Example:
{{{
old-mbox.example.microsoft.com.    MR  new-renamed-mbox.example.microsoft.com 
}}}
{{op1{MX}}}
Description: Mail exchanger (MX) resource record. Provides message routing to a mail exchanger host, as specified in mail_exchanger_host, for mail sent to the domain name specified in the owner field. A 2-digit preference value indicates preferred ordering if multiple exchanger hosts are specified. Each exchanger host must have a corresponding host (A) address resource record in a valid zone. For more information, see RFC 1035.
Syntax: owner  ttl  class  MX  preference  mail_exchanger_host

Example:
{{{
example.microsoft.com.    MX  10 mailserver1.example.microsoft.com 
}}}
{{op1{PTR}}}
Description: Pointer (PTR) resource record. Points from the name in owner to another location in the DNS namespace as specified by targeted_domain_name. Often used in special domains such as the in-addr.arpa domain tree to provide reverse lookups of address-to-name mappings. In most cases, each record provides information that points to another DNS domain name location, such as a corresponding host (A) address resource record in a forward lookup zone. For more information, see RFC 1035.
Syntax:
owner  ttl  class  PTR  targeted_domain_name

Example:
{{{
1.0.0.10.in-addr.arpa.    PTR  host.example.microsoft.com.
}}}
{{op1{RP}}}
Description: Responsible Person (RP) resource record. Specifies the domain mailbox name for a responsible person in mailbox_name. This name is then mapped to a domain name in text_record_name for which (TXT) resource records exist in the same zone. When RP records are used in DNS queries, subsequent queries are used to retrieve associated text (TXT) resource record information. For more information, see RFC 1183.
Syntax:
owner  ttl  class  RP  mailbox_name  text_record_name

Example:
{{{
example.microsoft.com.               RP    admin.example.microsoft.com.  admin-info.example.microsoft.com.
admin-info.example.microsoft.com.    TXT  "Joe Administrator, (555) 555-0110" 
}}}
{{op1{RT}}}
Description: Route through (RT) resource record. Provides an intermediate host binding for internal hosts that do not have a direct wide area network (WAN) or external network connection. The RT record is similar to the MX record in that any communication from an internal host is routed through the intermediate_host for the destination DNS domain name specified in the owner field. A 2-digit preference value is used to set priority if multiple intermediate routing hosts are specified. For each intermediate host specified, a corresponding host (A) address resource record is needed in the current zone. For more information, see RFC 1183.
Syntax:
owner  ttl  class  RT  preference  intermediate_host

Example:
{{{
example.microsoft.com.    RT    2 lan-router.example.microsoft.com
                          RT   10 wan-router.example.microsoft.com 
}}}
{{op1{SRV}}}
Description: Service locator (SRV) resource record. Allows multiple servers providing a similar TCP/IP-based service to be located using a single DNS query operation. This record enables you to maintain a list of servers for a well-known server port and transport protocol type ordered by preference for a DNS domain name. For example, in Windows 2000 Server, it provides the means to locate domain controllers that use Lightweight Directory Access Protocol (LDAP) service over TCP port 389.

The purposes of each of the specialized fields used in an SRV resource record are as follows:
{{{
* service  A symbolic name for the desired service. For well-known services, a reserved universal symbolic name such as "_telnet" or "_smtp" is defined in RFC 1700. If a well-known service name is not defined in RFC 1700, a local or user-preferred name can be used instead. Some widely used TCP/IP services, notably the Post Office Protocol (POP), do not have a single universal symbolic name. If RFC 1700 assigns a name for a service indicated in this field, the RFC-defined name is the only name that is legal to use. Only locally defined services can be named locally.

* protocol  Indicates the transport protocol type. Typically, this is either TCP or UDP, although any transport protocol named in RFC 1700 can be used.

* name  The DNS domain name referred to by this resource record. The SRV resource record is unique among other DNS record types in that it is not used to perform the search or query.

* priority  Sets the preference for a host specified in the target field. DNS clients that query for SRV resource records attempt to contact the first reachable host of the lowest numbered preference listed here. Although target hosts have the same stated preference value, they can be tried in random order. The range of preference values is 0 to 65535.

* weight  Can be used in addition to preference to provide a load-balancing mechanism where multiple servers are specified in the target field and are all set to the same level of preference. When selecting a target server host among those of equal preference, this value can be used to set an added level of preference that can be used to determine the exact order or balancing of selection for the target hosts used in an answered SRV query. When a non-zero value is used, servers of equal preference are tried in proportion to the weight of this value. The range of values is 1 to 65535. If load balancing is not needed, use a value of 0 in this field to make the record easier to read.

* port  The server port on the target host that provides the service indicated in the service field. The range of port numbers is 0 to 65535, although the number is often a well-known assigned service port number, as specified in RFC 1700. Unassigned ports can be used as needed.

* target  Specifies the DNS domain name of the host that provides the type of service being requested. For each host name used, a corresponding host address (A) resource record in the DNS namespace is required. A single period (.) can be used in this field to indicate authoritatively that the requested service specified in this SRV resource record is not available at this DNS domain name.
}}}
''Syntax:''
{{{
service.protocol.name  ttl  class  SRV  preference  weight  port  target
}}}

''Example:''
{{{
_ldap._tcp.ms-dcs    SRV  0 0   389 dc1.example.microsoft.com
                   SRV 10 0   389 dc2.example.microsoft.com 
}}}
{{op1{TXT}}}
Description: Text (TXT) resource record. Maps a DNS domain name specified in the owner field to a string of characters in text_string serving as descriptive text. For more information, see RFC 1035.
Syntax:
owner  ttl  class  TXT  text_string

Example:
{{{
example.microsoft.com.    TXT  "This is an example of additional domain name information." 
}}}
{{op1{WKS}}}
Description: Well-known service (WKS) resource record. Describes the well-known TCP/IP services supported by a particular protocol on a specific IP address. WKS records provide TCP and UDP availability information for TCP/IP servers. If a server either supports both TCP and UDP for a well-known service or has multiple IP addresses that support a service, then multiple WKS records are used. For more information, see RFC 1035.
Syntax:
owner  ttl  class  WKS  address  protocol  service_list

Example:
{{{
example.microsoft.com.    WKS  10.0.0.1 TCP ( telnet smtp ftp ) 
}}}
{{op1{X25}}}
Description: X.25 (X25) resource record. Maps a DNS domain name in the owner field to a Public Switched Data Network (PSDN) address number specified in psdn_number. PSDN numbers used with this record should follow the X.121 international numbering plan. For more information, see RFC 1183.
Syntax:
owner  ttl  class  X25  psdn_number

Example:
{{{
example.microsoft.com.    X25  52204455506
}}}
<<toBalaNotes "dnsrecord">>


///%dnsrecord
//%/
''參考文章''
1. Could not load host key: /etc/ssh/ssh_host_rsa_key Could not load host key: /etc/ssh/ssh_host_dsa_key (重設 SSH Server 的 Key)
http://knowledge-republic.com/CRM/2011/12/could-not-load-host-key-etcsshssh_host_rsa_key-could-not-load-host-key-etcsshssh_host_dsa_key/
2. Generate a ssh key and disable password authentication on the Ubuntu 12.04 (Precise Pangolin) server
http://lani78.wordpress.com/2012/07/21/generate-a-ssh-key-and-disable-password-authentication-on-ubuntu-server-12-0/
3. How To Use Key-Based Security With SSH On Ubuntu 12.04 Precise Pangolin
http://www.jonathanmoeller.com/screed/?p=3635
4. Key-Based SSH Logins With PuTTY
http://www.howtoforge.com/ssh_key_based_logins_putty
<<list shadowed>>
''參考文章''
''1. Learn Linux, 302 (Mixed environments): NetBIOS and WINS  (重要+必讀)''
http://www.ibm.com/developerworks/linux/library/l-lpic3-314-2/
2. Name Resolution and Browsing in Samba, Part 1 (主要談 WINS)
http://onlamp.com/pub/a/onlamp/excerpt/samba_chap7/index.html?page=1

{{item1{整合多網段電腦清單}}}
在 A Subnet 中, 安裝一部 Samba, 這部 Samba 作為 Domain Master Browser 及 WINS Server, 另外 B 及 C Subnet 中, 各安裝一部 Samba, 做為 Local Master Browser (不須作為 WINS Server), 這二部 LMB 均指向 A subnet 中的 WINS Server (wins server=x.x.x.x), 這樣就能整合不同網段的 Browser List.

{{op1{1. 設定 DHCP Server}}}
在 NS100 主機修改 DHCP Server 設定, 每一個 subnet 設定中加入 ''netbios-name-servers'' 及  ''netbios-node-type'' 這二個項目設定, 告知每個網段中 WINS Client, WINS Server 是那一部主機

''$ sudo nano /etc/dhcp3/dhcpd.conf''
{{{
                                :
default-lease-time 86400;
max-lease-time 86400;
                                :
                                :        
option netbios-name-servers 192.168.100.5;
option netbios-node-type 8;                         # 要設定此項目, 才能使 Windows 系統的網路芳鄰, 快速顯示網路清單
        
subnet 192.168.100.0 netmask 255.255.255.0 {
     option routers 192.168.100.254;
     option domain-name-servers 168.95.1.1;
     range 192.168.100.128 192.168.100.200;
}

subnet 192.168.66.0 netmask 255.255.255.128 {
     option routers 192.168.66.126;
     option domain-name-servers 168.95.1.1;
     range 192.168.66.60 192.168.66.120;
}

subnet 192.168.66.128 netmask 255.255.255.128 {
     option routers 192.168.66.254;
     option domain-name-servers 168.95.1.1;
     range 192.168.66.150 192.168.66.200;
}

subnet 192.168.88.0 netmask 255.255.255.0 {
     option routers 192.168.88.254;
     option domain-name-servers 168.95.1.1;
     range 192.168.88.128 192.168.88.200;
}

}}}

{{op1{2. 設定 NS100 Samba Server }}}
NS100 必須扮演 Domain Master Browser, 來整合各網段 Local Master Browser 送來的電腦清單

''$ sudo nano  /etc/samba/smb.conf''
{{{
[global]
workgroup = N301
wins support = yes                 # 作為 WINS Server
netbios name = NS100
os level = 255

domain master = yes              #  這行一定要設為 yes
preferred master =yes
local master = yes

browse list = yes
dns proxy = no
security = share
guest only = no
guest ok = yes

name resolve order = wins lmhosts hosts bcast

log file = /var/log/samba/log.%m
max log size = 1000
syslog = 2 
}}}

{{op1{3. 設定 NS88 Samba Server}}}
這部 Samba Server 扮演 Local Master Browser 收集所在網段的電腦清單, 然後送給 Domain Master Browser

''$ sudo nano /etc/samba/smb.conf''
{{{
[global]
workgroup = N301
wins support = no
wins server = 192.168.100.5          # 一定要指定 Domain Master Browser
wins proxy = yes                          # 要有這設定, 才能查詢其他 Subnet 主機 ($ nmblookup NS66)
netbios name = NS88
os level = 255

domain master = no
preferred master = yes
local master = yes

browse list = yes
dns proxy = no
security = share
guest only = no
guest ok = yes

name resolve order = wins lmhosts hosts bcast

log file = /var/log/samba/log.%m

max log size = 1000
syslog = 2
}}}

{{op1{4. 設定 NS660 Samba Server}}}
這部 Samba Server 扮演 Local Master Browser 收集所在網段的電腦清單, 然後送給 Domain Master Browser

''$ sudo nano /etc/samba/smb.conf''
{{{
[global]
workgroup = N301
wins support = no
wins server = 192.168.100.5             # 一定要指定 Domain Master Browser
wins proxy = yes
netbios name = NS660
os level = 255

domain master = no
preferred master = yes
local master = yes

browse list = yes
dns proxy = no
security = share
guest only = no
guest ok = yes

name resolve order = wins lmhosts hosts bcast

log file = /var/log/samba/log.%m

max log size = 1000
syslog = 2
}}}

{{item1{檢測 N301 網芳系統}}}

''1. 主機名稱解析''
不管在那個 Samba Server, 均可執行以下命令
{{{
student@NS660:~$ nmblookup NS88
querying NS88 on 192.168.66.127
192.168.88.5 NS88<00>

student@NS660:~$ nmblookup NS100
querying NS100 on 192.168.66.127
192.168.100.5 NS100<00>

student@NS660:~$ nmblookup NS660
querying NS660 on 192.168.66.127
192.168.66.5 NS660<00>
}}}

''2. 讀取 N301 網芳清單''
以下命令只能在 NS100, NS88 或 NS66 這三部 Samba Server 執行
{{{
student@NS660:~$ cat /var/cache/samba/browse.dat 
"N301"                    c0001000 "NS660"                       "N301"
"NS660"                   40859a03 "Samba 3.4.7"                 "N301"
"CLOUD"                   c0001000 "SKYPOPO"                     "CLOUD"
"D66_0"                   40809a03 "D660 Samba Server"           "N301"
"D100"                    00809a03 "D100 Samba Server"           "N301"
"D88"                     00809a03 "D88 Samba Server"            "N301"
"NS100"                   008d9a03 "Samba 3.4.7"                 "N301"
"NS88"                    00859a03 "Samba 3.4.7"                 "N301"
}}}

<<toBalaNotes "301">>



///%301
//%/
{{item1{查詢 MAC 註冊單位資訊的網站 (IEEE)}}}
查詢格式是 "00-50-56", 不是 "00:50:56", 查詢網址 : http://standards.ieee.org/develop/regauth/oui/public.html

{{item1{Locally Administered Address}}}
There are actually 4 sets of Locally Administered Address Ranges that can be used on your network without fear of conflict, assuming no one else has assigned these on your network:
{{{
x2-xx-xx-xx-xx-xx
x6-xx-xx-xx-xx-xx
xA-xx-xx-xx-xx-xx
xE-xx-xx-xx-xx-xx
}}}

{{item1{VMware}}}
Are you using VMware? If so the range set up by VMWare for manually applied MAC addresses is ''00:50:56:00:00:00-00:50:56:3F:FF:FF''
{{{
00-50-56   (hex)		VMware, Inc.
005056     (base 16)		VMware, Inc.
				3401 Hillview Avenue
				PALO ALTO CA 94304
				UNITED STATES
}}}

{{item1{Xen}}}
For Xen virtual machines you can use anything starting with ''00:16:3E'', and that's the default which many management tools will generate.
{{{
00-16-3E   (hex)		Xensource, Inc.
00163E     (base 16)		Xensource, Inc.
				2300 Geng Rd.
				Suite 250
				Palo Alto CA 94303
				UNITED STATES
}}}
<<toBalaNotes "1">>

///%1
//%/
{{op1{1. 編寫 tomcatup.sh  及 tomcatdown.sh}}}
{{{
$ cd /opt
$ sudo nano tomcatup.sh
export JAVA_HOME=/opt/jdk1.6.0_14
/opt/apache-tomcat-6.0.20/bin/startup.sh

$ sudo nano tomcatdown.sh
export JAVA_HOME=/opt/jdk1.6.0_14
/opt/apache-tomcat-6.0.20/bin/shutdown.sh

$ sudo chmod +x *.sh
}}}

{{op1{2. 編寫 /etc/rc.local}}}
{{{
$ sudo nano /etc/rc.local
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
sudo /opt/tomcatup.sh
exit 0
}}}

{{op1{3. 重新開機}}}
{{{
$ sudo reboot
}}}

<<toBalaNotes "tomcatup">>




///%tomcatup
//%/
''參考文章''
1. 15 Practical Linux cURL Command Examples (一定要看) 
http://www.thegeekstuff.com/2012/04/curl-examples/

{{item1{建置網站目錄架構}}}
在學生主機產生網站資料檔, 然後再複製到 Apache 主機的首頁目錄 /var/www 
{{{
$ mkdir ~/www
$ mkdir ~/www/img
$ mkdir ~/www/js
}}}

{{item1{首頁設計 (~/www/index.html)}}}
如透過網路磁碟機編輯此檔案, 不可使用記事本 (Notepad), 會造成檔案內的編碼 (cp950) 與 Ubuntu Server 系統 (UTF-8) 不合
{{{
$ nano ~/www/index.html
<html>
<head>
<script type="text/javascript" src="js/weatherimg.js"></script>
</head>
<body onload="show()">
<div id="weather">陰天</div>
</body>
</html>
}}}

{{item1{網頁程式設計 : ~/www/js/weatherimg.js}}}
如透過網路磁碟機編輯此檔案, 不可使用記事本 (Notepad), 會造成檔案內的編碼 (cp950) 與 Ubuntu Server 系統 (UTF-8) 不合
{{{
function show() {
   var x = document.getElementById('weather');

   if (x.innerHTML == "晴天")
      x.innerHTML="<img src='../img/01.png' />";
   else if (x.innerHTML == "下雨")
      x.innerHTML="<img src='../img/25.png' />";
   else if (x.innerHTML == "陰天")
      x.innerHTML="<img src='../img/08.png' />";
}
}}}

<<toBalaNotes "1">>

{{item1{上載網站資料}}}
{{{
$ cd ~/www

# 本機複製
$ sudo cp -r .  /var/www

# 遠端複製
$ scp -r  .  root@172.30.99.5:/var/www 
}}}

''[註]'' 需替 root 帳號, 設定密碼, 命令如下 :
{{{
$ sudo passwd root
}}}

<<toBalaNotes "2">>
{{item1{上載網站資訊 - 命令檔案 API}}}

''$ nano oc9mon.sh''
{{{
#!/bin/bash
[ "$USER" != "root" ] && echo "需要 root 權限" && exit 1

if [ "$1" == "stop" ]; then
    killall -9 inotifywait
    killall -9 oc9mon.sh
    exit 0 
fi

echo > $1/cmdfile.log

# inotifywait 放在 inotify-tools 套件中
# sudo apt-get install inotify-tools

inotifywait -rmq --timefmt "%m_%d_%H_%M_%S" --format "%w %f %e %T" -e create $1 | 
while read p f a t;
do 
   echo "$p$f" $a $t >> $1/cmdfile.log
   (./oc9webcp.sh $p $f $a $t &)
done
}}}

''$ nano oc9webcp.sh''
{{{
#!/bin/bash

[ -d $1$2 ] && exit 1

if [ "$2" == "backup" ]; then
   rm $1$2 >/dev/null 
   cp -r /home/student/www /var
   [ "$?" == "0" ] && echo "copy ok"
fi
}}}

<<toBalaNotes "3">>

///%1
//%/

///%2
//%/

///%3
//%/
{{item1{關閉 IPV6}}}
本文網址 : http://linuxforeverything.com/wordpress/?p=55

To check if IPv6 is disabled, run the following command:
{{{
$ cat /proc/sys/net/ipv6/conf/all/disable_ipv6
0
}}}

''0'' means it's enabled and ''1 - disabled''.

This tweak is thanks to an old comment from Stonecut (this way you don't have to edit the GRUB). Basically, to disable IPv6 in Ubuntu 10.04 Lucid Lynx, you have to add the following lines to ''/etc/sysctl.conf'':
{{{
# disable ipv6
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
}}}

{{item1{關閉 ICMP Redirects}}}
Edit the ''/etc/sysctl.conf'' file and add the following lines:

{{{
net.ipv4.conf.all.accept_redirects = 0 
net.ipv4.conf.all.send_redirects = 0 
}}}

{{item1{Disable ICMP on Linux}}}
Ping defined: Ping is normally used to check to see if another machine on a network is responding.  A simple command, which sends a small network packet to the machine is used.  If the machine is up, it will respond to the packed and return the packet to the system that initiated the request.

Sometimes ping can be used to discover potentially insecure hosts; hackers use ping to determine if your machine answers, if it does, then they may pursue your machine as a potentially hackable host.  

It can also be used to quickly scan a range of IP addresses to determine machines that are on that network, to the same effect, a hacker may then pursue your host as a potential target.
So lets disable ping on a Linux based system:

To eliminate this threat, we simply disable the kernel's response to the ping packet by issuing the following command:
{{{
echo 1 >/proc/sys/net/ipv4/icmp_echo_ignore_all
}}}
This is only a temporary solution, which you can see the effects by trying to ping your machine from another computer.  To discard the change, simply enter:
{{{
echo 0 >/proc/sys/net/ipv4/icmp_echo_ignore_all
}}}
If this is a change that you believe should be permanent, you may edit your sysctl.conf file, normally located at:
{{{
/etc/sysctl.conf
}}}
By adding or changing the following line:
{{{
net.ipv4.conf.icmp_echo_ignore_all = 1
}}}
<<toBalaNotes "ipv6icmp">>


///%ipv6icmp
//%/
1. 遠端連線的黑暗技(SSH Tunnel)
http://indeepnight.blogspot.tw/2007/09/ssh-tunnel.html
''參考文章''
1. Chapter 9. Users and Security ''(必讀)''
http://www.samba.org/samba/docs/using_samba/ch09.html

In fact, if you set the ''security = share'' option in the Samba configuration file, Samba will still reuse the ''username/password combinations'' in the system password files to authenticate access. More precisely, Samba will take the following steps when a client requests a connection using share-level security:
''
1. When a connection is requested, Samba will accept the password and (if sent) the username of the client.

2. If the share is guest only , the user is immediately granted access to the share with the rights of the user specified by the guest account parameter; no password checking is performed.

3. For other shares, Samba appends the username to a list of users who are allowed access to the share. It then attempts to validate the password given in association with that username. If successful, Samba grants the user access to the share with the rights assigned to that user. The user will not need to authenticate again unless a revalidate = yes option has been set inside the share.

4. If the authentication is unsuccessful, Samba attempts to validate the password against the list of users previously compiled during attempted connections, as well as those specified under the share in the configuration file. If the password matches that of any username, the user is granted access to the share under that username. (根據 samba 帳號的密碼作檢核)

5. However, if the share has a guest ok or public option set, the user will default to access with the rights of the user specified by the guest account option.
''
You can indicate in the configuration file which users should be initially placed on the share-level security user list by using the username configuration option, as shown here:
{{{
[global]
   security = share

[accounting1]
    path = /home/samba/accounting1
    guest ok = no
    writable = yes
    username = davecb, pkelly, andyo
}}}
Here, when a user attempts to connect to a share, Samba verifies the sent password against each user in its own list, in addition to the passwords of users davecb, pkelly, and andyo. If any of the passwords match, the connection is verified, and the user is allowed. Otherwise, connection to the specific share will fail.

{{op1{only user}}}
This Boolean option indicates whether Samba will allow connections to a share using share-level security based solely on the individuals specified in the username option, instead of those users compiled on Samba's internal list. The default value for this option is no. You can override it per share as follows:
{{{
[global]
    security = share
[data]
    username = andy, peter, valerie
    only user = yes
}}}

{{op1{username}}}
This option presents a list of usernames and/or group names against which Samba tests a connection password to allow access. It is typically used with clients that have share-level security to allow connections to a particular service based solely on a qualifying password—in this case, one that matches a password set up for a specific user:
{{{
[global]
    security = share
[data]
    username = andy, peter, terry
}}}
You can enter a list of usernames and/or group names. If a name is prefixed by an at sign (@), it is interpreted as a group name, with NIS groups searched before Unix groups. If the name is prefixed by a plus sign (+), it is interpreted as the name of a Unix group, and NIS is not searched. If the name is prefixed by an ampersand (&), it is interpreted as an NIS group name rather than a Unix group name. The plus sign and ampersand can be used together to specify whether NIS or Unix groups are searched first. When Samba encounters a group name in this option, it attempts to authenticate each user in the group until if finds one that succeeds. Beware that this can be very inefficient.

We recommend against using this option unless you are implementing a Samba server with share-level security.

<<toBalaNotes "1">>

{{item1{共享資料夾 - 不需密碼}}}

''1. 編輯 Samba 設定檔 (/etc/samba/smb.conf)''
{{{
$ sudo nano /etc/samba/smb.conf 
[global]
workgroup = IT100
wins support = yes
netbios name = IT100MB
server string = IT100 Master Browser
os level = 255

domain master = no 
preferred master = yes
local master = yes

browse list = yes
dns proxy = no

# 取消印表機共享功能
printcap name = /dev/null
load printers = no
printing = bsd

name resolve order = wins hosts bcast
log file = /var/log/samba/log.%m
max log size = 1000
syslog = 2

# 存取安全模式設為 share-level 
security = share

[tmpr]
   path = /tmp

   # 以下設定代表不需帳號及密碼, 便可使用此資源
   guest ok = yes

   # 以下設定將此共享資料夾設為唯讀
   read only = yes

[tmpw]
   path = /tmp

   # public 就是 guest ok
   public = yes

   # 以下設定將此共享資料夾設為可寫入
   writeable = yes
}}}

''2. 重新啟動 smbd 服務''
{{{
$ sudo restart smbd
}}}

''3. 檢視本機 Samba 共享資訊 ''
{{{
$ smbclient -N -L //localhost
WARNING: The security=share option is deprecated
Domain=[IT100] OS=[Unix] Server=[Samba 3.6.3]

	Sharename       Type      Comment
	---------       ----      -------
	tmpr            Disk      
	tmpw            Disk      
	IPC$            IPC       IPC Service (IT100 Master Browser)
Domain=[IT100] OS=[Unix] Server=[Samba 3.6.3]

	Server               Comment
	---------            -------
	IT100FS              IT100 File Server
	IT100MB              IT100 Master Browser
	W2K302               

	Workgroup            Master
	---------            -------
	IT100                IT100MB
}}}
<<toBalaNotes "2">>
{{item1{共享資料夾 - 需密碼}}}

''1. 建立帳號及群組''
{{{
$ sudo useradd -m -s /bin/bash tom
$ sudo passwd tom

$ sudo useradd -m -s /bin/bash mary
$ sudo passwd mary

$ sudo useradd -m -s /bin/bash ring01
$ sudo passwd ring01

# 建立 ring 群組
$ sudo groupadd ring

# 將 ring01 加入 ring  群組
$ sudo usermod -a -G ring ring01
}}}

''[註]''
Add existing user tony to ftp supplementary/secondary group with usermod command using -a option ~ i.e. add the user to the supplemental group(s). Use only with -G option :
{{{
# usermod -a -G ftp tony
}}}

Change existing user tony primary group to www:
{{{
# usermod -g www tony
}}}

''2. 建立 Samba 帳號及密碼''
{{{
$ sudo pdbedit -a -u tom
$ sudo pdbedit -a -u mary
$ sudo pdbedit -a -u ring01
}}}

''3. 編輯 Samba 設定檔 (/etc/samba/smb.conf)''
將以下設定, 加在原先設定檔的後面
{{{
              :
[tmpuw]
   path = /tmp
   writeable = yes   

   # 在網路芳鄰中不會看到此共享資料夾名稱
   browseable = No

   # 使用此共享資料夾, 只接受 tom, mary 的密碼檢核, 不管前端的帳號名稱
   username = tom, mary

[tmpur]
   path = /tmp
   browseable = No

   # 使用此共享資料夾, 只接受 tom, mary 及 ring 群組中組員的密碼檢核, 不管前端的帳號名稱
   username = @ring, tom, mary
}}}

''4. 重新啟動 smbd 服務''
{{{
$ sudo restart smbd
}}}

{{item1{Windows 前端連接}}}
如 Windows 系統, 登入的帳號所使用的密碼與 tom, mary 或 ring 群組中帳號一樣, 連接時不會詢問密碼, 所以要測試上述功能 (共享資料夾 - 需密碼), ''@@color:blue;請確認登入帳號的密碼與  tom, mary 或 ring 群組中帳號不一樣.@@''

[img[img/samba_share.png]]
<<toBalaNotes "3">>



///%1
//%/

///%2
//%/

///%3
//%/
{{{
$CATALINA_HOME   Tomcat 安装目錄        
├─bin          用以啟動與停止、關閉 Tomcat 或者其他功能的程序(.bat 文件和 .sh 程序)
├─common       Catalina 和 Web 應用程序會用到的 Class 及文件
├─conf         用以配置 Tomcat 的 XML 及 DTD 文件
├─logs         Catalina 和其他 Web 應用程序的日誌文件
├─server       Catalina 用到的 Class 及文件
├─shared       Web 應用程序用到的 Class 及文件
├─temp         暫存區
├─webapps      Web 應用專案的根目錄
└─work         用以產生有 JSP 编譯出的 Servlet 的 .java 和.class 文件
}}}
每一部主機都有一個首頁,但是如果每個個人用戶都想要有可以自己完全控管的首頁時, 那該如何設計?呵呵!Apache 早就幫我們想到了!

''1. 修改  /opt/lampp/etc/httpd.conf 設定檔''
請將 "Include etc/extra/httpd-userdir.conf" 的這行備註拿掉
{{{
# User home directories
Include etc/extra/httpd-userdir.conf
}}}

''2. httpd-userdir.conf 設定檔內容''
{{{
# Settings for user home directories
#
# Required module: mod_userdir

#
# UserDir: The name of the directory that is appended onto a user's home
# directory if a ~user request is received.  Note that you must also set
# the default access control for these directories, as in the example below.
#
UserDir public_html

#
# Control access to UserDir directories.  The following is an example
# for a site where these directories are restricted to read-only.
#
<Directory /home/*/public_html>
    AllowOverride FileInfo AuthConfig Limit Indexes
    Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
    <Limit GET POST OPTIONS>
        Order allow,deny
        Allow from all
    </Limit>
    <LimitExcept GET POST OPTIONS>
        Order deny,allow
        Deny from all
    </LimitExcept>
</Directory>
}}}

上面設定將預設的個人首頁, 放置在家目錄下的 public_html/ 目錄下!假如 tobala 的家目錄在 /home/tobala,那麼他的個人首頁預設在 /home/tobala/public_html/ 囉!你當然可以修改這個目錄名稱, 只要將上表的 UserDir 後面內容改掉即可。例如改為 www 時,使用者的個人首頁則放在家目錄下的 www 目錄中。 設定完畢後得要重新啟動你的 apache 喔!

''[問題]'' 如何讓未來所有『新增』的使用者預設家目錄下都有個 www 的目錄?
答: 因為新增使用者時所參考的家目錄在 /etc/skel 目錄內,所以你可以直接 mkdir /etc/skel/www 即可。 

好了,假設你的主機有個 profx 的用戶,那麼這傢伙怎麼建立他的個人首頁? 我們這樣測試一下好了!(底下的工作請以你的一般身份使用者處理):
{{{
$ cd ~
$ mkdir public_html
$ chmod 755 public_html
$ echo "Test your home" >> index.html
}}}
你的家目錄與 public_html 目錄的權限成為 drwxr-xr-x 才行!這個很重要啊! 那麼未來只要你在瀏覽器的網址列這樣輸入:
{{{
http://你的主機名稱/~profx/
}}}

''[問題]'' 如將 index.html 檔案刪除, 此時瀏覽結果如何 ?

不過,多這個毛毛蟲就很討厭~ 我可不可以將使用者的個人網站設定成為:
{{{
http://你的主機名稱/scjp30/
}}}
是可以啦!最簡單的方法是這樣的:
{{{
profx@UB1032SCE1:~$ cd /opt/lampp/htdocs/
profx@UB1032SCE1:~$ sudo ln -s /home/scjp30/java2009 scjp30
[sudo] password for profx:
}}}
<<toBalaNotes "perdir">>


///%perdir
//%/
本文網址 : http://www.ducea.com/2006/05/30/managing-apache2-modules-the-debian-way/

''The Apache2 HTTP Server is a modular program'', where we can choose its functionality by including in the server a set of modules. The modules can be statically compiled into the httpd binary when the server is built. Alternatively, modules can be compiled as ''Dynamic Shared Objects (DSOs)'' that exist separately from the main httpd binary file.

Normally enabling one particular apache DSO module will involve editing the main apache configuration file and adding a ''LoadModule'' line to enable the loading of the particular module. Depending from the module itself, we might need to add also some configuration directives. This will work fine on Debian also, but I am going to show you the Debian particular method of managing apache2 modules.

Regardless of the apache MPM (Multi-Processing Modules) you are using: apache2-mpm-prefork, apache2-mpm-worker or apache2-mpm-perchild after the installation you will end up with some default modules: some already enabled and some ready to be used. Opposed to a RedHat based system for example (where they will try to enable all the possible modules) the Debian package will enable by default only a very small amount of modules.

''內建在 Apache 核心的模組''
{{{
$ sudo apache2 -l
Compiled in modules:
  core.c
  mod_log_config.c
  mod_logio.c
  worker.c
  http_core.c
  mod_so.c
}}}

''[註]'' These modules can’t be disabled without recompiling the apache package

The Ubuntu apache2 package provides a unique mode of managing modules. All the loading and configuration related entries are found in individual files inside folder ''/etc/apache2/mods-available/''. Here we will find files like module_name.load (and if needed module_name.conf). Also all additional installed modules will place their configuration files in the same place.

Inside the folder ''/etc/apache2/mods-enabled/'' we will find all the enabled modules. Here we will find symlinks to the files from mods_available for all the enabled modules. Only the modules found in this folder will be enabled at run time.

''列出已啟動的動態模組''
{{{
$ ls /etc/apache2/mods-enabled/
alias.conf            authz_user.load  dir.conf          reqtimeout.conf
alias.load            autoindex.conf   dir.load          reqtimeout.load
auth_basic.load       autoindex.load   env.load          setenvif.conf
authn_file.load       cgid.conf        mime.conf         setenvif.load
authz_default.load    cgid.load        mime.load         status.conf
authz_groupfile.load  deflate.conf     negotiation.conf  status.load
authz_host.load       deflate.load     negotiation.load
}}}

For example the configuration file for mod_dir includes only one line to load the module:
{{{
$ cat /etc/apache2/mods-enabled/dir.load
LoadModule dir_module /usr/lib/apache2/modules/mod_dir.so
}}}

{{item1{Apache2 動態模組管理命令}}}
So in order to enable one additional module we will only have to create the proper symlinks from the mods-available to the mod-enabled files… But why not use the little tools Debian provides us for this:

''a2enmod'': enables an apache2 module (this does nothing else but creates the proper links to the module .load and .conf files). 
''a2dismod'': disables an apache2 module (removes the links from mod-enabled for the module). 

''命令實作''
1. Running ''a2enmod'' without any parameter will show the possible choices:
{{{
$ sudo a2enmod
Your choices are: actions alias asis auth_basic auth_digest authn_alias authn_anon authn_dbd authn_dbm authn_default authn_file authnz_ldap authz_dbm authz_default authz_groupfile authz_host authz_owner authz_user autoindex cache cern_meta cgi cgid charset_lite dav dav_fs dav_lock dbd deflate dir disk_cache dump_io env expires ext_filter file_cache filter headers ident imagemap include info ldap log_forensic mem_cache mime mime_magic negotiation proxy proxy_ajp proxy_balancer proxy_connect proxy_ftp proxy_http proxy_scgi reqtimeout rewrite setenvif speling ssl status substitute suexec unique_id userdir usertrack version vhost_alias
Which module(s) do you want to enable (wildcards ok)?
}}}

''[註]'' 直接按 Enter 鍵, 結束 a2enmod 命令執行
 
2. Running ''a2dismod'' without any parameter again will show us the list of enabled modules and allow to choose one:
{{{
$ sudo a2dismod
Your choices are: alias auth_basic authn_file authz_default authz_groupfile authz_host authz_user autoindex cgid deflate dir env mime negotiation reqtimeout setenvif status
Which module(s) do you want to disable (wildcards ok)?
}}}

''[註]'' a2dismod 命令會先將所有已啟動的動態模組列出, 然後詢問你要停止那個動態模組 

Dont forget to reload the apache daemon, after making any changes to the list of enabled modules:
{{{
/etc/init.d/apache2 reload
}}}

''啟動 mod_ssl 動態模組''
{{{
$ sudo a2enmod ssl
Enabling module ssl.
See /usr/share/doc/apache2.2-common/README.Debian.gz on how to configure SSL and create self-signed certificates.
Run '/etc/init.d/apache2 restart' to activate new configuration!
}}}

執行完啟動命令後, 在 /etc/apache2/mods-enabled/ 目錄中, 會出現 ssl.conf 及 ssl.load 這二個檔案, 如下 :
{{{
$ ls /etc/apache2/mods-enabled/
alias.conf            autoindex.conf  env.load          setenvif.load
alias.load            autoindex.load  mime.conf         ssl.conf
auth_basic.load       cgid.conf       mime.load         ssl.load
authn_file.load       cgid.load       negotiation.conf  status.conf
authz_default.load    deflate.conf    negotiation.load  status.load
authz_groupfile.load  deflate.load    reqtimeout.conf
authz_host.load       dir.conf        reqtimeout.load
authz_user.load       dir.load        setenvif.conf
}}}

''停止 mod_ssl 動態模組''
{{{
$ sudo a2dismod ssl
Module ssl disabled.
Run '/etc/init.d/apache2 restart' to activate new configuration!
}}}
<<toBalaNotes "modules">>


///%modules
//%/
Root Nameserver : http://en.wikipedia.org/wiki/Root_nameserver
DNS root zone : http://en.wikipedia.org/wiki/DNS_root_zone
Internet Systems Consortium (ISC) :http://www.isc.org/software/bind

{{item1{BIND}}}
- Bind 的全名是 Berkeley Internet Name Domain,最初的時候是由加州大學柏克萊分校所發展出來的 BSD UNIX 中的一部份,目前則由 ISC 組織來負責維護與發展。

- Bind 是用來解決網域名稱與 IP 位址對應的軟體,有近九成的 DNS 伺服器主機都是使用 Bind。 

- Recursive Query:DNS client 端只丟出一個詢問給 local DNS server,然後 local DNS 就會不斷地查到答案出來為止,最後把結果傳回來給 client,這種查詢稱為 Recursive Query。

- Non-Recursive Query (iterative query):local DNS 對其它 DNS 發出的詢問,都只是知道一個更進一步的線索,然後發問者 ( local DNS ) 根據線索再去進一步找答案, 這種詢問方式稱為 Non-Recursive Query(iterative query)。 

<<toBalaNotes "dns">>

///%dns
//%/
Avahi is a free Zero Configuration Networking (Zeroconf) implementation, including a system for multicast DNS/DNS-SD service discovery. It allows programs to publish and discover services and hosts running on a local network with no specific configuration. For example you can plug into a network and instantly find printers to print to, files to look at and people to talk to. It is licensed under the GNU Lesser General Public License (LGPL). (Source: Wikipedia:Avahi (software))

You could try to restart the daemon by following:

Open up a terminal(Ctrl-Alt-T) and type: sudo service avahi-daemon restart.

You can announce services by using the avahi service. To announce a service, you have to add a service description file in the /etc/avahi/services directory. For example, to announce an sftp share, create a file sftp.service with:
{{{
<service-group>
  <name replace-wildcards="yes">SFTP on %h</name>
  <service>
    <type>_sftp-ssh._tcp</type>
    <port>22</port>
  </service>
</service-group>
}}}
For FTP you have to change the type to _ftp._tcp and the port to 21, for an NFS share you have the change the type to _nfs._tcp and the port to 2049, and you also have to include something like:
{{{
<txt-record>path=/path/to/someshare</txt-record>
}}}
The avahi.service man page has all the information on the format of these files.
''參考文章''
1.Howto: Domain Name Server On Linux - DNS for your Intranet (or Internet) Serv
http://www.astahost.com/info.php/Howto-Domain-Server-Linux_t2508.html
2. BIND 9 Administrator Reference Manual (9.3.2)
http://www.bind9.net/manuals
3. Configuring bind9 on Ubuntu 10.04
http://blog.retep.org/2010/05/18/configuring-bind9-on-ubuntu-10-04/

{{item1{設定本機電腦名稱}}}

''1. 將新的電腦名稱輸入到 /etc/hostname 檔''
{{{
$ sudo nano /etc/hostname
oncloud99

$ sudo reboot              # 重新開機
}}}

''2. 檢視本機電腦名稱''
{{{
$ hostname
oncloud99
}}}

''3. ping 本機電腦名稱''
{{{
$ ping oncloud99
ping : unknown host oncloud99             # 執行失敗
}}}

''4. 修改 /etc/hosts 檔''
{{{
$ sudo nano /etc/hosts

127.0.0.1       localhost
127.0.1.1       oncloud99.localdomain   oncloud99

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

$ ping oncloud99
PING oncloud99.localdomain (127.0.1.1) 56(84) bytes of data.
64 bytes from oncloud99.localdomain (127.0.1.1): icmp_seq=1 ttl=64 time=0.617 ms
64 bytes from oncloud99.localdomain (127.0.1.1): icmp_seq=2 ttl=64 time=0.074 ms

}}}

''[註]''  ''/etc/hosts'' 主要是給 TCP/IP 相關命令及服務, 做為名稱解析之用, 而不是做為設定本機電腦名稱

{{item1{手動設定本機 IP 位址, 以做為 DNS Server 的 IP 位址}}}
因本機要做為 DNS Server, 那必須手動設定本機 IP 位址, 以及 本機 DNS Client 所使用的 DNS Server IP 位址
{{{
$ sudo nano /etc/network/interfaces
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto eth0
iface eth0 inet static
  address 192.168.56.5
  netmask 255.255.255.0
  gateway 192.168.56.2
  dns-nameservers 192.168.56.5   (必須設為本機位址, 因本機安裝 bind9)
}}}
上面的 dns-nameservers 192.168.56.5設定, 會存入 /etc/resolv.conf 檔案, 但在 10.04 版, 卻沒有執行此動作 ([[已報 bug|https://bugs.launchpad.net/ubuntu/+source/resolvconf/+bug/550962]]), 所以只好手動修改 /etc/resolv.conf, 如下 : 
{{{
$ sudo nano /etc/resolv.conf
nameserver 192.168.56.5
domain kvm.
}}}

如網卡設定 DHCP 取得 IP 位址, 那麼 DHCP Server 也會一併送出 DNS Server 的 IP 位址, 這 DNS Server IP 位址, 會存入 /etc/resolv.conf 檔案, 內容如下 :
{{{
$ cat /etc/resolv.conf
nameserver 192.168.56.2
domain kvm.
}}}

{{item1{安裝 bind 9}}}
{{{
$ sudo apt-get install bind9
正在讀取套件清單... 完成
正在重建相依關係
正在讀取狀態資料... 完成
下列的額外套件將被安裝:
  bind9utils
建議套件:
  bind9-doc resolvconf
下列【新】套件將會被安裝:
  bind9 bind9utils
升級 0 個,新安裝 2 個,移除 0 個,有 3 個未被升級。
需要下載 433kB 的套件檔。
此操作完成之後,會多佔用 1,368kB 的磁碟空間。
是否繼續進行 [Y/n]?y
下載:1 http://tw.archive.ubuntu.com/ubuntu/ lucid/main bind9utils 1:9.7.0.dfsg.P1-1 [111kB]
下載:2 http://tw.archive.ubuntu.com/ubuntu/ lucid/main bind9 1:9.7.0.dfsg.P1-1 [321kB]
取得 433kB 用了 4s (104kB/s)
正在預先設定套件 ...
選取了原先未被選取的套件 bind9utils。
(正在讀取資料庫 ... 系統目前共安裝了 42616 個檔案和目錄。)
正在解開 bind9utils (從 .../bind9utils_1%3a9.7.0.dfsg.P1-1_i386.deb)...
選取了原先未被選取的套件 bind9。
正在解開 bind9 (從 .../bind9_1%3a9.7.0.dfsg.P1-1_i386.deb)...
正在進行 man-db 的觸發程式 ...
正在進行 ufw 的觸發程式 ...
正在進行 ureadahead 的觸發程式 ...
ureadahead will be reprofiled on next reboot
正在設定 bind9utils (1:9.7.0.dfsg.P1-1) ...
正在設定 bind9 (1:9.7.0.dfsg.P1-1) ...
新增 'bind' 群組 (GID 112) ...
完成。
增加系統使用者 `bind' (UID 104 )
Adding new user `bind' (UID 104) with group `bind' ...
未建立家目錄『/var/cache/bind』。
wrote key file "/etc/bind/rndc.key"
#
 * Starting domain name service... bind9                                 [ OK ]
}}}

''[註]'' 在 LXC 的 Ubuntu 系統中, 需自行安裝 ''dnsutils'' 套件, 才有 dig 及 nslookup 命令

{{op1{4. 檢測 DNS Server}}}
{{{
# nslookup
> server
Default server : 172.23.100.8
Address: 172.23.100.8

> set type=any
> hinet.net.
Server:         140.137.202.20
Address:        140.137.202.20#53

> hinet.net.
Server:		172.30.100.2
Address:	172.30.100.2#53

Non-authoritative answer:
hinet.net
	origin = hntp1.hinet.net
	mail addr = hostmaster.hinet.net
	serial = 201008121
	refresh = 3600
	retry = 7200
	expire = 3600000
	minimum = 86400
hinet.net	mail exchanger = 10 netnews.hinet.net.
hinet.net	nameserver = ans1.hinet.net.
hinet.net	nameserver = ans2.hinet.net.

Authoritative answers can be found from:
hinet.net	nameserver = ans1.hinet.net.
hinet.net	nameserver = ans2.hinet.net.
netnews.hinet.net	internet address = 168.95.195.16

> exit                       (離開 nslookup 命令)
}}}

''顯示 BIND9 版本''
{{{
$ /usr/sbin/named -v
BIND 9.7.3
}}}

{{item1{DNS Server 安裝後的設定檔}}}
The DNS configuration files are stored in the ''/etc/bind'' directory. The primary configuration file is ''/etc/bind/named.conf.''

The include line specifies the filename which contains the DNS options. The directory line in the /etc/bind/named.conf.options file tells DNS where to look for files. All files BIND uses will be relative to this directory.

The file named ''/etc/bind/db.root'' describes the root nameservers in the world. The servers change over time, so the ''/etc/bind/db.root'' file must be maintained now and then. This is usually done as updates to the bind9 package. The zone section defines a master server, and it is stored in a file mentioned in the file option.

{{op1{1. 列出 /etc/bind 目錄所有檔案}}}
''$ ls -al /etc/bind''
{{{
總計 52
drwxr-sr-x  2 root bind 4096 2009-08-23 10:16 .
drwxr-xr-x 72 root root 4096 2009-08-23 10:16 ..
-rw-r--r--  1 root root  237 2009-07-29 11:38 db.0
-rw-r--r--  1 root root  271 2009-07-29 11:38 db.127
-rw-r--r--  1 root root  237 2009-07-29 11:38 db.255
-rw-r--r--  1 root root  353 2009-07-29 11:38 db.empty
-rw-r--r--  1 root root  270 2009-07-29 11:38 db.local
-rw-r--r--  1 root root 2878 2009-07-29 11:38 db.root
-rw-r--r--  1 root bind  907 2009-07-29 11:38 named.conf
-rw-r--r--  1 root bind  165 2009-07-29 11:38 named.conf.local
-rw-r--r--  1 root bind  572 2009-07-29 11:38 named.conf.options
-rw-r-----  1 bind bind   77 2009-08-23 10:16 rndc.key
-rw-r--r--  1 root root 1317 2009-07-29 11:38 zones.rfc1918
}}}

{{op1{2. 顯示 /etc/bind/named.conf 檔案內容}}}

''$ cat /etc/bind/named.conf''
{{{
// This is the primary configuration file for the BIND DNS server named.
//
// Please read /usr/share/doc/bind9/README.Debian.gz for information on the
// structure of BIND configuration files in Debian, *BEFORE* you customize
// this configuration file.
//
// If you are just adding zones, please do that in /etc/bind/named.conf.local

include "/etc/bind/named.conf.options";
include "/etc/bind/named.conf.local";
include "/etc/bind/named.conf.default-zones";
}}}

{{op1{3. 顯示 /etc/bind/named.conf.default-zones 檔案內容}}}
{{{
// prime the server with knowledge of the root servers
zone "." {
        type hint;
        file "/etc/bind/db.root";
};

// be authoritative for the localhost forward and reverse zones, and for
// broadcast zones as per RFC 1912

zone "localhost" {
        type master;
        file "/etc/bind/db.local";
};

zone "127.in-addr.arpa" {
        type master;
        file "/etc/bind/db.127";
};
                                             :
                                             :
}}}

{{op1{4. 顯示 /etc/bind/named.conf.options 檔案內容}}}

''$ cat /etc/bind/named.conf.options''
{{{
options {
        directory "/var/cache/bind";

        // If there is a firewall between you and nameservers you want
        // to talk to, you may need to fix the firewall to allow multiple
        // ports to talk.  See http://www.kb.cert.org/vuls/id/800113

        // If your ISP provided one or more IP addresses for stable
        // nameservers, you probably want to use them as forwarders.
        // Uncomment the following block, and insert the addresses replacing
        // the all-0's placeholder.

        // forwarders {
        //      0.0.0.0;
        // };

        auth-nxdomain no;    # conform to RFC1035
        listen-on-v6 { any; };
};
}}}

''[註]''
''auth-nxdomain''
If yes, the AA bit is always set on NXDOMAIN responses, even if the server is not actually authoritative. The default is yes. Do not turn off auth-nxdomain unless you are sure you know what you are doing (但是 Ubuntu 安裝的 Bind9 此項目是設定值為 no), as some older software won't like it.

NX-DOMAIN means ''"domain doesn't exist"'' The ''AA bit'' means the server has ''authority''. 

{{op1{5. 顯示 /etc/bind/db.root 檔案內容}}}
{{{
;       This file holds the information on root name servers needed to
;       initialize cache of Internet domain name servers
;       (e.g. reference this file in the "cache  .  <file>"
;       configuration file of BIND domain name servers).
;
;       This file is made available by InterNIC 
;       under anonymous FTP as
;           file                /domain/named.root
;           on server           FTP.INTERNIC.NET
;       -OR-                    RS.INTERNIC.NET
;
;       last update:    Feb 04, 2008
;       related version of root zone:   2008020400
;
; formerly NS.INTERNIC.NET
;
.                        3600000  IN  NS    A.ROOT-SERVERS.NET.
A.ROOT-SERVERS.NET.      3600000      A     198.41.0.4
A.ROOT-SERVERS.NET.      3600000      AAAA  2001:503:BA3E::2:30
;
; formerly NS1.ISI.EDU
;
.                        3600000      NS    B.ROOT-SERVERS.NET.
B.ROOT-SERVERS.NET.      3600000      A     192.228.79.201
;
; formerly C.PSI.NET
;
.                        3600000      NS    C.ROOT-SERVERS.NET.
C.ROOT-SERVERS.NET.      3600000      A     192.33.4.12
;
; formerly TERP.UMD.EDU
;
.                        3600000      NS    D.ROOT-SERVERS.NET.
D.ROOT-SERVERS.NET.      3600000      A     128.8.10.90
;
; formerly NS.NASA.GOV
;
.                        3600000      NS    E.ROOT-SERVERS.NET.
E.ROOT-SERVERS.NET.      3600000      A     192.203.230.10
;
; formerly NS.ISC.ORG
;
.                        3600000      NS    F.ROOT-SERVERS.NET.
F.ROOT-SERVERS.NET.      3600000      A     192.5.5.241
F.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:2f::f
;
; formerly NS.NIC.DDN.MIL
;
.                        3600000      NS    G.ROOT-SERVERS.NET.
G.ROOT-SERVERS.NET.      3600000      A     192.112.36.4
;
; formerly AOS.ARL.ARMY.MIL
;
.                        3600000      NS    H.ROOT-SERVERS.NET.
H.ROOT-SERVERS.NET.      3600000      A     128.63.2.53
H.ROOT-SERVERS.NET.      3600000      AAAA  2001:500:1::803f:235
;
; formerly NIC.NORDU.NET
;
.                        3600000      NS    I.ROOT-SERVERS.NET.
I.ROOT-SERVERS.NET.      3600000      A     192.36.148.17
;
; operated by VeriSign, Inc.
;
.                        3600000      NS    J.ROOT-SERVERS.NET.
J.ROOT-SERVERS.NET.      3600000      A     192.58.128.30
J.ROOT-SERVERS.NET.      3600000      AAAA  2001:503:C27::2:30
;
; operated by RIPE NCC
;
.                        3600000      NS    K.ROOT-SERVERS.NET.
K.ROOT-SERVERS.NET.      3600000      A     193.0.14.129 
K.ROOT-SERVERS.NET.      3600000      AAAA  2001:7fd::1
;
; operated by ICANN
;
.                        3600000      NS    L.ROOT-SERVERS.NET.
L.ROOT-SERVERS.NET.      3600000      A     199.7.83.42
;
; operated by WIDE
;
.                        3600000      NS    M.ROOT-SERVERS.NET.
M.ROOT-SERVERS.NET.      3600000      A     202.12.27.33
M.ROOT-SERVERS.NET.      3600000      AAAA  2001:dc3::35
; End of File
}}}

{{op1{6. 顯示 /etc/bind/named.conf.local 檔案內容}}}
''$ cat /etc/bind/named.conf.local''
{{{
//
// Do any local configuration here
//

// Consider adding the 1918 zones here, if they are not used in your
// organization
//include "/etc/bind/zones.rfc1918";
}}}

<<toBalaNotes "bind">>

///%bind
//%/
{{item1{Adding an IPv6 IP}}}

To bind IPv6 IPs to your Ubuntu server, edit your /etc/network/interfaces file and add the following lines to the bottom.
{{{
#IPV6 configuration
iface eth1 inet6 static
pre-up modprobe ipv6
address 2607:f0d0:2001:0000:0000:0000:0000:0010
netmask 64
gateway 2607:f0d0:2001:0000:0000:0000:0000:0001
}}}

The first line tells the system which interface to use IPv6 on.
The second line tells the system to load the module for IPv6.
The third line gives the IPv6 address.
The fourth line defines the netmask for the IPv6 subnet.
The fifth line defines the default gateway for the IPv6 subnet.

After this has been performed you will need to restart networking:
{{{
/etc/init.d/networking restart
Verifying IPv6 connectivity
}}}

''Verify IPv6 IP is bound''
{{{
root@server:~# ip -6 address show eth1
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qlen 1000
    inet6 2607:f0d0:2001::/64 scope global
       valid_lft forever preferred_lft forever
    inet6 fe80::230:48ff:fe7e:330a/64 scope link
       valid_lft forever preferred_lft forever
root@server:~#
}}}

''IPv6 Neighbor Cache''
{{{
root@server:~# ip -6 neighbor show dev eth1
2607:f0d0:2001::1 lladdr 00:1b:0d:e6:57:c0 router REACHABLE
root@server:~#
}}}
If the neighbor cache shows a fe80 entry only then your gateway is either not set, the IP is not bound to the correct interface, the IP is not bound correctly to the public interface, or your software firewall is blocking IPv6 ICMP.


''IPv6 Default Gateway''
{{{
root@server:~# ip -6 route show dev eth1
2607:f0d0:2001::/64  proto kernel  metric 256  mtu 1500 advmss 1440 hoplimit 4294967295
fe80::/64  proto kernel  metric 256  mtu 1500 advmss 1440 hoplimit 4294967295
default via 2607:f0d0:2001::1  metric 1024  mtu 1500 advmss 1440 hoplimit 4294967295
root@server:~#
}}}
If you do not have the default gateway listed, yet you can ping6 your default gateway then you may add it manually:
{{{
root@server:~# ip -6 route add default via 2607:f0d0:2001::1
root@server:~#
}}}

<<toBalaNotes "1">>

Here's what I do for my system with a static IPv6 address:
{{{
    iface eth0 inet6 static
	address <system_ipv6_addr>
	netmask 64
	gateway <rtr_ipv6_addr>
	# disable IPv6 address auto-configuration
	pre-up /sbin/sysctl -w net.ipv6.conf.eth0.autoconf=0
	# disable IPv6 acceptance of default router in RA
	pre-up /sbin/sysctl -w net.ipv6.conf.eth0.accept_ra_defrtr=0
	dns-nameservers <dns_ipv6_addr_1> <dns_ipv6_addr_2>
	dns-options edns0
}}}
I'm ignoring the router address in the RA because I'm a net guy & know what
router I want to use.  Most systems would not set the gateway & would accept
the router address in the RA by not setting
net.ipv6.conf.eth0.accept_ra_defrtr=0.


{{item1{設定檔內容}}}
{{{
$ cat /etc/network/interfaces 
# This file describes the network interfaces available on your system 
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface

auto lo
iface lo inet loopback

# The primary network interface
auto eth0
#iface eth0 inet static
#  address 192.168.100.188
#  netmask 255.255.255.0
#  gateway 192.168.100.252

iface eth0 inet6 static
  address 2012::188
  netmask 64

up ip -6 route add fd00:155::/64 via 2012::155 dev eth0
up ip -6 route add fd00:166::/64 via 2012::166 dev eth0

auto eth1
#iface eth1 inet static
#  address 192.168.188.254
#  netmask 255.255.255.0

iface eth1 inet6 static
  address fd00:188::254
  netmask 64
}}}

{{item1{TOTD}}}

''TOTD 安裝''
{{{
$ sudo apt-get install totd
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Suggested packages:
  resolvconf
The following NEW packages will be installed:
  totd
0 upgraded, 1 newly installed, 0 to remove and 6 not upgraded.
Need to get 57.5 kB of archives.
After this operation, 254 kB of additional disk space will be used.
Get:1 http://tw.archive.ubuntu.com/ubuntu/ precise/universe totd i386 1.5.1-1.1 [57.5 kB]
Fetched 57.5 kB in 1s (50.7 kB/s)
Preconfiguring packages ...
Selecting previously unselected package totd.
(Reading database ... 44850 files and directories currently installed.)
Unpacking totd (from .../totd_1.5.1-1.1_i386.deb) ...
Processing triggers for man-db ...
Processing triggers for ureadahead ...
Setting up totd (1.5.1-1.1) ...
Starting totd: totd.
}}}

{{item1{tayga}}}

''Tayga 安裝''
{{{
$ sudo apt-get install tayga
[sudo] password for student: 
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following NEW packages will be installed:
  tayga
0 upgraded, 1 newly installed, 0 to remove and 6 not upgraded.
Need to get 36.4 kB of archives.
After this operation, 129 kB of additional disk space will be used.
Get:1 http://tw.archive.ubuntu.com/ubuntu/ precise/universe tayga i386 0.9.2-3 [36.4 kB]
Fetched 36.4 kB in 7s (4,581 B/s)
Selecting previously unselected package tayga.
(Reading database ... 44839 files and directories currently installed.)
Unpacking tayga (from .../tayga_0.9.2-3_i386.deb) ...
Processing triggers for ureadahead ...
ureadahead will be reprofiled on next reboot
Processing triggers for man-db ...
Setting up tayga (0.9.2-3) ...
 * tayga disabled, please adjust the configuration to your needs 
 * and then set RUN to 'yes' in /etc/default/tayga to enable it.
}}}

///%1
//%/
''參考文章''
1. SAMBA smbpasswd 與 passwd 的同步設定
http://www.pigo.idv.tw/archives/6
2. Chapter 18 - Samba (非常完整)
http://www.brennan.id.au/18-Samba.html
3. Learn Linux, 302 (Mixed environments): Managing user accounts and groups
http://www.ibm.com/developerworks/linux/library/l-lpic3-313-1/index.html
4. How to Create Samba (Windows) Shares in Linux the Easy Way (Samba 圖形管理工具)
http://www.howtogeek.com/74459/how-to-create-samba-windows-shares-in-linux-the-easy-way/

{{item1{建置部門共用資料夾}}}

''1. 建立使用者帳號''
{{{
$ sudo useradd -m -s /bin/bash a01
$ sudo useradd -m -s /bin/bash b01
$ sudo useradd -m -s /bin/bash c01
$ sudo useradd -m -s /bin/bash c02
}}}

''2. 建立 sale 群組''
{{{
$ sudo groupadd sale
}}}

''3. 將 c01 及 c02 加入 sale 群組''
{{{
$ sudo usermod -a -G sale c01
$ sudo usermod -a -G sale c02

$ sudo cat /etc/group | grep sale
sale:x:1006:c01,c02
}}}

''4. 建立 Samba 帳號''
{{{
$ sudo smbpasswd -a a01
New SMB password:
Retype new SMB password:
Added user a01.
student@myds:~$ sudo smbpasswd -a b01
New SMB password:
Retype new SMB password:
Added user b01.
student@myds:~$ sudo smbpasswd -a c01
New SMB password:
Retype new SMB password:
Added user c01.
student@myds:~$ sudo smbpasswd -a c02
New SMB password:
Retype new SMB password:
Added user c02.
}}}

''5. 建立部門共用資料夾 ( /home/sale)''
{{{
$ sudo mkdir /home/sale
$ ll /home/
總計 40
                 :
drwxr-xr-x  2 root    root    4096  9月 18 13:15 sale/
}}}

''6. 設定 /home/sale 目錄權限''
{{{
$ sudo chown student:sale /home/sale
$ sudo chmod 775 /home/sale
}}}

''7. 設定 Samba''
{{{
$ sudo nano /etc/samba/smb.conf 
[global]
workgroup = IT100
wins server = 10.0.3.5
netbios name = IT100FS
server string = IT100 File Server

# Backup Browser
# preferred master = yes

browse list = yes
dns proxy = no

# 取消印表機共享功能
printcap name = /dev/null
load printers = no
printing = bsd

name resolve order = wins hosts bcast

log file = /var/log/samba/log.%m
max log size = 1000
syslog = 2
security = user

[sale]
  path = /home/sale
  read list = a01, b01
  write list = @sale
}}}

''7. 重新啟動 smbd''
{{{
$ sudo restart smbd
}}}

<<toBalaNotes "1">>

{{item1{在 Windows 系統, 使用部門共用資料夾}}}

''1. 連接部門共用資料夾''

[img[img/sambauser01.png]]


''2. 在 Samba 伺服器, 檢視連接資訊''
{{{

$ smbstatus -v
using configfile = /etc/samba/smb.conf

Samba version 3.6.3
PID     Username      Group         Machine                        
-------------------------------------------------------------------
Opened /var/run/samba/connections.tdb

Service      pid     machine       Connected at
-------------------------------------------------------
sale         404   w2k302        Tue Sep 18 13:53:42 2012

Locked files:
Pid          Uid        DenyMode   Access      R/W        Oplock           SharePath   Name   Time
--------------------------------------------------------------------------------------------------
404          1004       DENY_NONE  0x100081    RDONLY     NONE             /home/sale   .   Tue Sep 18 13:53:45 2012
404          1004       DENY_NONE  0x100081    RDONLY     NONE             /home/sale   .   Tue Sep 18 13:53:45 2012
}}}

<<toBalaNotes "2">>

{{item1{Permission precedence}}}
本文網址 : http://www.cyberciti.biz/tips/how-do-i-set-permissions-to-samba-shares.html
Samba comes with different types of permissions for share. Try to remember few things about UNIX and Samba permissions.

''(a)'' Linux system permissions take precedence over Samba permissions. For example if a directory does not have Linux ''write permission'', setting samba writeable = Yes (see below) will not allow to write to shared directory / share.

''(b)'' The filesystem permission cannot be take priority over Samba permission. For example if filesystem mounted as readonly setting writeable = Yes will not allow to write to any shared directory or share via samba server.

Limits set by kernel-level access control such as file permissions, file system mount options, ACLs, and SELinux policies cannot be overridden by Samba. Both the kernel and Samba must permit the user to perform an action on a file before that action can occur.

''[註]'' Samba 權限設定無法, 覆蓋 Linux system permissions 及 The filesystem permission

{{item1{設定新增檔案及目錄權限}}}

''強制設定檔案權限為 0770''
{{{
create mask = 0770
force create mode = 0770
}}}

''強制設定目錄權限為 0770''
{{{
directory mask = 0770
force directory mode = 0770
}}}

<<toBalaNotes "3">>
{{item1{Samba 與 Linux 帳號同步}}}
First, install the ''libpam-smbpass'' package which will sync the system users to the Samba user database:
{{{
sudo apt-get install libpam-smbpass      # 需要同步才需安裝此套件
}}}
If you chose the Samba Server task during installation libpam-smbpass is already installed.

''[注意]''
''libpam-smbpass 安裝後並不會自動將 Linux 帳號資訊, 匯入到 Samba 帳號資料庫, 請看以下說明'' 
{{{
Dear actionparsnip,

libpam-smbpass synchronizes between the UNIX user accounts and the Samba passwords.

The problem is that the UNIX passwords are not migrated into the Samba
passwords all at once. From comments in the configuration files I've
found that password synchs are done at specific triggers like changing a
user's password with passwd.

What I'm asking is if this is indeed true and whether there's a built-in method to synch all the passwords at once.
}}}

''限制使用者的讀寫權限''
{{{
1. 在分享目錄中設定全部的權限
    writeable=no  不可寫 read only=yes
    writeable=yes 可讀

2. 在分享目錄中設定某些人的權限
    write list=  使用者名稱,@群組名稱
    read list=   使用者名稱,@群組名稱
}}}

''限制某一些使用者不可以登錄''
{{{
invalid users=使用者名稱
valid users=使用者名稱
}}}

''限制某些主機可否登入''
{{{
hosts allow= 150.203. except 150.203.6.66
hosts allow= 150.203.15.0/255.255.255.0
}}}


///%1
//%/

///%2
//%/

///%3
//%/
本文網址 : http://brneurosci.org/linuxsetup107.html 

在 ''個人網站虛擬目錄'' (/home/profx/public_html), 啟動檔案上載功能,  public_html 目錄必須要有寫入 (write) 的權限

{{op1{Step 1: Edit httpd.conf or .htaccess}}}
Add the following lines to the ''httpd-userdir.conf'' file:
{{{
<Directory /home/*/public_html>
                      :
   AddHandler php5-script php 
   DirectoryIndex index.html index.php  
   AddType application/x-httpd-php .php .htm .html
</Directory>
}}}

{{op1{Step 2: Make sure inline php is working}}}
產生 PHP 測試網頁, 如下
{{{
<html>
<head></head>
<body>
Test of inline php
<br />
<?php echo "This line will be visible if inline php is working on this server.";?> 
</body>
</html>
}}}

{{op1{Step 3: Create the upload form}}}
Here is a complete upload form (upload.html). A real form would also have a more complete doctype header, including a line for the css page to control the formatting, but this example still works.

{{{
<html>
<head></head>
<body>
<h4> File uploads </h4>
<form enctype="multipart/form-data" action="upload.php" method="post">
<p>
Select File:
<input type="file" size="35" name="uploadedfile" />
<br/>
<input type="submit" name="Upload" value="Upload" />
</p>
</form>
</body>
</html>
}}}

{{op1{Step 4: Create the php script}}}
Here is a minimal but functional php script (upload.php) for uploading a file.

{{{
<?php

$target_path = "/home/profx/public_html/";
$target_path = $target_path . basename( $_FILES['uploadedfile']['name']); 

echo "Source=" .        $_FILES['uploadedfile']['name'] . "<br />"; 
echo "Target path=" .   $target_path . "<br />"; 
echo "Size=" .          $_FILES['uploadedfile']['size'] . "<br />"; 

if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
    echo "The file ".  basename( $_FILES['uploadedfile']['name']). 
    " has been uploaded";
} else{
    echo "There was an error uploading the file, please try again!";
}
?>
}}}

''[註]'' 有些類型的檔案無法上載 (*.exe,..)


{{item1{設定 Tomcat Web Application Manager 的管理帳號}}}
1. 停止 Tomcat
2. 修改 %CATALINA_HOME%\conf 目錄中的 tomcat-users.xml, 修改如下 :

<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
''<role rolename="manager"/>
<user username="tomcat" password="tomcat" roles="manager"/>''
</tomcat-users>

3. 重新啟動 Tomcat, 然後登入 Tomcat Web Application Manager

4. 登入後, 畫面如下 :

[img[img/tomcat/tomcatwebman.png]]

<<toBalaNotes "setup">>




///%setup
//%/
''參考文章''
1. Running several name-based web sites on a single IP address.
http://httpd.apache.org/docs/2.2/vhosts/examples.html

每一部主機都有一個首頁,但是如果每個使用者都想要有可以自己完全控管的首頁時, 那該如何設計?呵呵!Apache 早就幫我們想到了!

''1. 啟動 mod_userdir 動態模組''
{{{
$ sudo a2enmod userdir
Enabling module userdir.
Run '/etc/init.d/apache2 restart' to activate new configuration!
}}}

''2. 修改 /etc/apache2/httpd.conf 設定檔內容''
{{{
$ sudo nano /etc/apache2/httpd.conf
}}}

修改內容如下 : 
{{{
# Settings for user home directories
#
# Required module: mod_userdir   (a2enmod 命令啟動)
#
# UserDir: The name of the directory that is appended onto a user's home
# directory if a ~user request is received.  Note that you must also set
# the default access control for these directories, as in the example below.
#
UserDir www    

<Directory /home/*/www>
    AllowOverride FileInfo AuthConfig Limit Indexes
    Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec

    # If GET is used it will also restrict HEAD requests. The TRACE method cannot be limited.
    <Limit GET POST OPTIONS>
        Order allow,deny
        Allow from all
    </Limit>

    <LimitExcept GET POST OPTIONS>
        Order deny,allow
        Deny from all
    </LimitExcept>
</Directory>
}}}
上面設定將預設的個人首頁, 放置在家目錄下的 www/ 目錄下!假如 tobala 的家目錄在 /home/tobala,那麼他的個人首頁預設在 /home/tobala/www/ 囉!你當然可以修改這個目錄名稱, 只要將上表的 UserDir 後面內容改掉即可。例如改為 www 時,使用者的個人首頁則放在家目錄下的 www 目錄中。 設定完畢後得要重新啟動你的 apache 喔!
{{{
$ sudo /etc/init.d/apache2 restart
 * Restarting web server apache2                                                 
... waiting                                                             [ OK ]
}}}

''[問題]'' 如何讓未來所有『新增』的使用者預設家目錄下都有個 www 的目錄?

''答:'' 因為新增使用者時會將 /etc/skel 目錄內所有內容複製到你的家目錄,所以你可以直接 mkdir /etc/skel/www 即可。 

好了,假設你的主機有個 student 的用戶,那麼這傢伙怎麼建立他的個人首頁? 我們這樣測試一下好了!(底下的工作請以你的一般身份使用者處理):
{{{
$ su student
$ cd ~
$ mkdir www
$ chmod 755 www
$ echo "Test your home" >  www/index.html
}}}

你的 www 目錄權限成為 drwxr-xr-x 才行!這個很重要啊! 那麼未來只要你在瀏覽器的網址列這樣輸入:
{{{
http://Apache Server IP/~student/
}}}

''[問題]'' 如將 index.html 檔案刪除, 此時瀏覽結果如何 ?

不過,多這個毛毛蟲就很討厭~ 我可不可以將使用者的個人網站設定成為:
{{{
http://Apache Server IP/student/
}}}

是可以啦!最簡單的方法是這樣的:
{{{
$ cd /var/www
$ sudo ln -s /home/student/www student
}}}

''[註]'' 如上述命令中的目錄名稱打錯, 瀏覽時會出現 "You don't have permission to access /student on this server." 這樣的錯誤訊息

<<toBalaNotes "1">>

///%1
//%/

///%2
//%/

///%3
//%/

///%4
//%/
''參考文章''
1. Sending HEAD requests with ext/curl
http://schlitt.info/opensource/blog/0606_sending_head_requests_with_extcurl.html

{{item1{AllowOverride}}}
{{{
<Directory /home/*/www>
    AllowOverride FileInfo AuthConfig Limit Indexes
                           :
</Directory>
}}}

是否允許額外設定檔 .htaccess 的權限複寫?我們可以在 httpd.conf 內設定好所有的權限,不過如此一來若使用者自己的個人網頁想要修改權限時將會對管理員造成困擾。因此 Apache 預設可以讓使用者以目錄底下的 .htaccess 檔案內複寫 <Directory> 內的權限設定。 這個項目則是在規定 .htaccess 可以複寫的權限類型有哪些。常見的有:
{{{
* ALL:全部的權限均可被複寫;
* AuthConfig:僅有網頁認證 (帳號密碼) 可複寫;
* Indexes:僅允許 Indexes 方面的複寫;
* Limits:允許使用者利用 Allow, Deny 與 Order 管理可瀏覽的權限;
* None:不可複寫,亦即 .htaccess 檔案失效去!
}}}

{{item1{<Limit> 與 <LimitExcept>}}}

''<Limit>'' 主要是限制指定的 HTTP 命令, 如下例, 命令是 POST, PUT 及 DELETE, 必須要認證後才可使用, 而沒有指定的命令, 則不需要認證, 所以沒有指定的命令, 需要透過 ''<LimitExcept>'' 來規範
{{{
<Limit POST PUT DELETE>
Require valid-user
</Limit>
}}}
''[註]'' 
The method names listed can be one or more of: GET, POST, PUT, DELETE, CONNECT, OPTIONS, PATCH, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, and UNLOCK. The method name is case-sensitive. If GET is used it will also restrict HEAD requests. The TRACE method cannot be limited.

''<LimitExcept>'' 主要是限制不在指定的 HTTP 命令,如下例, 命令是 POST, PUT 及 DELETE, 不需要認證, 但其他命令則必需認證後才可使用
{{{
<LimitExcept POST GET>
Require valid-user
</LimitExcept> 
}}}

{{item1{實作 : 限制 HTTP 命令}}}
''以下實作無法在 Firefox 5 以後版本執行''

1. 使用 Firefox 開啟 ''Linux2008\ajax\AjaxCall.htm'' 網頁

2. 在 Method 欄位, 輸入 GET, 然後在 URL 欄位, 輸入 "http://Apache Server IP/~student"

3. 執行結果, 如下圖 :

[img[img/apache2/ap2test01.png]]

4. 在 Method 欄位, 輸入 HEAD, 執行結果, 如下圖 :

[img[img/apache2/ap2test02.png]]

5. 修改 /etc/apache2/httpd.conf  設定檔

在 <Limit> 及 <LimitExcept> 設定段, 請移除 GET 命令
{{{
               : 
    <Limit POST OPTIONS>
        Order allow,deny
        Allow from all
    </Limit>

    <LimitExcept POST OPTIONS>
        Order deny,allow
        Deny from all
    </LimitExcept>
}}}

''[註]'' If ''GET'' is used it will also restrict ''HEAD'' requests. The ''TRACE'' method cannot be limited.

6. 重新啟動 Apache 2, 再一次執行 HEAD 命令, 會出現錯誤訊息, 結果如下 :

[img[img/apache2/ap2test03.png]]
<<toBalaNotes "2">>

{{item1{Order}}}
''The Order directive, along with the Allow and Deny directives, controls a @@color:red;three-pass@@ access control system''. The first pass processes either all Allow or all Deny directives, as specified by the Order directive. The second pass parses the rest of the directives (Deny or Allow). The third pass applies to all requests which do not match either of the first two.

''[註]'' that all Allow and Deny directives are processed, unlike a typical firewall, where only the first match is used. The last match is effective (also unlike a typical firewall). Allow 及 Deny 命令均要檢查, 最後一個符合條件生效

Additionally, the order in which lines appear in the configuration files is not significant -- all Allow lines are processed as one group, all Deny lines are considered as another, and the default state is considered by itself.

Ordering is one of: (以下說明一定要看)

''Allow,Deny''
''First'', all Allow directives are evaluated; at least one must match, or the request is rejected. ''Next'', all Deny directives are evaluated. If any matches, the request is rejected. ''Last'', any requests which do not match an Allow or a Deny directive are ''denied (拒絕)'' by default.

''Deny,Allow''
''First'', all Deny directives are evaluated; if any match, the request is denied unless it also matches an Allow directive. Any requests which do not match any Allow or Deny directives are ''permitted (允許)''.

''Mutual-failure''
This order has the same effect as Order Allow,Deny and is deprecated in its favor. 

In the following example, all hosts in the apache.org domain are allowed access; all other hosts are denied access.
{{{
Order Deny,Allow
Deny from all
Allow from apache.org
}}}
In the next example, all hosts in the apache.org domain are allowed access, except for the hosts which are in the foo.apache.org subdomain, who are denied access. All hosts not in the apache.org domain are denied access because the default state is to Deny access to the server.
{{{
Order Allow,Deny
Allow from apache.org
Deny from foo.apache.org
}}}
On the other hand, if the Order in the last example is changed to Deny,Allow, all hosts will be allowed access. This happens because, regardless of the actual ordering of the directives in the configuration file, the Allow from apache.org will be evaluated last and will override the Deny from foo.apache.org. All hosts not in the apache.org domain will also be allowed access because the default state is Allow.

The presence of an Order directive can affect access to a part of the server even in the absence of accompanying Allow and Deny directives because of its effect on the default access state. For example,
{{{
<Directory /www>
   Order Allow,Deny
</Directory> 
}}}
''will Deny all access to the /www directory because the default access state is set to Deny''.

The Order directive controls the order of access directive processing only within each phase of the server's configuration processing. This implies, for example, that an Allow or Deny directive occurring in a <Location> section will always be evaluated after an Allow or Deny directive occurring in a <Directory> section or .htaccess file, regardless of the setting of the Order directive. For details on the merging of configuration sections, see the documentation on How Directory, Location and Files sections work.

<<toBalaNotes "3">>
{{item1{限制連接主機}}}

1. 修改 /etc/apache2/httpd.conf  設定檔, 如下 :
{{{
<Directory /home/*/www>
                  :
    <Limit GET POST OPTIONS>
        Order allow,deny
        Allow from all
	Deny from 192.168.56.1   
    </Limit>
                  :
</Directory>
}}}

2. 在 Method 欄位, 輸入 HEAD, 執行結果, 會出現錯誤訊息, 如下圖 :

[img[img/apache2/ap2test04.png]]

<<toBalaNotes "4">>

{{item1{使用 Linux curl 命令, 直接下達 HTTP 命令 (HEAD,OPTIONS,GET,POST)}}}

''下達 HEAD 命令''
{{{
$ curl -i -X HEAD http://www.it49.kvm
HTTP/1.1 200 OK
Date: Sun, 09 Sep 2012 16:59:40 GMT
Server: Apache/2.2.22 (Ubuntu)
Last-Modified: Sun, 09 Sep 2012 16:04:42 GMT
ETag: "4078c-b1-4c946ffbbed43"
Accept-Ranges: bytes
Content-Length: 177
Vary: Accept-Encoding
Content-Type: text/html
X-Pad: avoid browser bug

curl: (18) transfer closed with 177 bytes remaining to read
}}}

''下達 OPTIONS 命令''
{{{
$ curl -i -X OPTIONS http://www.it49.kvm
HTTP/1.1 200 OK
Date: Sun, 09 Sep 2012 17:00:11 GMT
Server: Apache/2.2.22 (Ubuntu)
Allow: GET,HEAD,POST,OPTIONS
Vary: Accept-Encoding
Content-Length: 0
Content-Type: text/html
}}}

''下達 POST 命令''
{{{
$ curl -i -X POST http://www.it49.kvm
HTTP/1.1 200 OK
Date: Sun, 09 Sep 2012 17:00:34 GMT
Server: Apache/2.2.22 (Ubuntu)
Last-Modified: Sun, 09 Sep 2012 16:04:42 GMT
ETag: "4078c-b1-4c946ffbbed43"
Accept-Ranges: bytes
Content-Length: 177
Vary: Accept-Encoding
Content-Type: text/html
X-Pad: avoid browser bug

<html><body><h1>It works!</h1>
<p>This is the default web page for this server.</p>
<p>The web server software is running but no content has been added, yet.</p>
</body></html>
}}}

''下達 GET 命令''
{{{
$ curl -i -X GET http://www.it49.kvm
HTTP/1.1 200 OK
Date: Sun, 09 Sep 2012 17:00:52 GMT
Server: Apache/2.2.22 (Ubuntu)
Last-Modified: Sun, 09 Sep 2012 16:04:42 GMT
ETag: "4078c-b1-4c946ffbbed43"
Accept-Ranges: bytes
Content-Length: 177
Vary: Accept-Encoding
Content-Type: text/html
X-Pad: avoid browser bug

<html><body><h1>It works!</h1>
<p>This is the default web page for this server.</p>
<p>The web server software is running but no content has been added, yet.</p>
</body></html>
}}}

///%2
//%/

///%3
//%/

///%4
//%/
The DNS configuration files are stored in the ''/etc/bind'' directory. The primary configuration file is ''/etc/bind/named.conf''.

The include line specifies the filename which contains the DNS options. The directory line in the ''/etc/bind/named.conf.options'' file tells DNS where to look for files. All files BIND uses will be relative to this directory.

The file named ''/etc/bind/db.root'' describes the root nameservers in the world. The servers change over time, so the ''/etc/bind/db.root'' file must be maintained now and then. This is usually done as updates to the bind9 package. The zone section defines a master server, and it is stored in a file mentioned in the file option.

It is possible to configure the same server to be a ''caching name server'', ''primary master'', and ''secondary master''. A server can be the Start of Authority (SOA) for one zone, while providing secondary service for another zone. All the while providing caching services for hosts on the local LAN.

{{item1{Caching Nameserver}}}
The default configuration is setup to act as a caching server. All that is required is simply adding the IP Addresses of your ISP's DNS servers. Simply uncomment and edit the following in ''/etc/bind/named.conf.options'':
{{{
forwarders {
                1.2.3.4;
           };
}}}

''[註]'' Replace 1.2.3.4 with the IP Adresses of actual nameservers (168.95.1.1). 所謂的 forwarder,就是當某一台 DNS 遇到非本機負責的 Zone 之查詢請求的時候,將不直接向 Root Server 查詢,而把請求轉交給指定的另一台 DNS 主機(forwarder)代為查詢。 

''重新啟動 DNS Server''
{{{
$ sudo service bind9 restart

      or

$ sudo /etc/init.d/bind9 restart
}}}

{{item1{測試 DNS Server}}}
{{{
# nslookup
> server                                    # 確定是自己安裝的 DNS IP 位址, 如不是請執行 server 'DNS IP', 切換到自己安裝的 DNS Server, 這樣 DNS 的 Cache 才會有資料
Default server : 172.23.100.8
Address: 172.23.100.8
> set type=any
> hinet.net.
Server:		172.30.100.2
Address:	172.30.100.2#53

Non-authoritative answer:
hinet.net	nameserver = ans1.hinet.net.
hinet.net	nameserver = ans2.hinet.net.
hinet.net	mail exchanger = 10 netnews.hinet.net.

Authoritative answers can be found from:
hinet.net	nameserver = ans1.hinet.net.
hinet.net	nameserver = ans2.hinet.net.
ans1.hinet.net	internet address = 168.95.192.15
ans2.hinet.net	internet address = 168.95.1.15
netnews.hinet.net	internet address = 168.95.195.16
> exit
}}}

{{item1{檢視 DNS Server Cache 內容}}}
確定有在自己安裝的 DNS Server 查詢過資料, 這樣 DNS 的 Cache 才會有資料
{{{
$ sudo rndc dumpdb  -cache
$ ls -al /var/cache/bind
總計 16
drwxrwxr-x 2 root bind 4096 2009-08-24 23:27 .
drwxr-xr-x 8 root root 4096 2009-08-23 10:15 ..
-rw-r--r-- 1 bind bind 6294 2009-08-24 23:29 named_dump.db

$ cat /var/cache/bind/named_dump.db   
     1  ;
     2  ; Start view _default
     3  ;
     4  ;
     5  ; Cache dump of view '_default'
     6  ;
     7  $DATE 20090824152927
     8  ; authanswer
     9  .                       517634  IN NS   A.ROOT-SERVERS.NET.
    10                          517634  IN NS   B.ROOT-SERVERS.NET.
    11                          517634  IN NS   C.ROOT-SERVERS.NET.
    12                          517634  IN NS   D.ROOT-SERVERS.NET.
    13                          517634  IN NS   E.ROOT-SERVERS.NET.
    14                          517634  IN NS   F.ROOT-SERVERS.NET.
    15                          517634  IN NS   G.ROOT-SERVERS.NET.
    16                          517634  IN NS   H.ROOT-SERVERS.NET.
    17                          517634  IN NS   I.ROOT-SERVERS.NET.
    18                          517634  IN NS   J.ROOT-SERVERS.NET.
    19                          517634  IN NS   K.ROOT-SERVERS.NET.
    20                          517634  IN NS   L.ROOT-SERVERS.NET.
    21                          517634  IN NS   M.ROOT-SERVERS.NET.
    22  ; glue
    23  net.                    172034  NS      A.GTLD-SERVERS.net.
    24                          172034  NS      B.GTLD-SERVERS.net.
    25                          172034  NS      C.GTLD-SERVERS.net.
    26                          172034  NS      D.GTLD-SERVERS.net.
    27                          172034  NS      E.GTLD-SERVERS.net.
    28                          172034  NS      F.GTLD-SERVERS.net.
    29                          172034  NS      G.GTLD-SERVERS.net.
    30                          172034  NS      H.GTLD-SERVERS.net.
    31                          172034  NS      I.GTLD-SERVERS.net.
    32                          172034  NS      J.GTLD-SERVERS.net.
    33                          172034  NS      K.GTLD-SERVERS.net.
    34                          172034  NS      L.GTLD-SERVERS.net.
    35                          172034  NS      M.GTLD-SERVERS.net.
    36  ; glue
    37  A.GTLD-SERVERS.net.     172034  A       192.5.6.30
    38  ; glue
    39                          172034  AAAA    2001:503:a83e::2:30
    40  ; glue
    41  B.GTLD-SERVERS.net.     172034  A       192.33.14.30
    42  ; glue
    43                          172034  AAAA    2001:503:231d::2:30
    44  ; glue
    45  C.GTLD-SERVERS.net.     172034  A       192.26.92.30
    46  ; glue
    47  D.GTLD-SERVERS.net.     172034  A       192.31.80.30
    48  ; glue
                                                     :
    64  ; glue
    65  M.GTLD-SERVERS.net.     172034  A       192.55.83.30
    66  ; authauthority
    67  hinet.net.              85634   NS      dns.hinet.net.
    68                          85634   NS      hntp1.hinet.net.
    69                          85634   NS      hntp3.hinet.net.
    70  ; glue
    71  dns.hinet.net.          172034  A       168.95.1.1
    72  ; glue
    73  hntp1.hinet.net.        172034  A       168.95.192.1
    74  ; glue
    75  hntp3.hinet.net.        172034  A       168.95.192.2
    76  ; authanswer
    77  www.hinet.net.          85634   A       61.219.38.89
    78                          85634   A       203.66.88.89
    79  ; additional
    80  A.ROOT-SERVERS.net.     604034  A       198.41.0.4
    81  ; additional
    82                          604034  AAAA    2001:503:ba3e::2:30
    83  ; additional
    84  B.ROOT-SERVERS.net.     604034  A       192.228.79.201
    85  ; additional
    86  C.ROOT-SERVERS.net.     604034  A       192.33.4.12
    87  ; additional
    88  D.ROOT-SERVERS.net.     604034  A       128.8.10.90
    89  ; additional
    90  E.ROOT-SERVERS.net.     604034  A       192.203.230.10
    91  ; additional
    92  F.ROOT-SERVERS.net.     604034  A       192.5.5.241
    93  ; additional
    94                          604034  AAAA    2001:500:2f::f
    95  ; additional
    96  G.ROOT-SERVERS.net.     604034  A       192.112.36.4
    97  ; additional
    98  H.ROOT-SERVERS.net.     604034  A       128.63.2.53
    99  ; additional
   100                          604034  AAAA    2001:500:1::803f:235
   101  ; additional
   102  I.ROOT-SERVERS.net.     604034  A       192.36.148.17
   103  ; additional
   104  J.ROOT-SERVERS.net.     604034  A       192.58.128.30
   105  ; additional
   106                          604034  AAAA    2001:503:c27::2:30
   107  ; additional
   108  K.ROOT-SERVERS.net.     604034  A       193.0.14.129
   109  ; additional
   110                          604034  AAAA    2001:7fd::1
   111  ; additional
   112  L.ROOT-SERVERS.net.     604034  A       199.7.83.42
   113  ; additional
   114                          604034  AAAA    2001:500:3::42
   115  ; additional
   116  M.ROOT-SERVERS.net.     604034  A       202.12.27.33
   117  ; additional
   118                          604034  AAAA    2001:dc3::35
   119  ; authauthority
   120  www.                    10352   \-ANY   ;-$NXDOMAIN
   121  ;
   122  ; Address database dump
   123  ;
   124  ; A.ROOT-SERVERS.NET [v4 TTL 85633] [v6 TTL 85633] [v4 success] [v6 success]
   125  ;       198.41.0.4 [srtt 6] [flags 00000000] [ttl 1352]
   126  ;       2001:503:ba3e::2:30 [srtt 4] [flags 00000000] [ttl 1352]
   127  ; C.ROOT-SERVERS.NET [v4 TTL 85633] [v4 success] [v6 unexpected]
   128  ;       192.33.4.12 [srtt 9] [flags 00000000] [ttl 1352]
   129  ; E.ROOT-SERVERS.NET [v4 TTL 85633] [v4 success] [v6 unexpected]
   130  ;       192.203.230.10 [srtt 11] [flags 00000000] [ttl 1352]
   131  ; G.ROOT-SERVERS.NET [v4 TTL 85633] [v4 success] [v6 unexpected]
   132  ;       192.112.36.4 [srtt 47994] [flags 00000000] [ttl 1352]
   133  ; I.ROOT-SERVERS.NET [v4 TTL 85633] [v4 success] [v6 unexpected]
   134  ;       192.36.148.17 [srtt 1] [flags 00000000] [ttl 1352]
   135  ; K.ROOT-SERVERS.NET [v4 TTL 85633] [v6 TTL 85633] [v4 success] [v6 success]
   136  ;       193.0.14.129 [srtt 5] [flags 00000000] [ttl 1352]
   137  ;       2001:7fd::1 [srtt 14] [flags 00000000] [ttl 1352]
   138  ; M.ROOT-SERVERS.NET [v4 TTL 85633] [v6 TTL 85633] [v4 success] [v6 success]
   139  ;       202.12.27.33 [srtt 18] [flags 00000000] [ttl 1352]
   140  ;       2001:dc3::35 [srtt 27] [flags 00000000] [ttl 1352]
   141  ; B.ROOT-SERVERS.NET [v4 TTL 85633] [v4 success] [v6 unexpected]
   142  ;       192.228.79.201 [srtt 29] [flags 00000000] [ttl 1352]
   143  ; D.ROOT-SERVERS.NET [v4 TTL 85633] [v4 success] [v6 unexpected]
   144  ;       128.8.10.90 [srtt 194116] [flags 00000000] [ttl 1352]
   145  ; F.ROOT-SERVERS.NET [v4 TTL 85633] [v6 TTL 85633] [v4 success] [v6 success]
   146  ;       192.5.5.241 [srtt 19] [flags 00000000] [ttl 1352]
   147  ;       2001:500:2f::f [srtt 19] [flags 00000000] [ttl 1352]
   148  ; H.ROOT-SERVERS.NET [v4 TTL 85633] [v6 TTL 85633] [v4 success] [v6 success]
   149  ;       128.63.2.53 [srtt 16] [flags 00000000] [ttl 1352]
   150  ;       2001:500:1::803f:235 [srtt 29] [flags 00000000] [ttl 1352]
   151  ; J.ROOT-SERVERS.NET [v4 TTL 85633] [v6 TTL 85633] [v4 success] [v6 success]
   152  ;       192.58.128.30 [srtt 7] [flags 00000000] [ttl 1352]
   153  ;       2001:503:c27::2:30 [srtt 26] [flags 00000000] [ttl 1352]
   154  ; L.ROOT-SERVERS.NET [v4 TTL 85633] [v4 success] [v6 unexpected]
   155  ;       199.7.83.42 [srtt 9] [flags 00000000] [ttl 1352]
   156  ;
   157  ; Unassociated entries
   158  ;
   159  ;       168.95.192.1 [srtt 23] [flags 00000000] [ttl 1034]
   160  ;       2001:503:231d::2:30 [srtt 20] [flags 00000000] [ttl 1034]
   161  ;       192.42.93.30 [srtt 9] [flags 00000000] [ttl 1034]
   162  ;       192.33.14.30 [srtt 20] [flags 00000000] [ttl 1034]
   163  ;       2001:503:a83e::2:30 [srtt 17] [flags 00000000] [ttl 1034]
   164  ;       192.48.79.30 [srtt 17] [flags 00000000] [ttl 1034]
   165  ;       192.35.51.30 [srtt 15] [flags 00000000] [ttl 1034]
   166  ;       192.55.83.30 [srtt 14] [flags 00000000] [ttl 1034]
   167  ;       192.54.112.30 [srtt 27] [flags 00000000] [ttl 1034]
   168  ;       192.12.94.30 [srtt 15] [flags 00000000] [ttl 1034]
   169  ;       192.5.6.30 [srtt 25] [flags 00000000] [ttl 1034]
   170  ;       168.95.192.2 [srtt 50863] [flags 00000000] [ttl 1034]
   171  ;       2001:500:3::42 [srtt 3] [flags 00000000] [ttl 1352]
   172  ;       192.43.172.30 [srtt 58179] [flags 00000000] [ttl 1034]
   173  ;       192.31.80.30 [srtt 15] [flags 00000000] [ttl 1034]
   174  ;       192.26.92.30 [srtt 25] [flags 00000000] [ttl 1034]
   175  ;       192.41.162.30 [srtt 27] [flags 00000000] [ttl 1034]
   176  ;       168.95.1.1 [srtt 31] [flags 00000000] [ttl 1034]
   177  ;       192.52.178.30 [srtt 17] [flags 00000000] [ttl 1034]
   178  ;
   179  ; Start view _bind
   180  ;
   181  ;
   182  ; Cache dump of view '_bind'
   183  ;
   184  $DATE 20090824152927
   185  ;
   186  ; Address database dump
   187  ;
   188  ;
   189  ; Unassociated entries
   190  ;
   191  ; Dump complete
}}}

{{item1{清除 DNS Cache}}}
{{{
$ sudo rndc flush
}}}

''再次檢視 DNS Server Cache''
{{{
$ sudo rndc dumpdb  -cache

$ cat /var/cache/bind/named_dump.db   
;
; Start view _default
;
;
; Cache dump of view '_default' (cache _default)
;
$DATE 20100815041107
;
; Address database dump
;
;
; Unassociated entries
;
;
; Bad cache
;
;
; Start view _bind
;
;
; Cache dump of view '_bind' (cache _bind)
;
$DATE 20100815041107
;
; Address database dump
;
;
; Unassociated entries
;
;
; Bad cache
;
;
; Start view _meta
;
;
; Cache dump of view '_meta' (cache _meta)
;
$DATE 20100815041107
;
; Address database dump
;
;
; Unassociated entries
;
;
; Bad cache
;
; Dump complete
}}}
<<toBalaNotes "cachedns">>


///%cachedns
//%/
''參考文章''
1. Part1 – OPENVSWICH – Creating and Submitting Openvswitch Extension To Microcore Upstream (非常詳細)
http://brezular.wordpress.com/2011/09/03/part1-openvswich-creating-and-submitting-openvswitch-extension-to-microcore-upstream/
2. Part3 – OPENVSWICH – Campus Model with Layer2 Access, Built with Open-Source Applications (非常詳細)
http://brezular.wordpress.com/2011/11/23/part3-openvswich-campus-model-with-layer2-access-built-with-open-source-applications/

{{{
#Enable forwarding between interfaces
sysctl -w net.ipv4.ip_forward=1
sysctl -w net.ipv6.conf.all.forwarding=1
}}}

''參考文章''
1. Analyzing Apache Log Files
http://www.the-art-of-web.com/system/logs/
''參考文章''
1. preexec and postexec Scripts (登入執行檔)
http://delta.nitt.edu/books/References/Manual%20pages/linux/samba/ch10-01.htm

{{op1{1. 修改設定檔 /etc/samba/smb.conf}}}
{{{
[global]
workgroup = IT100
wins server = 10.0.3.5            # 指向 WINS Server, 如沒建置 WINS Server, 則不需此設定
netbios name = IT100FS
server string = IT100 File Server

# Backup Browser
preferred master = yes

browse list = yes
dns proxy = no

# 取消印表機共享功能
printcap name = /dev/null
load printers = no
printing = bsd

name resolve order = wins hosts bcast

log file = /var/log/samba/log.%m
max log size = 1000
syslog = 2

# 採用 Samba 自行認證模式
security = user 
guest only = no
guest ok = no

[homes]
  comment = Home Directories

  # browseable = no 這設定, 使得在網芳系統不會看到 homes 這名稱
  browseable = no

  # By default, the home directories are exported read-only. Change next
  # parameter to ‘yes’ if you want to be able to write to them.
  writable = yes

  # By default, \\server\username shares can be connected to by anyone
  # with access to the samba server. Un-comment the following parameter
  # to make sure that only “username” can connect to \\server\username
  valid users = %S

  # 符合指定格式的檔案(.*), 不會顯示
  veto files = /.*/    

  # 指定的 bin 目錄內容不會顯示
  dont descend = bin
      
  create mode = 0664
  directory mode = 0775
}}}
''[註] disable netbios = yes'' 這項設定, 會停止啟動 nmbd 服務
   
{{op1{2. 重新啟動 Samba}}}
{{{
$ sudo restart smbd     #  10.04 版的執行命令, restart 命令是由 upstart 啟動模組提供
}}}

{{op1{3. Windows 網路磁碟機}}}

[img[img/linux/msnetdrv.png]]

''在 VMware Workstation 系統中, 如無法連接, 請檢查 VMnet8 或 VMnet1 網卡是否安裝 Client for Microsoft Networks, 如下圖 :''

[img[img/linux/sambamsclient.png]]

{{op1{4. 檢視 Samba 連接資訊}}}
{{{
$ sudo smbstatus

Samba version 3.3.2
PID     Username      Group         Machine
-------------------------------------------------------------------
2756      xman01        xman01        it100-ws2003 (192.168.200.138)

Service      pid     machine       Connected at
-------------------------------------------------------
IPC$         2756   it100-ws2003  Fri Sep  4 08:17:25 2009
xman01       2756   it100-ws2003  Fri Sep  4 08:17:28 2009

Locked files:
Pid          Uid        DenyMode   Access      R/W        Oplock           SharePath   Name   Time
--------------------------------------------------------------------------------------------------
2756         1001       DENY_NONE  0x100081    RDONLY     NONE             /home/xman01   .   Fri Sep  4 08:17:28 2009

}}}
<<toBalaNotes "1">>

///%1
//%/
本文網址 : http://pro-programmers.blogspot.com/2008/05/shutdown-tomcat-from-java-program.html

I send the shutdown command to the shutdown port both of which are configured in the root element of CATALINA_HOME/conf/server.xml .

{{op1{Step(1)}}}
I configured the ''CATALINA_HOME/conf/server.xml''  as follow:
{{{
<Server port="8005" shutdown="myShutDownCommand">
}}}
The attribute port is optional. If it is omitted, the default one, 8005, is used.

The value for shutdown attribute can be anything. This should not be known by others.

{{op1{Step(2)}}}
I made the java program send the shutdown command, myShutDownCommand, using java.net.Socket class to the shutdown port, 8005.
{{{
    try {
        Socket socket = new Socket("localhost", 8005);
        if (socket.isConnected()) {
            PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
            pw.println("myShutDownCommand");//send shut down command
            pw.close();
            socket.close();
        }
    } catch (Exception e) {
        e.printStackTrace();
    } 
}}}
<<toBalaNotes "stopt">>

{{item1{使用 telnet 命令關閉 Tomcat}}}
{{{
c:\> telnet localhost 8005
SHUTDOWN         (鍵盤輸入, 一定要大寫字)
}}}
///%stopt
//%/
''參考文章''
1. Ubuntu DNS Server Guide - BIND Master Server Setup
http://www.zaphu.com/2007/09/14/ubuntu-dns-server-guide-bind-master-server-setup/
2. DNS BIND Query Statements
http://www.zytrax.com/books/dns/ch7/queries.html

{{op1{1. 檢視主設定檔 (/etc/bind/named.conf)}}}
/etc/bind/named.conf 會指出 Server 管轄的區域 (Zone) 名稱及相關檔案。

''# sudo nano /etc/bind/named.conf''
{{{
// This is the primary configuration file for the BIND DNS server named.
//
// Please read /usr/share/doc/bind9/README.Debian.gz for information on the
// structure of BIND configuration files in Debian, *BEFORE* you customize
// this configuration file.
//
// If you are just adding zones, please do that in /etc/bind/named.conf.local

include "/etc/bind/named.conf.options";
include "/etc/bind/named.conf.local";
include "/etc/bind/named.conf.default-zones";
}}}

{{op1{2. 宣告正/反解區域 (/etc/bind/named.conf.local)}}}

''$ nano /etc/bind/named.conf.local''
{{{
// 增加正解區域(Zone)
zone "kvm." {
   type master;
   file "/etc/bind/db.kvm";
};
// 增加反解區域(Zone)
zone "100.30.172.in-addr.arpa" {
   type master;
   file "/etc/bind/db.100.30.172";
};
}}}

{{op1{3. 修改 Bind 參數 (/etc/bind/named.conf.options)}}}

''# sudo nano named.conf.options''
{{{
options {
      directory "/var/cache/bind";
      forwarders {
         168.95.1.1; 139.175.10.20; 203.133.1.6;
      };
      allow-query { any; };
      allow-transfer { none; };
};
}}}

''allow-transfer'' 設為 none, 主要停止本機 DNS Server Zone 資訊傳送, 此時你無法使用以下命令, 取得本機 DNS Server Zone 資訊
{{{
$ host -l microsoft.com.             (不會成功)
; Transfer failed.
Host microsoft.com not found: 9(NOTAUTH)
; Transfer failed.

$ host -l ibm.com.                     (不會成功)
; Transfer failed.
Host ibm.com not found: 9(NOTAUTH)
; Transfer failed.

# host -l nixcraft.org                   (會成功)
nixcraft.org SOA ns1.nixcraft.org. admin.nixcraft.org. 12 10800 900 604800 86400
nixcraft.org name server ns1.nixcraft.org.
nixcraft.org mail is handled by 10 mail.nixcraft.org.
nixcraft.org has address 192.168.0.5
gw.nixcraft.org has address 192.168.0.254
mail.nixcraft.org has address 192.168.0.7
ns1.nixcraft.org has address 192.168.0.5
w2k.nixcraft.org has address 192.168.0.1
www.nixcraft.org has address 192.168.0.6
nixcraft.org SOA ns1.nixcraft.org. admin.nixcraft.org. 12 10800 900 604800 86400
}}}

''[註]'' Perform a ''zone transfer'' for zone name using -l option:

{{op1{4. 建立正解區域設定檔 (/etc/bind/db.kvm)}}}

''$ sudo nano /etc/bind/db.kvm''
{{{
; BIND data file for local loopback interface

$TTL  604800
@   IN   SOA   US104-100-RD.kvm. admin.US104-100-RD.kvm. (
            1     ; Serial
            604800     ; Refresh
            86400       ; Retry
            2419200    ; Expire
            604800 )    ; Negative Cache TTL
;
@       IN     NS     US104-100-RD.kvm.
US104-100-RD      IN     A      172.30.100.2

}}}

{{op1{5. 建立反解區域設定檔 (/etc/bind/db.100.30.172)}}}

''$ sudo nano /etc/bind/db.100.30.172''
{{{
; BIND reverse data file for local loopback interface

$TTL 604800
@       IN   SOA   US104-100-RD.kvm. admin.US104-100-RD.kvm. (
            1     ; Serial
            604800     ; Refresh
            86400       ; Retry
            2419200    ; Expire
            604800 )    ; Negative Cache TTL
    ;
@       IN     NS     US104-100-RD.kvm.
2     IN     PTR     US104-100-RD.kvm. 
}}}

{{op1{6. 檢查設定檔格式}}}
You can check zone file syntax and /etc/named.conf file using following utilities. named-checkconf command is named (BIND) configuration file syntax checking tool.

''檢查 BIND Server 設定檔 (named-checkconf)''
{{{
$ named-checkconf /etc/bind/named.conf.local 
}}}

''檢查 zone 設定檔 (named-checkzone)''
Check zone file syntax for errors. named-checkzone is zone file validity checking tool. named-checkzone checks the syntax and integrity of a zone file. It performs the same checks as named does when loading a zone. This makes named checkzone useful for checking zone files before configuring them into a name server.
{{{
$ named-checkzone kvm. /etc/bind/db.kvm
zone kvm/IN: loaded serial 1
OK
}}}

{{op1{7. 重開 DNS Server}}}
{{{
$ sudo /etc/init.d/bind9 restart
 * Stopping domain name service... bind         [ OK ]
 * Starting domain name service... bind          [ OK ]
}}}

{{item1{測試 DNS Server}}}
You can use host and dig utilties to test your bind configuration.
{{{
student@US104-100-RD:~$ dig kvm. any

; <<>> DiG 9.7.0-P1 <<>> kvm. any
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 64673
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; QUESTION SECTION:
;kvm.				IN	ANY

;; ANSWER SECTION:
kvm.			604800	IN	SOA	US104-100-RD.kvm. tobalaking.US104-100-RD.kvm. 1 604800 86400 2419200 604800
kvm.			604800	IN	NS	US104-100-RD.kvm.

;; ADDITIONAL SECTION:
US104-100-RD.kvm.	604800	IN	A	172.30.100.2

;; Query time: 7 msec
;; SERVER: 172.30.100.2#53(172.30.100.2)
;; WHEN: Sun Aug 15 16:16:19 2010
;; MSG SIZE  rcvd: 111
}}}

<<toBalaNotes "dns">>

{{item1{Intranet Root DNS Server}}}
The master file for a root zone is really no different than for any other zone. As for named.conf configuration, that isn't really much different either:

''Primary Zone 設定''
{{{
zone "." {
    type master;
    file "root";   /* Or whatever you want */
};
}}}

''Slave Zone 設定''
{{{
zone "." {
    type slave;
    file "root";          /* Or whatever */
    masters {
        x.x.x.x; /* Address of master */
        y.y.y.y; /* Address of some other slave, for redundancy */
    };
};
}}}

///%dns
//%/
I'm running apache2 on 7.10, and I update/upgrade at every opportunity.

I tried using the apache2ctl command as follows:

Code:
{{{
$0> sudo apache2ctl status
[sudo] password for rgeddes:
Forbidden

You don't have permission to access /server-status on this server.

-------------------------------------------------------------------------------------------------------------------------

Apache/2.2.4 (Ubuntu) PHP/5.2.3-1ubuntu6.3 mod_ssl/2.2.4 OpenSSL/0.9.8e Server
at localhost Port 80
}}}
You have to enable the apache URL for apache2ctl status to work. The error is telling you that you don't have access to the url http://localhost/server-status  which is where apache2ctl gets its status information.

You need to add this to the appropriate apache configuration file (such as /etc/apache2/sites-available/default):
{{{
<Location /server-status>
SetHandler server-status
Order Allow,Deny
Allow from all
</Location>
}}}
Instead of "Allow from all" you should try "Allow from localhost" or "Allow from 127.0.0.1" so that only the apache2ctl status command can access your stats and not the world at large.
{{item1{中文處理}}}
在新版的 3.x 上面有數個提供這些語系轉換的設定喔,如下所示:
* display charset = 自己伺服器上面的顯示編碼, 例如你在終端機時所查閱的編碼資訊。一般來說,與底下的 unix charset 會相同。
* unix charset = 在 Linux 伺服器上面所使用的編碼,一般來說就是 i18n 的編碼囉! 所以你必須要參考 /etc/sysconfig/i18n 內的『預設』編碼。
* dos charset = 就是 Windows 用戶端的編碼了! 一般來說我們的繁體中文 Windows 使用的是 big5 編碼,這個編碼在 Samba 內的格式被稱為『 cp950 』喔! 

{{op1{實作步驟}}}
''1. 系統 Locale 設定''
{{{
tobala@UB10Serv001:~$ sudo cat /etc/default/locale
LANG="zh_TW.UTF-8"
}}}

''2. smb.conf 設定''
{{{
tobala@UB10Serv001:~$ sudo cat /etc/samba/smb.conf
[global]
workgroup = it100
wins support = yes
netbios name = it100MB
os level = 255

domain master = no
preferred master = yes
local master = yes

browse list = yes
dns proxy = no
security = user
guest only = no
guest ok = no

name resolve order = wins lmhosts bcast

# 中文顯示設定
unix charset  = utf8
display charset = utf8
dos charset  = cp950

log file = /var/log/samba/log.%m
max log size = 1000
syslog = 2

[homes]
  comment = Home Directories
  browseable = no

  # By default, the home directories are exported read-only. Change next
  # parameter to if you want to be able to write to them.
  writable = yes

  # By default, \\server\username shares can be connected to by anyone
  # with access to the samba server. Un-comment the following parameter
  # to make sure that only ^username^ can connect to \\server\username
  valid users = %S

  create mode = 0664
  directory mode = 0775
}}}

''3. 重新啟動 Samba''
{{{
$ service smbd restart     (Ubuntu 10.04)
}}}
<<toBalaNotes "sambacht">>

{{item1{在 Samba 系統, 正確顯示檔案的中文內容}}}
在後端 Samba 系統中, 設定使用 UTF-8 編碼, 如果在 Windows 系統使用記事本, 內定以 ANSI 儲存檔案內容, 所以在 Samba 系統無法正常顯示檔案內容, 但是記事本使用 UTF-8 方式存檔, 那就可以正常顯示檔案內容

{{item1{如何在 gedit 中開啟 big5 編碼的文件而不會出現亂碼 ?}}}
因在中文 Windows 系統中, 所產生的文字檔, 均以 big5 編碼, 而後端的 Linux 系統是以 UTF-8 編碼, 所以 gedit 在開啟 big5 編碼的文件, 必須先選擇 big5 來開啟檔案, 操作如圖 :

[img[img/ubuntu10.4/Desktop/geditbig501.png]]

[img[img/ubuntu10.4/Desktop/geditbig502.png]]

[img[img/ubuntu10.4/Desktop/geditbig503.png]]

<<toBalaNotes "gedit">>

///%sambacht
//%/

///%gedit
//%/
''參考網址''
1. Running PHP under CGI with Apache on Ubuntu 10.04 LTS
http://library.linode.com/web-servers/apache/php-cgi/ubuntu-10.04-lucid
2. 15 Practical Linux cURL Command Examples (一定要看) 
http://www.thegeekstuff.com/2012/04/curl-examples/

{{item1{何謂 CGI 程式}}}
Web CGI programs can be written in any language which can process standard input (stdin), environment variables and write to standard output (stdout). The web server will interact with all CGI programs using the "Common Gateway Interface" (CGI) standard as set by RFC 3875. This capability is possessed by most modern computer programming and scripting languages, including the ''bash script''. 

{{item1{CGI 程式運作}}}
1. All CGI scripts must write out a header used by the browser to identify the content.
2. They typically process some input. (URL, form data or ISINDEX)
3. CGI can access environment variables set by the web server.
4. CGI scripts will write out HTML content to be viewed. This typically has the structure of the "head" which contains non-viewable content and "body" which provides the viewable content.

@@color:red;''[註] Apache 內定 CGI 目錄為 /usr/lib/cgi-bin''@@

{{item1{建置使用者 CGI 程式介面}}}
''1. 修改 /etc/apache2/httpd.conf 設定檔''
{{{
$ sudo nano /etc/apache2/httpd.conf
                       :
                       :
<Directory /home/*/www/cgi-bin>
  AllowOverride None
  Options ExecCGI -MultiViews +SymLinksIfOwnerMatch
  SetHandler cgi-script
  Order allow,deny
  Allow from all
</Directory>
}}}

''2. 建立 cgi-bin 目錄''
{{{
$ cd ~
$ cd www
$ mkdir cgi-bin
}}}

''3. 編寫 cgi 程式''
{{{
$ nano test.cgi
#!/bin/bash

echo Content-type: text/html
echo ""
echo "<html>"
echo "<body>"
echo "<h1>CGI Test</h1>"
/usr/bin/whoami
echo "</body>"
echo "</html>"
}}}

''4. 付予執行權限''
{{{
$ chmod +x test.cgi
}}}

''5. 重新啟動 Apche2''
{{{
$ sudo /etc/init.d/apache2 restart
}}}

''6. 執行 test.cgi''

在另一部電腦, 啟動瀏覽器, 然後輸入以下網址 :
{{{
http://your ip/~student/cgi-bin/test.cgi
}}}

''[註]'' 上面的 URL 中, 必須輸入 ''~'' 字元, 執行 CGI 程式, 無法使用連接檔 (ln -s)

''執行結果''
{{{
CGI Test
www-data 
}}}

由執行結果得知, 真正執行 test.sh 的使用者帳號是 www-data

{{item1{檢視  /etc/apache2/envvars 檔案 (檢視執行 CGI 程式的 User 及 Group)}}}
{{{
$ sudo nano /etc/apache2/envvars
# envvars - default environment variables for apache2ctl

# Since there is no sane way to get the parsed apache2 config in scripts, some
# settings are defined via environment variables and then used in apache2ctl,
# /etc/init.d/apache2, /etc/logrotate.d/apache2, etc.
export APACHE_RUN_USER=www-data                                          # 執行 CGI 程式的 User 
export APACHE_RUN_GROUP=www-data                                       # 執行 CGI 程式的 Group
export APACHE_PID_FILE=/var/run/apache2.pid

## The locale used by some modules like mod_dav
export LANG=C
## Uncomment the following line to use the system default locale instead:
#. /etc/default/locale

export LANG

## The command to get the status for 'apache2ctl status'.
## Some packages providing 'www-browser' need '--dump' instead of '-dump'.
#export APACHE_LYNX='www-browser -dump'
                                :
}}}
<<toBalaNotes "1">>



///%1
//%/
''參考文章''
1. Bash shell CGI
http://www.yolinux.com/TUTORIALS/BashShellCgi.html
2. Apache CGI 程式環境建立和資源程式應用
http://mouse.oit.edu.tw/htdocs/Hope/199901/CONTENT/CGI.HTM

{{item1{檢視 Request/Response 封包內容}}}

''Request/Response 封包標頭內容''

1. 啟動 Firefox 瀏覽器, 並啟動 Firebug Plugin 的 ''網路'' 功能

[img[img/firebug/firebug01.png]]

[img[img/firebug/firebug02.png]]

2. 輸入以下 URL 
{{{
http://tobala.net/cgi-bin/x/ajaxreq.sh
}}}

[img[img/firebug/firebug03.png]]

''回應網頁內容''
{{{
SERVER_SIGNATURE=
Apache/2.2.16 (CentOS) mod_ssl/2.2.16 0.9.8l DAV/2 mod_fcgid/2.3.5 mod_auth_passthrough/2.1 FrontPage/5.0.2.2635 Server at tobala.net Port 80


UNIQUE_ID=THPyykrc23oAAGCM7jMAAADQ
HTTP_KEEP_ALIVE=115
HTTP_USER_AGENT=Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-TW; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8
SERVER_PORT=80
HTTP_HOST=tobala.net
DOCUMENT_ROOT=/home6/tbalanet/public_html
HTTP_ACCEPT_CHARSET=UTF-8,*
SCRIPT_FILENAME=/home6/tbalanet/public_html/cgi-bin/x/ajaxreq.sh
REQUEST_URI=/cgi-bin/x/ajaxreq.sh
SCRIPT_NAME=/cgi-bin/x/ajaxreq.sh
HTTP_CONNECTION=keep-alive
REMOTE_PORT=1551
PATH=/usr/local/bin:/usr/bin:/bin
PWD=/home6/tbalanet/public_html/cgi-bin/x
SERVER_ADMIN=webmaster@tbala.net
HTTP_ACCEPT_LANGUAGE=zh-tw,en-us;q=0.7,en;q=0.3
HTTP_ACCEPT=text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
REMOTE_ADDR=115.82.191.211
SHLVL=1
SERVER_NAME=tobala.net
SERVER_SOFTWARE=Apache/2.2.16 (CentOS) mod_ssl/2.2.16 0.9.8l DAV/2 mod_fcgid/2.3.5 mod_auth_passthrough/2.1 FrontPage/5.0.2.2635
QUERY_STRING=
SERVER_ADDR=69.89.27.215
GATEWAY_INTERFACE=CGI/1.1
SERVER_PROTOCOL=HTTP/1.1
HTTP_CACHE_CONTROL=max-age=0
HTTP_ACCEPT_ENCODING=gzip,deflate
REQUEST_METHOD=GET
_=/usr/bin/env
}}}

''[註]'' 傳回資訊中, 有詳細的 Apache 運作資訊

<<toBalaNotes "head">>

{{item1{取得 CGI 程式執行期間的環境變數}}}

''$ nano ~/www/cgi-bin/cgienv.sh''
{{{
#!/bin/bash

echo "Content-type: text/html"
echo ""

echo '<html>'
echo '<head>'
echo '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">'
echo '<title>Environment Variables</title>'
echo '</head>'
echo '<body>'
echo 'Environment Variables:'
echo '<pre>'
/usr/bin/env
echo '</pre>'

echo '</body>'
echo '</html>'

exit 0
}}}

<<toBalaNotes "env">>

{{item1{遠端執行 Linux 命令}}}

''$ nano ~/www/cgi-bin/uptime.sh''
{{{
#!/bin/bash

echo "Content-type: text/html"
echo ""

echo '<html>'
echo '<head>'
echo '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">'

PATH="/bin:/usr/bin:/usr/sbin:/usr/opt/bin"
export $PATH

echo '<title>System Uptime</title>'
echo '</head>'
echo '<body>'

echo '<h3>'
hostname
echo '</h3>'

uptime

echo '</body>'
echo '</html>'

exit 0
}}}

<<toBalaNotes "cmd">>

{{item1{接受表單資料}}}
''$ nano ~/www/cgi-bin/ajaxform.sh''
{{{
#!/bin/bash

# let the browser know that this is html code
echo "Content-type: text/html"
echo ""

# read in our parameters
ID=`echo "$QUERY_STRING" | sed -n 's/^.*id=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`
TEXT=`echo "$QUERY_STRING" | sed -n 's/^.*text=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`

# our html code
echo "<html>"
echo "<head><title>Hello CGI</title></head>"
echo "<body>"

# test if any parameters were passed
if [ $ID ] && [ $TEXT ]
then
	echo "The parameters were set <br>"
	echo "the value of ID is $ID <br>"
	echo "the value of TEXT is $TEXT <br>"
else
	echo "<form method=get>"
	echo "ID : <input type=text name=id><br>"
	echo "TEXT : <input type=text name=text><br>"
	echo "TEXT : <input type=submit>"
	echo "</form>"
fi

echo "</body>"
echo "</html>"
}}}

In order to process these, we need to do some ugly bashing of the environment string.
{{{
ID=`echo "$QUERY_STRING" | sed -n 's/^.*id=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`
TEXT=`echo "$QUERY_STRING" | sed -n 's/^.*text=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`
}}}
WHAT IS THIS ?!?!? It is actually easier than it looks :-)

The first line parses a numeric parameter and save it in the environment variable ID.
The second line parses an alpha-numeric parameter and save it in the environment variable TEXT.

Let me explain step by step:
{{{
* echo "$QUERY_STRING" | sed
  send the value of $QUERY_STRING to sed
* sed -e 's/^.*id=\([^&]*\).*$/\1/'
   cut out only the value of "id="
* sed -e 's/^.*text=\([^&]*\).*$/\1/'
   cut out only the value of "text="
* sed "s/%20/ /g"`
   replace the html escaped %20 for spaces 
}}}

<<toBalaNotes "form">>

We just wrote our first bash based CGI that actually does something half reasonable. Let's look at a more complicated example that does a certain action based on the actual value of the parameter. The following example gives the user a number of radio buttons. Depending on which one was set, a different command is executed. You will also learn how to use the case construct inside a bash script.

{{{
#!/bin/sh
echo "Content-type: text/html\n"

# read in our parameters
CMD=`echo "$QUERY_STRING" | sed -n 's/^.*cmd=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`
FOLDER=`echo "$QUERY_STRING" | sed -n 's/^.*folder=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"| sed "s/%2F/\//g"`

# our html header
echo "<html>"
echo "<head><title>Hello CGI</title></head>"
echo "<body>"


# test if any parameters were passed
if [ $CMD ]
then
  case "$CMD" in
    ifconfig)
      echo "Output of ifconfig :<pre>"
      /sbin/ifconfig
      echo "</pre>"
      ;;

    uname)
      echo "Output of uname -a :<pre>"
      /bin/uname -a
      echo "</pre>"
      ;;

    dmesg)
      echo "Output of dmesg :<pre>"
      /bin/dmesg
      echo "</pre>"
      ;;

    ls)
      echo "Output of ls $FOLDER :<pre>"
      /bin/ls "$FOLDER"
      echo "</pre>"
      ;;

    *)
      echo "Unknown command $CMD<br>"
      ;;
  esac
fi

# print out the form
echo "Choose which command you want to run"
echo "<form method=get>"
echo "<input type=radio name=cmd value=ifconfig checked> ifconfig <br>"
echo "<input type=radio name=cmd value=uname> uname -a <br>"
echo "<input type=radio name=cmd value=dmesg> dmesg <br>"
echo "<input type=radio name=cmd value=ls> ls  -- folder <input type=text name=folder value=/mnt/flash><br>"
echo "<input type=submit>"
echo "</form>"
echo "</body>"
echo "</html>"
}}}

[img[img/cgi01.jpg]]

<<toBalaNotes "3">>



{{item1{設定 www-data 群組可執行 sudo 命令, 並取消輸入密碼}}}
{{{
$ sudo nano /etc/sudoers
                   :
%www-data ALL=(ALL) NOPASSWD:ALL               # 自行加入這一行
}}}

''產生使用者帳號''
{{{
$ nano createuser.sh
#!/bin/bash

echo Content-type: text/html
echo ""
echo "<html>"
echo "<body>"
echo "<h1>Create aaa</h1>"
sudo /usr/sbin/useradd -m -s /bin/bash aaa &>/tmp/error
echo $?
echo "</body>"
echo "</html>"
}}}

''遠端關機''
{{{
$ nano /usr/lib/cgi-bin/down.sh
#!/bin/bash

echo Content-type: text/html
echo ""
echo "<html>"
echo "<body>"
echo "<h1>Shutdown</h1>"
sudo shutdown -h now

echo "</body>"
echo "</html>"
}}}

上面程式執行, 在 /var/log/apache2/error.log 這錯誤訊息檔, 會出現以下錯誤訊息 :
{{{
# tail /var/log/apache2/error.log 
/usr/lib/cgi-bin/down.sh: line 8: shutdown: command not found
/usr/lib/cgi-bin/down.sh: line 8: shutdown: command not found
}}}

''修改 down.sh 程式''
{{{
$ nano /usr/lib/cgi-bin/down.sh
#!/bin/bash

echo Content-type: text/html
echo ""
echo "<html>"
echo "<body>"
echo "<h1>Shutdown</h1>"
sudo /sbin/shutdown -h now

echo "</body>"
echo "</html>"
}}}

''@@color:red;另一個執行方法 : @@'' 只要修改 /sbin/shutdown 檔案屬性 (chmod 4755 /sbin/shutdown), 不需修改 /etc/sudoers 
<<toBalaNotes "4">>




///%head
//%/

///%env
//%/

///%cmd
//%/

///%form
//%/

///%3
//%/

///%4
//%/
''參考文章''
1. DNS BIND Zone Transfers and Updates
http://www.zytrax.com/books/dns/ch7/xfer.html

{{item1{Primary Master}}}
Once a ''Primary Master'' has been configured a Secondary Master is needed in order to maintain the availability of the domain should the Primary become unavailable.

First, on the Primary Master server, the zone transfer needs to be allowed. Add the allow-transfer option to the example Forward and Reverse zone definitions in ''/etc/bind/named.conf.local'':
{{{
zone "kvm." {
   type master;
   file "/etc/bind/db.kvm";
   allow-transfer { 172.30.100.254; };
};

zone "100.30.172.in-addr.arpa" {
   type master;
   file "/etc/bind/db.100.30.172";
   allow-transfer { 172.30.100.254; };
};
}}}

''[注意]'' Replace 192.168.1.11 with the IP Address of your Secondary nameserver.

{{op1{Incremental Zone Transfers (IXFR : 只傳送變動資訊)}}}
The incremental zone transfer (IXFR) protocol is a way for slave servers to transfer only changed data, instead of having to transfer the entire zone. The IXFR protocol is specified in RFC 1995. See Proposed Standards.

When acting as a master, BIND 9 supports IXFR for those zones where the necessary change history information is available. These include master zones maintained by dynamic update and slave zones whose data was obtained by IXFR. For manually maintained master zones, and for slave zones obtained by performing a full zone transfer (AXFR), IXFR is supported only if the option ixfr-from-differences is set to yes.

When acting as a slave, BIND 9 will attempt to use IXFR unless it is explicitly disabled. For more information about disabling IXFR, see the description of the request-ixfr clause of the server statement. 

{{op1{BIND 9 IXFR Configuration}}}
It's even easier to configure IXFR in a BIND 9 master name server because you don't have to do a thing: ''it's on by default''. If you need to turn it off for a particular slave server (and you probably won't, since a slave must request an incremental zone transfer), use the provide-ixfr server substatement, which defaults to yes :
{{{
server 192.249.249.1 {
    provide-ixfr no;
};
}}}

''[註]'' 上述設定, 是設定在 /etc/bind/named.conf 這設定檔, 192.249.249.1 指的是 slave server

You can also use provide-ixfr as an options substatement, in which case it applies to all slaves that don't have an explicit provide-ixfr substatement of their own in a server statement.

Since BIND 9 master name servers send many-answers zone transfers by default, you don't need any special transfer-format configuration.

More useful is the request-ixfr substatement, which can be used in either an options or a server statement. If you have a mix of IXFR-capable and IXFR-impaired masters, you can tailor your slave's zone transfer requests to match the capabilities of its masters:
{{{
options {
    	directory "/var/named";
    	request-ixfr no;
};

server 192.249.249.3 {
    	request-ixfr yes;     // of our masters, only terminator supports IXFR
};
}}}
BIND 9 doesn't support the max-ixfr-log-sizesubstatement.

''provide-ixfr''
{{{
provide-ixfr yes|no ;
}}}
The provide-ixfr option defines whether a master will respond to an incremental zone transfer request(IXFR) (option = yes) or will respond with a full zone transfer (AXFR) (option = no). The default is yes. This statement may be specified in normal server or view clauses or in a global options clause.

''request-ixfr''
{{{
request-ixfr yes|no ;
}}}
Applies to ''slave zones only''. The request-ixfr option defines whether a server will request an incremental zone transfer (IXFR) (option = yes) or will request a full zone transfer (AXFR) (option = no). The default is yes. This statement may be specified in normal server or view clauses or in a global options clause.

{{item1{Secondary Master}}}
Next, on the Secondary Master, install the bind9 package the same way as on the Primary. Then edit the ''/etc/bind/named.conf.local'' and add the following declarations for the Forward and Reverse zones:
{{{
zone "kvm" {
	type slave;
        file "/var/cache/bind/db.kvm";
        masters { 172.30.100.2; };
};        
      
zone "1.168.192.in-addr.arpa" {
	type slave;
        file "/var/cache/bind/db.100.30.172";
        masters { 172.30.100.2; };
};
}}}

''[重點]''  Replace 172.30.100.2 with the IP Address of your Primary nameserver. The zone file must be in ''/var/cache/bind/'' because, by default, ''AppArmor'' only allows write access inside it (this was made specifically for a slave configuration. See AppArmor's configuration in /etc/apparmor.d/usr.sbin.named). 

Restart BIND9 on the Secondary Master:
{{{
$ sudo /etc/init.d/bind9 restart
}}}
In /var/log/syslog you should see something similar to:

''$ tail /var/log/syslog''
{{{
Aug 15 13:26:49 US104-100-NAT named[1466]: transfer of 'kvm/IN' from 172.30.100.2#53: connected using 172.30.100.254#46039
Aug 15 13:26:49 US104-100-NAT named[1466]: zone kvm/IN: transferred serial 1
Aug 15 13:26:49 US104-100-NAT named[1466]: transfer of 'kvm/IN' from 172.30.100.2#53: Transfer completed: 1 messages, 4 records, 147 bytes, 0.037 secs (3972 bytes/sec)
}}}

''測試 Secondary Master''
{{{
student@US104-100-NAT:~$ nslookup
> server
Default server: 140.137.202.20             (這是原先這部主機所設定的 DNS Server)
Address: 140.137.202.20#53
Default server: 140.137.198.21
Address: 140.137.198.21#53


> server 172.30.100.254                       (切換到 Secondary Master)
Default server: 172.30.100.254
Address: 172.30.100.254#53

> set type=any

> kvm.
Server:		172.30.100.254
Address:	172.30.100.254#53

kvm
	origin = US104-100-RD.kvm
	mail addr = tobalaking.US104-100-RD.kvm
	serial = 1
	refresh = 604800
	retry = 86400
	expire = 2419200
	minimum = 604800
kvm	nameserver = US104-100-RD.kvm.
> exit
}}}

{{item1{更新 Secondary Master Zone 資訊}}}

上述 KVM. 網域中, 少了 US104-172-30-100-NAT 的 A 記錄, 操作步驟如下 :

''1. 修改 US104-172-30-100-RD 的 DNS 設定檔, 記得修改 serial 號碼''

''2. 將  US104-172-30-100-NAT 系統中的  /var/cache/bind 目錄中的檔案刪除''

''3. 重新啟動  US104-172-30-100-NAT 的 DNS Server''

<<toBalaNotes "sm">>


///%sm
//%/
''參考文章''
1. Monitor Linux file system events with inotify
http://www.ibm.com/developerworks/linux/library/l-inotify/index.html?ca=drs
2. 強大的檔案控管機制-Inotify
http://daydreamer.idv.tw/rewrite.php/read-6.html
3. Monitoring file system events with inotify, incron and authctl (必讀)
http://andries.filmer.nl/kb/Monitoring-file-system-events-with-inotify,-incron-and-authctl/129
4. inotifywait(1) - Linux man page
http://linux.die.net/man/1/inotifywait

inotify 官方網站 : http://inotify.aiken.cz/?section=common&page=home&lang=en

{{item1{認識 inotify}}}
inotify 創作人 Rober Love 在 Linux Journal 上所說的一段話
{{{
inotify is a file change notification system—a kernel feature that allows applications to request the monitoring of a set of files against a list of events. When the event occurs, the application is notified. To be useful, such a feature must be simple to use, lightweight with little overhead and flexible. It should be easy to add new watches and painless to receive notification of events.
}}}
上面那段話簡單的來說, inotify 可以幫助你即時的觀測檔案的改變,並回送通知給你,而 inotify 把檔案狀態的變化分為以下十類
{{{
1. IN_ACCESS:File was read from.
2. IN_MODIFY:File was written to.
3. IN_ATTRIB:File's metadata (inode or xattr) was changed.
4. IN_CLOSE_WRITE:File was closed (and was open for writing).
5. IN_CLOSE_NOWRITE:File was closed (and was not open for writing).
6. IN_OPEN:File was opened.
7. IN_MOVED_FROM:File was moved away from watch.
8. IN_MOVED_TO:File was moved to watch.
9. IN_DELETE File:was deleted.
10. IN_DELETE_SELF:The watch itself was deleted.
}}}
所以不論 讀, 寫, 開啟, 刪除,或 attribute 改變, 都可以從 inotify 收到通知,使用這樣的機制好處是,你再也不用去 polling 你所有要監測的檔案了,這對 embedded device 來說是十分重要的功能,因為它可以簡化你所有監測的動作並且節省 device 的資源

''[註]'' linux kernel在 2.6.13 以後的版本可以使用 Inotify

{{item1{安裝 inotify}}}
{{{
$ apt-get install inotify-tools
}}}

{{item1{實作一次監控}}}

''1. 在背景執行監控''
{{{
$ mkdir  /tmp/ABird
$ inotifywait -q  /tmp/ABird &                            
[1] 873
}}}

''[註]'' -q: quiet 簡化輸出的訊息

''2. 在監控目錄中產生檔案''
{{{
$ touch  /tmp/ABird/x
/tmp/ABird/ OPEN x
[1]+  Done                    inotifywait -q /tmp/ABird
}}}

{{item1{全程監控}}}

''1. 監控的目錄是 /tmp/ABird/''
{{{
$ inotifywait -mrq /tmp/ABird/ &
}}}

-m: monitor 如果不使用的話,就僅僅會顯示一筆變動記錄後就結束!
-r: recursive 包括底下所有子路徑

''2. 產生新檔案''
{{{
$ touch /tmp/ABird/y
/tmp/ABird/ CREATE y
/tmp/ABird/ OPEN y
/tmp/ABird/ ATTRIB y
/tmp/ABird/ CLOSE_WRITE,CLOSE y
}}}

''3. 結束監控''
{{{
$ ps aux | grep inotifywait
root       876  0.0  0.0   1884   544 ttyS0    S    11:53   0:00 inotifywait -mrq /tmp/ABird
root       894  0.0  0.1   3328   800 ttyS0    S+   11:59   0:00 grep --color=auto inotifywait

$ kill -9 876
[1]+  已砍掉               inotifywait -mrq /tmp/ABird
}}}

{{item1{監控指定事件}}}

''1. 監控的目錄是 /tmp/ABird/''
{{{
$ inotifywait -mrq -e create,move,delete,modify  /tmp/ABird/ &
}}}

''[註]''
inotifywait -mrq -e create,move,delete,modify  /tmp/ABird/ & 這行指令用 -e,只顯示 create,move,delete,modify 四種事件,當有事件發生時,輸出的訊息有三個欄位,如下:
{{{
/tmp/ABird/ CREATE z
}}}
分別是 "路徑" "事件狀態" "檔案名稱",所以也可以讀入特定的欄位來進行處理。另外,Inotify 預設只能夠監看 8K(8192) 以下的檔案數量,如果檔案數量超出的話,修改 /proc/sys/fs/inotify/max_user_watches 的值就可以增加了

''2. 功能測試''
{{{
$ inotifywait -mrq -e create  /tmp/ABird/ &
[1] 899
# touch /tmp/ABird/y
# touch /tmp/ABird/z
/tmp/ABird/ CREATE z
}}}

''[註]'' y 是已存在的檔案

''3. 結束監控''
{{{
$ ps aux | grep inotifywait
root       876  0.0  0.0   1884   544 ttyS0    S    11:53   0:00 inotifywait -mrq /tmp/ABird
root       894  0.0  0.1   3328   800 ttyS0    S+   11:59   0:00 grep --color=auto inotifywait

$ kill -9 876
[1]+  已砍掉               inotifywait -mrq /tmp/ABird
}}}

{{item1{目錄同步}}}

如果有需要兩個目錄要完全一模一樣,可以利用 rsync:
{{{
inotifywait -mrq -e create,move,delete,modify /home/abc | while read DIR ACT FILE ; do rsync -avq --delete /home/abc /home/def
}}}

這樣當 /home/abc 有任何變動時, /home/def 會即時跟著變動。

{{item1{目錄稽核}}}
Log the /home/andries/myProject directory after being opened in writeable mode
{{{
$ inotifywait -mrq --format '%w%f' -e close_write /home/andries/myProject | while read file;do echo $file >> /var/log/inotify; done &
}}}

&ndash;-format '%w%f' : Echo the full path instead of the file only (default).

{{item1{備份系統目錄}}}
It can be very usefull to make a automatic backup for each file in a directory with a timestamp.
{{{
$ mkdir /var/backups/inotify
}}}

A example to backup all /etc/ files.
{{{
$ inotifywait -mrq --format '%w%f' -e close_write /etc | while read file;do \
    cp --parents $file /var/backups/inotify;mv /var/backups/inotify$file \ 
    /var/backups/inotify$file-`date +'%Y-%m-%d_%H:%M'`; done &
}}}
* Option cp &ndash;-parents use full source file name under DIRECTORY
* Command mv moves the $file to the $file with a date-stamp date +'%Y-%m-%d_%H:%M.


<<toBalaNotes "1">>

{{item1{incron (背景服務)}}}
If you want some monitoring, backup events permanent then incron is very useful.

The inotify cron daemon (incrond) is a daemon which monitors filesystem events and executes commands defined in system and user tables. It's use is generally similar to cron(8).

''安裝 incron''
{{{
# apt-get install incron
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following NEW packages will be installed:
  incron
0 upgraded, 1 newly installed, 0 to remove and 25 not upgraded.
Need to get 113kB of archives.
After this operation, 377kB of additional disk space will be used.
Get:1 http://tw.archive.ubuntu.com/ubuntu/ lucid/universe incron 0.5.9-4 [113kB]
Fetched 113kB in 14s (7620B/s) 
[master fbbad72] saving uncommitted changes in /etc prior to apt run
 15 files changed, 263 insertions(+), 3 deletions(-)
debconf: delaying package configuration, since apt-utils is not installed
Selecting previously deselected package incron.
(Reading database ... 40781 files and directories currently installed.)
Unpacking incron (from .../incron_0.5.9-4_i386.deb) ...
Processing triggers for man-db ...
Setting up incron (0.5.9-4) ...
Adding group `incron' (GID 108) ...
Done.
update-rc.d: warning: incron stop runlevel arguments (0 1 6) do not match LSB Default-Stop values (1)
 * Starting File system events scheduler                                 [ OK ] 

[master c940cdc] committing changes in /etc after apt run
 14 files changed, 154 insertions(+), 0 deletions(-)
 create mode 100644 incron.allow
 create mode 100644 incron.conf
 create mode 100644 incron.deny
 create mode 100755 init.d/incron
 create mode 120000 rc0.d/K20incron
 create mode 120000 rc1.d/K20incron
 create mode 120000 rc2.d/S20incron
 create mode 120000 rc3.d/S20incron
 create mode 120000 rc4.d/S20incron
 create mode 120000 rc5.d/S20incron
 create mode 120000 rc6.d/K20incron
}}}

''Create your backups''
As a example I have made a small script to backup all files in the etc and myProject directory.
{{{
$ nano /root/inotify.sh

 #!/bin/sh
 
 # Create a inotify backup dir (if not exists)
 #
 mkdir /var/backups/inotify
 
 # Make a copy off the full path and file
 #
 cp -p --parents $1  /var/backups/inotify
 
 # move the file to a file with datetime-stamp
 #
 mv /var/backups/inotify$1 /var/backups/inotify$1_`date +'%Y-%m-%d_%H:%M'
}}}

Make the file executable for root
{{{
$  chmod 755 /root/inotify.sh
}}}

''Open''
{{{
$ incrontab -e

 /etc IN_CLOSE_WRITE,IN_MODIFY /root/inotify.sh $@/$# 
 /home/andries/myProject IN_CLOSE_WRITE /root/inotify.sh $@/$# 
}}}

As you can see you can do many more ;)
* Manpage: http://manpages.ubuntu.com/manpages/lucid/man5/incrontab.5.html

<<toBalaNotes "2">>


///%1
//%/

///%2
//%/
{{item1{新增使用者帳號}}}

''1. 建立存放使用者帳號資料庫的目錄''
{{{
$ mkdir /usr/lib/cgi-bin/data
$ chown root:www-data /usr/lib/cgi-bin/data
$ chmod 775 /usr/lib/cgi-bin/data
}}}

''2. 撰寫程式''
{{{
$ nano adduser.sh
#!/bin/bash

# let the browser know that this is html code
echo "Content-type: text/html"
echo ""

# read in our parameters
ID=`echo "$QUERY_STRING" | sed -n 's/^.*id=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`
PASS=`echo "$QUERY_STRING" | sed -n 's/^.*pass=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`
TEXT=`echo "$QUERY_STRING" | sed -n 's/^.*text=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`

[ ! -f data/users.db ] && touch data/users.db

if [ ! -z "$ID" ]; then
   grep "<div id='$ID'>" data/users.db &>/dev/null
   if [ "$?" == "0" ]; then
      echo "2"
   else
      echo -e "<div id='$ID'>\n  <div>$ID</div>\n  <div>$PASS</div>\n  <p>$TEXT</p>\n</div>" >> data/users.db
      echo  "0"
   fi
else
   echo "1"
fi
}}}

@@color:red;''[註] Apache 內定 CGI 目錄為 /usr/lib/cgi-bin''@@

''3. 測試''
{{{
http://140.137.214.250/cgi-bin/adduser.sh?id=123&pass=123&text=123
}}}

<<toBalaNotes "1">>

{{item1{帳號登入}}}

''1. 撰寫程式''
{{{
$ nano login.sh

#!/bin/bash

# let the browser know that this is html code
echo "Content-type: text/html"
echo ""

# read in our parameters
ID=`echo "$QUERY_STRING" | sed -n 's/^.*id=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`
#PASS=`echo "$QUERY_STRING" | sed -n 's/^.*pass=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`
#TEXT=`echo "$QUERY_STRING" | sed -n 's/^.*text=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`

if [ ! -z "$ID" ]; then
   if [ ! -f data/users.db ]; then
      echo "<script>alert('檔案不存在')</script>"
      return
   fi
   grep "<div id='$ID'>" data/users.db &>/dev/null
   if [ "$?" == "0" ]; then
      echo "<script>alert('登入成功')</script>"
   else
      echo "<script>alert('帳號不存在')</script>"
   fi
else
   echo "<script>alert('帳號不存在')</script>"
fi
}}}

''2. 測試''
{{{
http://140.137.214.250/cgi-bin/login.sh?id=123
}}}

<<toBalaNotes "2">>

{{item1{以 HTTP POST 命令上傳資料}}}
程式範例網址 : http://paulturner.me/2009/07/reading-http-post-data-using-bash/

''1. 撰寫程式''
{{{
$ nano postdata.sh

#!/bin/bash
echo "Content-type: text/html; charset=UTF-8"
echo "Status: 200 OK"
echo ""

if [ "$REQUEST_METHOD" = "POST" ]; then
    if [ "$CONTENT_LENGTH" -gt 0 ]; then
        read -n $CONTENT_LENGTH POST_DATA <&0
    fi
fi

echo "<script>alert(decodeURI('${POST_DATA}'))</script>"
}}}

''2. 編輯 formpost.html 網頁 (此網頁一定要存到 /var/www 目錄中)''
{{{
$ nano formpost.html

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Form</title>
</head>
<body>
  <form action="/cgi-bin/postdata.sh" method="post">
    ID : <input type=text name=id><br/>
    Text : <input type=text name=text><br/>
    <input type="submit" value="submit">
  </form>
</body>
</html>
}}}

''3. 執行''
{{{
http://140.137.214.250/formpost.html
}}}

<<toBalaNotes "3">>
///%1
//%/

///%2
//%/

///%3
//%/
參考文章
1. Install Drupal with XAMPP in Ubuntu
http://creativebushido.wordpress.com/2009/06/10/install-drupal-in-ubuntu/

{{item1{下載與安裝 Drupal}}}
{{{
# wget http://ftp.drupal.org/files/projects/drupal-6.13.tar.gz
--2009-09-01 00:35:24--  http://ftp.drupal.org/files/projects/drupal-6.13.tar.gz
正在查找主機 ftp.drupal.org... 140.211.166.134
正在連接 ftp.drupal.org|140.211.166.134|:80... 連上了。
已送出 HTTP 要求,正在等候回應... 200 OK
長度: 1080373 (1.0M) [application/x-gzip]
Saving to: `drupal-6.13.tar.gz'

100%[================================================>] 1,080,373   43.0K/s   in 30s

2009-09-01 00:35:59 (35.3 KB/s) -- 已儲存 ‘drupal-6.13.tar.gz’ [1080373/1080373])
}}}

This will create a new directory drupal-x.x/ containing all Drupal files and directories and will preserve all of Drupal's file and directory permissions. Move the contents of that directory into a directory within your web server's document root or your public HTML directory
{{{
# tar -zxvpf drupal-6.13.tar.gz
}}}

The base URL for your Drupal installation will be set in your Web server's configuration file. You will need to know this URL before proceeding to the next step of the installation. If you are installing Drupal on your local machine the base URL may be: http://localhost. If you are installing Drupal onto a Web server your base URL may be a specific domain name (such as http://example.com).
{{{
# mv drupal-6.13/* drupal-6.13/.htaccess /opt/lampp/htdocs/
# ls -al /opt/lampp/htdocs/
總計 276
drwxr-xr-x 11 nobody root  4096 2009-09-01 00:48 .
drwxr-xr-x 20 root   root  4096 2009-08-01 21:35 ..
-rw-r--r--  1   1080 1080 42420 2009-07-02 04:51 CHANGELOG.txt
-rw-r--r--  1   1080 1080   981 2008-02-06 20:45 COPYRIGHT.txt
-rw-r--r--  1   1080 1080   262 2006-08-09 15:42 cron.php
-rw-r--r--  1 root   root 30894 2007-05-11 20:40 favicon.ico
-rw-r--r--  1   1080 1080  3837 2008-12-11 04:04 .htaccess
drwxr-xr-x  2   1080 1080  4096 2009-07-02 04:55 includes
-rw-r--r--  1   1080 1080   980 2007-12-26 16:46 index.php
-rw-r--r--  1   1080 1080  1308 2007-11-20 03:53 INSTALL.mysql.txt
-rw-r--r--  1   1080 1080  1075 2007-11-27 00:36 INSTALL.pgsql.txt
-rw-r--r--  1   1080 1080 46926 2009-04-27 18:50 install.php
-rw-r--r--  1   1080 1080 15646 2008-07-10 03:15 INSTALL.txt
-rw-r--r--  1   1080 1080 18048 2009-01-07 01:27 LICENSE.txt
-rw-r--r--  1   1080 1080  1924 2009-04-30 01:15 MAINTAINERS.txt
drwxr-xr-x  3   1080 1080  4096 2009-07-02 04:55 misc
drwxr-xr-x 35   1080 1080  4096 2009-07-02 04:55 modules
drwxr-xr-x  3   1080 1080  4096 2009-07-02 04:55 profiles
-rw-r--r--  1   1080 1080  1590 2008-12-11 04:12 robots.txt
drwxr-xr-x  2   1080 1080  4096 2009-07-02 04:55 scripts
drwxr-xr-x  4   1080 1080  4096 2009-07-02 04:55 sites
drwxr-xr-x  7   1080 1080  4096 2009-07-02 04:55 themes
-rw-r--r--  1   1080 1080 25457 2009-03-30 19:15 update.php
-rw-r--r--  1   1080 1080  5002 2008-01-05 00:15 UPGRADE.txt
drwxr-xr-x  2 nobody root  4096 2009-07-15 17:24 webalizer
drwxr-xr-x  7 root   root  4096 2009-07-30 17:00 xampp
-rw-r--r--  1   1080 1080   352 2005-12-11 03:26 xmlrpc.php
}}}


1. Function ereg() is deprecated
http://drupal.org/node/514334
{{{
I used this in my .htaccess file:

php_value error_reporting 4096

That solved the deprecated warning for my setup (XAMPP on Mac).
}}}

{{op1{Grant write permissions on the configuration file}}}
{{{
root@tobalaking:/opt/lampp/htdocs/sites/default# ls -al
總計 20
drwxr-xr-x 2 1080 1080 4096 2009-07-02 04:55 .
drwxr-xr-x 4 1080 1080 4096 2009-07-02 04:55 ..
-rw-r--r-- 1 1080 1080 8956 2009-06-09 18:44 default.settings.php

root@tobalaking:/opt/lampp/htdocs/sites/default# cp default.settings.php settings.php
root@tobalaking:/opt/lampp/htdocs/sites/default# chmod 666 settings.php

}}}






本文網址 : http://mhashem.wordpress.com/2008/08/25/set-tomcat-memory-heap-size/

when you are using tomcat as you application server for not small application you can easy get (out of memory exception). this is because the default heap size tomcat use is small and suitable only for small web applications.

to set the start and maximum heap size run the following command before starting your tomcat:
{{{
export CATALINA_OPTS="-Xms256m -Xmx512m"
}}}
or
{{{
export JAVA_OPTS="-Xms256m -Xmx512m"
}}}
this will create environment variable called CATALINA_OPTS  or JAVA_OPTS contains the required options to make tomcat start heap size 256M and maximum heap size 512M.

{{item1{7 Common Errors in Setting Java Heap Size}}}
本文網址 : http://javahowto.blogspot.com/2006/06/6-common-errors-in-setting-java-heap.html

Two JVM options are often used to tune JVM heap size: -Xmx for maximum heap size, and -Xms for initial heap size. Here are some common mistakes I have seen when using them:

''1. Missing m, M, g or G at the end (they are case insensitive). For example,''
{{{
# java -Xmx128 BigApp
java.lang.OutOfMemoryError: Java heap space
}}}
The correct command should be: java -Xmx128m BigApp. To be precise, -Xmx128 is a valid setting for very small apps, like HelloWorld. But in real life, I guess you really mean -Xmx128m

''2. Extra space in JVM options, or incorrectly use =. For example,''
{{{
# java -Xmx 128m BigApp
Invalid maximum heap size: -Xmx

Could not create the Java virtual machine.

# java -Xmx=512m HelloWorld
Invalid maximum heap size: -Xmx=512m
      
Could not create the Java virtual machine.
}}}
The correct command should be java -Xmx128m BigApp, with no whitespace nor =. -X options are different than -Dkey=value system properties, where = is used.

''3. Only setting -Xms JVM option and its value is greater than the default maximum heap size, which is 64m.'' The default minimum heap size seems to be 0. For example,
{{{
# java -Xms128m BigApp
Error occurred during initialization of VM

Incompatible initial and maximum heap sizes specified
}}}
The correct command should be java -Xms128m -Xmx128m BigApp. It's a good idea to set the minimum and maximum heap size to the same value. In any case, don't let the minimum heap size exceed the maximum heap size.

''4. Heap size is larger than your computer's physical memory. For example,''
{{{
# java -Xmx2g BigApp
Error occurred during initialization of VM
      
Could not reserve enough space for object heap
Could not create the Java virtual machine.
}}}
The fix is to make it lower than the physical memory: java -Xmx1g BigApp

''5. Incorrectly use mb as the unit, where m or M should be used instead.''
{{{
# java -Xms256mb -Xmx256mb BigApp
Invalid initial heap size: -Xms256mb
      
Could not create the Java virtual machine.
}}}

''6. The heap size is larger than JVM thinks you would ever need. For example,''
{{{
# java -Xmx256g BigApp
Invalid maximum heap size: -Xmx256g
      
The specified size exceeds the maximum representable size.
Could not create the Java virtual machine.
}}}
The fix is to lower it to a reasonable value: java -Xmx256m BigApp

''7. The value is not expressed in whole number. For example,''
{{{
# java -Xmx0.9g BigApp
Invalid maximum heap size: -Xmx0.9g
      
Could not create the Java virtual machine.
}}}
The correct command should be java -Xmx928m BigApp

{{op1{PS:}}}
''How to set java heap size in Tomcat?''
Stop Tomcat server, set environment variable CATALINA_OPTS, and then restart Tomcat. Look at the file tomcat-install/bin/catalina.sh or catalina.bat for how this variable is used. For example,
{{{
set CATALINA_OPTS="-Xms512m -Xmx512m"  (Windows)
export CATALINA_OPTS="-Xms512m -Xmx512m"  (ksh/bash)
setenv CATALINA_OPTS "-Xms512m -Xmx512m"  (tcsh/csh)
}}}
In catalina.bat or catallina.sh, you may have noticed CATALINA_OPTS, JAVA_OPTS, or both can be used to specify Tomcat JVM options. What is the difference between CATALINA_OPTS and JAVA_OPTS? The name CATALINA_OPTS is specific for Tomcat servlet container, whereas JAVA_OPTS may be used by other java applications (e.g., JBoss). Since environment variables are shared by all applications, we don't want Tomcat to inadvertently pick up the JVM options intended for other apps. I prefer to use CATALINA_OPTS.

{{op1{How to set java heap size in Eclipse?}}}
''You have 2 options:''
1. Edit eclipse-home/eclipse.ini to be something like the following and restart Eclipse.
{{{
-vmargs
-Xms64m
-Xmx256m
}}}
2. Or, you can just run eclipse command with additional options at the very end. Anything after -vmargs will be treated as JVM options and passed directly to the JVM. JVM options specified in the command line this way will always override those in eclipse.ini. For example,
{{{
eclipse -vmargs -Xms64m -Xmx256m
}}}







''參考文章''
1. BIND's new static-stub zone type
http://jpmens.net/2011/01/25/binds-new-static-stub-zone-type/

{{item1{Static Stub (BIND 9.8 新增功能)}}}
Version 9.8.0b1 of BIND brings with it a new zone type, which IIRC was developed by the DeNIC. It is called a static-stub, and it allows an administrator to force queries for a particular zone to go to specified addresses instead of BIND recursing for the name server records of that zone.

So, for example, suppose you have a zone called uno.aa and you want BIND to direct queries at your name server located at mynameserver.example.com, you'd set up a static-stub zone as
{{{
zone "uno.aa" {
   type static-stub;
   //server-names {
   //  "mynameserver.example.com";
   //};    
   server-addresses {
      192.168.1.2;
   };
}
}}}

需關閉安全檢核, Bind 9.8 內定是開啟. 將 ''dnssec-validation'' 設成 no,  如下 :
{{{
# nano /etc/bind/named.conf.options
options {
	directory "/var/cache/bind";

	// If there is a firewall between you and nameservers you want
	// to talk to, you may need to fix the firewall to allow multiple
	// ports to talk.  See http://www.kb.cert.org/vuls/id/800113

	// If your ISP provided one or more IP addresses for stable 
	// nameservers, you probably want to use them as forwarders.  
	// Uncomment the following block, and insert the addresses replacing 
	// the all-0's placeholder.

	// forwarders {
	// 	0.0.0.0;
	// };

	//========================================================================
	// If BIND logs error messages about the root key being expired,
	// you will need to update your keys.  See https://www.isc.org/bind-keys
	//========================================================================
	dnssec-validation no;

	auth-nxdomain no;    # conform to RFC1035
	listen-on-v6 { any; };
};
}}}

{{item1{Stub zones 要項}}}

1. When a stub zone is used, BIND sends an ''iterative (non-recursive) query'' to one of the name servers in the stub zone. BIND will continue to send iterative queries to resolve the query.

2. BIND uses both UDP 53 and TCP 53 when populating a stub zone, even if the master name server allows EDNS. BIND uses UDP 53 when querying the SOA record for the zone, and TCP 53 when transferring the NS records and A glue records. I find this surprising as IXFR and AXFR aren't involved.

3. BIND will check the stub server(s) at the SOA REFRESH interval for any changes to the SOA, NS, and A glue records. 

''[註]'' 擁有 Stub zones 的 BIND 主機, 對 Stub zone 記錄中的 name servers 執行 iterative 查詢, 這有別於正規 iterative 查詢, 均是從 Root DNS Server 開始查詢. Only DNS servers running Windows Server 2003 and BIND 9 support stub zones.

{{item1{Stub Zones and Conditional Forwarding}}}
A stub zone enables a DNS server that is hosting a parent zone to be aware of the names and IP addresses of DNS servers that are authoritative for a child zone, even if the DNS server does not have a complete copy of the child zone. In addition, when a stub zone is used, the DNS server does not have to send queries to the DNS root servers. If the stub zone for a child zone is hosted on the same DNS server as the parent zone, the DNS server that is hosting the stub zone receives a list of all new authoritative DNS servers for the child zone when it requests an update from the stub zone’s primary server. In this way, the DNS server that is hosting the parent zone maintains a current list of the authoritative DNS servers for the child zone as the authoritative DNS servers are added and removed.

Use conditional forwarding if you want DNS servers in one network to perform name resolution for DNS clients in another network. You can configure DNS servers in separate networks to forward queries to each other without querying DNS servers on the Internet. If DNS servers in separate networks forward DNS client names to each other, the DNS servers cache this information. This enables you to create a direct point of contact between DNS servers in each network and reduces the need for recursion.

If you are using a stub zone and you have a firewall between DNS servers in the networks, then DNS servers on the query/resolution path must have port 53 open. However, if you are using conditional forwarding and you have a firewall between DNS servers in each of the networks, the requirement to have port 53 open only applies to the two DNS servers on either side of the firewall.

<<toBalaNotes "stub">>
{{item1{父網域 DNS 設定 (kvm.)}}}

''子網域授權''
{{{
$ sudo nano /etc/bind/db.kvm

; BIND data file for local loopback interface

$TTL  604800
@   IN   SOA   US104-100-RD.kvm. tobalaking.US104-100-RD.kvm. (
            1     ; Serial
            604800     ; Refresh
            86400       ; Retry
            2419200    ; Expire
            604800 )    ; Negative Cache TTL
;
@       IN     NS     US104-100-RD.kvm.
US104-100-RD      IN     A      172.30.100.2

}}}

在上述設定檔的最下方增加這兩行:
{{{
it66.kvm. IN NS US104-66-DM.it66.kvm.
US104-66-DM.it66.kvm. IN A 172.30.66.5
}}}

直接將 it66.kvm. 這個網域的 NS 權限 (name server) 轉給 US104-66-DM.it66.kvm. 這部主機來管理,並同時列出 US104-66-DM.it66.kvm. 的正解資訊 (A 記錄). 那麼未來當有人要查詢 it66.kvm. 時,我們的 US104-100-RD.kvm. (父網域 DNS) 會直接將查詢的要求丟給 US104-66-DM.it66.kvm. 去處理.


''允許 zone 資訊複製 (transfer)''
{{{
$ sudo nano /etc/bind/named.conf.local

zone "kvm." {
   type master;
   file "/etc/bind/db.kvm";
   allow-transfer { 172.30.100.254; 172.30.66.5; 172.30.99.5; };
};
}}}

在 allow-transfer 設定加入 子網域 DNS 的 IP 位址, 使得子網域 DNS 能正常取得 Stub Zone 資訊

''@@color:red;[注意]@@'' 父網域 DNS, 如有設定 forwarders, 會造成在父網域 DNS, 查詢不到子網域資訊, 會由 forwarders 來執行,  如 forwarders 是 168.95.1.1, 這部 Hinet 的 DNS Server, 是不可能找到你設的子網域資訊.

{{item1{子網域 DNS 設定 (it66.kvm.)}}}

''負責 it66.kvm 網域的 DNS Server 主要設定檔''
{{{
$ sudo nano /etc/bind/named.conf.local
//
// Do any local configuration here
//

// Consider adding the 1918 zones here, if they are not used in your
// organization
//include "/etc/bind/zones.rfc1918";

zone "it66.kvm" {
   type master;
   file "/etc/bind/db.it66.kvm";
};

// 子網域只需設定以下的 Stub Zone 
zone "kvm." {
   type stub;
   masters { 172.30.100.2; };
   file "/var/cache/bind/stub.kvm";
};
}}}

''it66.kvm Zone 設定''
{{{
$ sudo nano /etc/bind/db.it66.kvm
; BIND reverse data file for local loopback interface

$TTL 604800
@       IN   SOA   it66.kvm. tobalaking.it66.kvm. (
            1     ; Serial
            604800     ; Refresh
            86400       ; Retry
            2419200    ; Expire
            604800 )    ; Negative Cache TTL
;
@       IN     NS     US104-66-DM.it66.kvm.
@       IN     A      172.30.66.5
@       IN     MX 10  US104-66-DM.it66.kvm.

US104-66-DM   IN     A     172.30.66.5
www     IN       CNAME US104-66-DM.it66.kvm.
}}}

請加入 ''MX'' 及 ''CNAME'' 記錄.

<<toBalaNotes "sub">>


///%sub
//%/

///%stub
//%/
{{item1{自定監控資訊格式}}}
{{{
$ inotifywait -rmq --timefmt "%m_%d_%H_%M_%S" --format "%w %f %e %T" -e create /tmp/ABird &
[1] 1183
$ touch /tmp/ABird/z
/tmp/ABird/ z CREATE 06_18_15_01_03
}}}

''&ndash;-format 參數說明''
%w : 監控檔案的完整目錄名稱
%f : 監控檔案的名稱
%e : 監控的事件名稱
%Xe : Replaced with the Event(s) which occurred, separated by whichever character is in the place of 'X'. 
%T : Replaced with the current Time in the format specified by the &ndash;-timefmt option, which should be a format string suitable for passing to strftime(3).

{{item1{執行監控程式}}}

''1. 撰寫程式''
{{{
$ nano testInotify.sh
#!/bin/bash
inotifywait -rmq --timefmt "%m_%d_%H_%M_%S" --format "%w %f %e %T" -e create $1 |
while read p f a t;
do 
   echo "$p$f" $a $t 
   echo ""
done

$ chmod +x testInotify.sh 
}}}

''2. 執行程式''
{{{
$ ./testInotify.sh /tmp/ &
[1] 1201
}}}

''3. 測試程式''
{{{
$ touch /tmp/z
$ touch /tmp/v
/tmp/v CREATE 06_18_15_37_40
}}}

監控 Samba 共享資料夾, 資訊如下 :
{{{
# 將 abc.sh 更名為 abca.sh
/tmp/abc.sh MOVED_FROM 09_20_00_22_40
/tmp/abca.sh MOVED_TO 09_20_00_22_40

# 在 Windows 系統, 將 Blue Lace 16.bmp 複製至 Samba 共享資料夾
/tmp/Blue Lace 16.bmp CREATE 09_20_00_33_15
/tmp/Blue Lace 16.bmp MODIFY 09_20_00_33_15
/tmp/Blue Lace 16.bmp MODIFY 09_20_00_33_15

# 在 Windows 系統, 將 clock.avi 複製至 Samba 共享資料夾
/tmp/clock.avi CREATE 09_20_00_35_09
/tmp/clock.avi MODIFY 09_20_00_35_09
/tmp/clock.avi MODIFY 09_20_00_35_09
/tmp/clock.avi MODIFY 09_20_00_35_09

# 在 Windows 系統, 將 abc.sh 複製至 Samba 共享資料夾
/tmp/abc.sh CREATE 09_20_00_34_04

# 在 Windows 系統, 直接在 Samba 共享資料夾, 產生 "新增點陣圖影像.bmp" 檔案
/tmp/新增點陣圖影像.bmp CREATE 09_20_00_35_44

# 在 Windows 系統, 直接在 Samba 共享資料夾, 產生 "新增文字文件.txt" 檔案, 然後將之更名為 vvv.sh
/tmp/新增文字文件.txt CREATE 09_20_00_35_50
/tmp/新增文字文件.txt MOVED_FROM 09_20_00_36_00
/tmp/vvv.sh MOVED_TO 09_20_00_36_00
}}}

''4. 結束程式執行''
{{{
# killall -9 inotifywait
[1]+  Done                    ./testInotify.sh  /tmp/ABird/
}}}

<<toBalaNotes "1">>
{{item1{自動刪除檔案}}}

''1. 編輯程式''
{{{
$ nano mywatch.sh
#!/bin/bash
inotifywait -rmq --timefmt "%m_%d_%H_%M_%S" --format "%w %f %e %T" -e create,move,del$
while read p f e t;
do 
   echo "$p$f" $e $t 
   if [ "$e" == "CREATE" ] || [ "$e" == "MOVED_TO" ]; then
      if [ "${f##*.}" == "sh" ]; then
         sudo rm "$p$f" &>/dev/null
         [ "$?" == "0" ] && echo "rm $p$f ok"
      fi
   fi
done
}}}

''2. 測試程式''
{{{
$ ./mywatch.sh /tmp
/tmp/abc.sh CREATE 09_20_00_44_54
rm /tmp/abc.sh ok
/tmp/abc.sh DELETE 09_20_00_44_54
/tmp/新增文字文件.txt CREATE 09_20_00_45_04
/tmp/新增文字文件.txt MOVED_FROM 09_20_00_45_10
/tmp/abc.sh MOVED_TO 09_20_00_45_10
rm /tmp/abc.sh ok
/tmp/abc.sh DELETE 09_20_00_45_10
}}}

{{item1{上載新增檔案至 HDFS 系統}}}

''1. 撰寫程式''
{{{
$ nano new2HDFS.sh
#!/bin/bash
export JAVA_HOME=/usr/lib/jvm/java-6-sun
export HADOOP_HOME=/root/hadoop-0.20.203.0
export PATH=$PATH:$HADOOP_HOME/bin

inotifywait -rmq --timefmt "%m_%d_%H_%M_%S" --format "%w %f %e %T" -e create $1 | 
while read p f a t;
do 
   echo "$p$f" $a $t 
   hadoop dfs -put "$p$f" /user
   echo ""
done

$ chmod +x new2HDFS.sh
}}}

''2. 執行程式''
{{{
$  ./new2HDFS.sh  /tmp/ABird/  &
}}}

''3. 測試程式''
{{{
$  touch /tmp/ABird/xy
}}}

''4. 結束程式執行''
{{{
# killall -9 inotifywait
[1]+  Done                    ./new2HDFS.sh /tmp/ABird/
}}}

<<toBalaNotes "2">>

///%1
//%/

///%2
//%/
{{item1{明碼認證}}}

''1. 產生目錄設定檔 (.htaccess)''
{{{
$ cd ~/www
$ nano .htaccess
AuthName     "Protect by .htaccess"
AuthType     Basic
AuthUserFile /home/student/apache.passwd
Require valid-user
}}}

''2. 產生密碼''
{{{
$ htpasswd -c ~/apache.passwd student
New password:
Re-type new password:
Adding password for user student
}}}

''[註]'' 設定第二個帳號, 不需 -c 這參數
Note that using the -c flag with htpasswd on an existing file will clear the file's contents completely and create a new one.

''3. 測試''
啟動瀏覽器, 輸入以下網址 (一定要有 ~) :
{{{
http://192.168.99.6/~student
}}}
這時會被要求輸入帳號與密碼

[img[img/apache2/a2basic.png]]
<<toBalaNotes "1">>


///%1
//%/
{{item1{ClamAV}}}
官方網站 : http://www.clamav.net/

ClamAV is a command line virus scanner. It can only detect viruses; it cannot remove them from files. It detects viruses on all platforms, but due to the popularity of the platform, it primarily detects Windows viruses and malware. 

{{item1{安裝 ClamAV}}}
* Ubuntu 8.04: ClamAV is in the Universe repository. (If you do not have Universe enabled, see AddingRepositoriesHowto).
* Ubuntu 8.10 and up: ClamAV is in the Main repository, so no repositories need to be added. 
ClamAV has two modes of operation; a program that loads into memory only when you want to scan a file, or for more regular use (such as scanning all incoming e-mail), a program that connects to a daemon that is always running.

Database updates can also be downloaded automatically .
* For manual use: install the package ''clamav''.
* For automated use: install the package ''clamav-daemon''. 

Both methods will also install ''clamav-freshclam'', the updater.

''安裝手動操作 clamav''
{{{
$ sudo apt-get install clamav
正在讀取套件清單... 完成
正在重建相依關係
正在讀取狀態資料... 完成
下列的額外套件將被安裝:
  clamav-base clamav-freshclam libclamav6 libtommath0
建議套件:
  clamav-docs libclamunrar6
下列【新】套件將會被安裝:
  clamav clamav-base clamav-freshclam libclamav6 libtommath0
升級 0 個,新安裝 5 個,移除 0 個,有 3 個未被升級。
需要下載 4,673kB 的套件檔。
此操作完成之後,會多佔用 10.8MB 的磁碟空間。
是否繼續進行 [Y/n]?
}}}

After installing, you may be asked some questions about how to get virus signature updates. Select the download site closest to you. ClamAV updates are a very small download and it is well worth scheduling them to happen automatically.

If you see a message about ClamAV engine being outdated, most likely you aren't running the latest stable Ubuntu. For example on a hardy LTS machine...
{{{
# /etc/init.d/clamav-daemon restart
 * Stopping ClamAV daemon clamd                                          [ OK ]
 * Starting ClamAV daemon clamd                                                
LibClamAV Warning: ***  This version of the ClamAV engine is outdated.     ***
LibClamAV Warning: *** DON'T PANIC! Read http://www.clamav.net/support/faq ***
LibClamAV Warning: ***********************************************************
                                                                         [ OK ]
}}}

{{item1{Using ClamAV}}}
{{op1{1. 更新資料庫}}}
{{{
# cd /etc/clamav                           #  一定要到此目錄, 才可執行下一行命令
# sudo freshclam                          #  這命令執行需要時間去下載資料庫
ClamAV update process started at Wed Apr 27 00:06:47 2005
main.cvd is up to date (version: 31, sigs: 33079, f-level: 4, builder: tkojm)
daily.cvd is up to date (version: 855, sigs: 714, f-level: 4, builder: ccordes)  
}}}

{{op1{2. 開始掃除病毒}}}

''clamscan 使用格式''
* To check files in the all users home directories: ''clamscan -r /home''
* To check all files on the computer, displaying the name of each file: ''clamscan -r / ''
* To check all files on the computer, but only display infected files and ring a bell when found: ''<nowiki>clamscan -r --bell -i /</nowiki>''
When ClamAV has scanned all the files you asked it to, it will report a summary:
{{{
----------- SCAN SUMMARY -----------
Known viruses: 33840
Scanned directories: 145
Scanned files: 226
Infected files: 1
Data scanned: 54.22 MB
I/O buffer size: 131072 bytes
Time: 20.831 sec (0 m 20 s)  
}}}
''[註]'' ClamAV can only read files that the user running it can read. If you want to check all files on the system, use the sudo command (see UsingSudo for more information). 

{{item1{How to trigger Linux shell script execution from a Windows machine}}}
To signal Linux, you can use a number of methods.  Since you have a SMB share, you can drop a marker file in the same directory one the process is complete.  This marker file can be just a file, wtih no contents.

On the Linux system create a crontab job using the following method:
{{{
crontab -e

*/5 * * * * path_to_script/script.sh
}}}
The above line will cause the script to execute every 5 minutes.

The script could have the following to test for the existence of a file:
{{{
#!/bin/bash
 
# code to test for the marker file
if [ -f /smb_share/marker file ]; then
   cmd_to_run
   rm /smb_share/marker_file
fi
}}}
''參考文章''
1. Configure TLS and SSL in Ubuntu 10.04 LTS
http://blog.joefallon.net/2010/08/configure-tls-and-ssl-in-ubuntu-10-04-lts/
2. SSL/TLS Strong Encryption: How-To
http://httpd.apache.org/docs/2.0/ssl/ssl_howto.html

{{item1{憑證產生}}}
To set up a secure server using SSL, ''public key cryptography'' is used to create a public and private key pair. The ''certificate request'' (including the public key), proof of identity, and payment is sent to a ''Certificate Authority (CA)''. The CA verifies the certificate request and the identity of the requester. Then, a ''certificate'' is sent back to the requester.

''1. Generating a Certificate Signing Request''
Whether the certificate is being obtained from a CA or a self-signed certificate is being created, the first step is to generate a key. To generate the Certificate Signing Request (CSR), create a key (e.g. server.key).

以下命令產生 CSR, 而不會啟動 pass phrase 功能 (Apache 2 啟動必需輸入密碼)
{{{
# openssl genrsa -out server.key 4096
Generating RSA private key, 4096 bit long modulus
...................................................................................................................................++
.................................................................................++
e is 65537 (0x10001)
}}}

After the key is created, the Certificate Signing Request (CSR) is created using the key. This will require the following information:
{{{
* Country Name
* State or Province Name
* Locality Name
* Organization Name
* Organizational Unit Name
* Common Name (must match domain name e.g. www.mysecureserver.com)
* Email Address
* Challenge Password
* Company Name
}}}
If the Common Name does not match the DNS name or the IP address of the web server, then the client will get a “domain mismatch” error. Additionally, the default values for the prompts are stored in /etc/ssl/openssl.cnf. Therefore, if there are a large number of certificate signing requests that will need to be created then appropriate defaults can be set.

To create the CSR, run the following command:
{{{
# openssl req -new -key server.key -out server.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:TW
State or Province Name (full name) [Some-State]:Taiwan
Locality Name (eg, city) []:Taipei
Organization Name (eg, company) [Internet Widgits Pty Ltd]:OBF
Organizational Unit Name (eg, section) []:OBF
Common Name (eg, YOUR name) []:AS996
Email Address []:as996@gmail.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:student
An optional company name []:
}}}

''2. Creating/Obtaining a Certificate''
The CSR file is now submitted to the Certificate Authority (CA) for processing. The CA will use the CSR file and issue the certificate. Alternatively, a self-signed certificate using this CSR can be created using the following command:

自己簽發的憑證, 有效日期為 365 天, 執行命令如下 :
{{{
# openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
Signature ok
subject=/C=TW/ST=Taiwan/L=Taipei/O=OBF/OU=OBF/CN=AS996/emailAddress=as996@gmail.com
Getting Private key
}}}

The previous command will prompt for a pass-phrase if using the secure key. Otherwise, if a pass-phrase was not used, then it will not. Once the correct pass-phrase is entered, the certificate will be created and it will be stored in the server.crt file.

''3. Install the key and certificate''
{{{
# mkdir /etc/apache2/ssl/
# cp server.crt /etc/apache2/ssl/
# cp server.key /etc/apache2/ssl/
}}}
<<toBalaNotes "1">>

''4. 啟動 SSL 模組''
{{{
$ sudo a2enmod ssl
}}}

''5. 設定 Default Site 啟動 SSL''
{{{
# nano /etc/apache2/sites-available/default-ssl 
}}}

This file is basically set up but you will want to ''uncomment the SSLOptions line'' and also ''change the SSLCertificate lines'' to reflect the location and name of your new information.
{{{
SSLEngine on
SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
SSLCertificateFile /etc/apache2/ssl/server.crt
SSLCertificateKeyFile /etc/apache2/ssl/server.key
}}}

The port 443 is enabled when you use SSL so that is ready to go.
{{{
sudo a2ensite default-ssl
}}}
If you do not enable the default-ssl you will get this error:
“ssl_error_rx_record_too_long apache”

''6. 重新啟動 Apache 2''
{{{
sudo /etc/init.d/apache2 restart
}}}
<<toBalaNotes "2">>
{{item1{測試 SSL 連接}}}

''1. 啟動 Firefox, 輸入以下 URL :''
{{{
https://192.168.99.6/~student
}}}

''2. 取得 Apache Server 憑證''

[img[img/apache2/a2ssl01.png]]

[img[img/apache2/a2ssl02.png]]

{{item1{檢視憑證}}}
[img[img/apache2/a2ssl03.png]]

[img[img/apache2/a2ssl04.png]]

///%1
//%/

///%2
//%/
{{item1{DNS 設定}}}
在 it66.kvm. 的 Zone 資料庫檔加入 CNAME 及 A 記錄
{{{
# cat /usr/local/etc/bind/it66.kvm.db 
$TTL 86400
@  IN SOA NS660.it66.kvm. admin.NS660.it66.kvm. (
     1      ; Serial number
     43200           ; Refresh timer - 12 hours
     3600            ; Retry timer - 1 hour
     7200            ; Expire timer - 2 hour
     86400           ; Minimum timer - 1 day
)                
@ IN      NS      NS660.it66.kvm.
NS660.it66.kvm. IN A 192.168.66.5
www IN CNAME AS995.it66.kvm.
AS995.it66.kvm. IN A 192.168.99.5
}}}

如在 Tiny Core 系統中設定 BIND, 記得重新開機前要執行以下命令
{{{
# filetool.sh -b
}}}
<<toBalaNotes "1">>
{{item1{Apache 設定}}}
''1. 建立網站目錄區''
{{{
$ sudo mkdir /home/www/it88
$ sudo nano /home/www/it88/index.html
<h1>my it88 web site</h1>

$ sudo mkdir /home/www/it66
$ sudo nano /home/www/it66/index.html
<h1>my it66 web site</h1>
}}}

''2.Virtual Host 設定''
{{{
$ sudo nano /etc/apache2/httpd.conf

<VirtualHost *:80>
        ServerName www.it66.kvm
        DocumentRoot /home/www/it66
</VirtualHost>

<VirtualHost *:80>
        ServerName www.it88.kvm
        DocumentRoot /home/www/it88
</VirtualHost>
}}}

''[註]'' ServerName 的名稱中最後不要加上 句點 (.)
<<toBalaNotes "2">>
///%1
//%/

///%2
//%/
網址 : http://code.google.com/p/shellinabox/

{{item1{Ajax 終端機 : shellinabox}}}

''1. 安裝 shellinabox''
{{{
$ wget http://shellinabox.googlecode.com/files/shellinabox_2.10-1_i386.deb
--2010-09-24 23:38:19--  http://shellinabox.googlecode.com/files/shellinabox_2.10-1_i386.deb
正在查找主機 shellinabox.googlecode.com... 72.14.203.82
正在連接 shellinabox.googlecode.com|72.14.203.82|:80... 連上了。
已送出 HTTP 要求,正在等候回應... 200 OK
長度: 124070 (121K) [application/x-archive application/x-debian-package]
Saving to: `shellinabox_2.10-1_i386.deb'

100%[======================================>] 124,070      110K/s   in 1.1s

2010-09-24 23:38:21 (110 KB/s) - `shellinabox_2.10-1_i386.deb' saved [124070/124070]

$ dpkg -i shellinabox_2.10-1_i386.deb
dpkg: 該操作需要超級使用者權限

$ sudo dpkg -i shellinabox_2.10-1_i386.deb
選取了原先未被選取的套件 shellinabox。
(正在讀取資料庫 ... 系統目前共安裝了 44091 個檔案和目錄。)
正在解開 shellinabox (從 shellinabox_2.10-1_i386.deb)...
正在設定 shellinabox (2.10-1) ...
 * Starting Shell In A Box Daemon shellinabox                            [ OK ]

正在進行 ureadahead 的觸發程式 ...
ureadahead will be reprofiled on next reboot
正在進行 man-db 的觸發程式 ...
}}}

''2. 使用 shellinabox (內定 Port 為 4200)''

[img[img/shellinabox01.png]]

[img[img/shellinabox02.png]]

''[註]'' 無法輸入中文, 可顯示中文

{{item1{取消 4200 port 連接, 只接受 80 port (http) 連接}}}

''1. 修改 /etc/default/shellinabox 設定檔''
{{{
# Should shellinaboxd start automatically
SHELLINABOX_DAEMON_START=1

# TCP port that shellinboxd's webserver listens on
SHELLINABOX_PORT=80                      # 將 4200 改成 80

# Parameters that are managed by the system and usually should not need
# changing:
# SHELLINABOX_DATADIR=/var/lib/shellinabox
# SHELLINABOX_USER=shellinabox
# SHELLINABOX_GROUP=shellinabox

# Any optional arguments (e.g. extra service definitions)
# We disable beeps, as there have been reports of the VLC plugin crashing
# Firefox on Linux/x86_64.
SHELLINABOX_ARGS="--no-beep --disable-ssl"          # 加入 --disable-ssl 這參數 (要有雙引號), 取消執行 ssl 功能, 這樣可增加執行速度
}}}

''2. 重新啟動 shellinabox''
{{{
$ sudo invoke-rc.d shellinabox restart
}}}

{{item1{取消 4200 port 連接, 只接受 443 port (https) 連接}}}

''1. 修改 /etc/default/shellinabox 設定檔''
{{{
$ sudo nano /etc/default/shellinabox
# Should shellinaboxd start automatically
SHELLINABOX_DAEMON_START=1

# TCP port that shellinboxd's webserver listens on
SHELLINABOX_PORT=4200                       # 將 4200 改成 443

# Parameters that are managed by the system and usually should not need
# changing:
# SHELLINABOX_DATADIR=/var/lib/shellinabox
# SHELLINABOX_USER=shellinabox
# SHELLINABOX_GROUP=shellinabox

# Any optional arguments (e.g. extra service definitions)
# We disable beeps, as there have been reports of the VLC plugin crashing
# Firefox on Linux/x86_64.
SHELLINABOX_ARGS=--no-beep
}}}

''2. 重新啟動 shellinabox''
{{{
$ sudo invoke-rc.d shellinabox restart
}}}

<<toBalaNotes "1">>

///%1
//%/

Background: #fff
Foreground: #000
PrimaryPale: #fc8
PrimaryLight: #f81
PrimaryMid: #b40
PrimaryDark: #410
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
/***
|''Name:''|CryptoFunctionsPlugin|
|''Description:''|Support for cryptographic functions|
***/
//{{{
if(!version.extensions.CryptoFunctionsPlugin) {
version.extensions.CryptoFunctionsPlugin = {installed:true};

//--
//-- Crypto functions and associated conversion routines
//--

// Crypto "namespace"
function Crypto() {}

// Convert a string to an array of big-endian 32-bit words
Crypto.strToBe32s = function(str)
{
	var be = Array();
	var len = Math.floor(str.length/4);
	var i, j;
	for(i=0, j=0; i<len; i++, j+=4) {
		be[i] = ((str.charCodeAt(j)&0xff) << 24)|((str.charCodeAt(j+1)&0xff) << 16)|((str.charCodeAt(j+2)&0xff) << 8)|(str.charCodeAt(j+3)&0xff);
	}
	while (j<str.length) {
		be[j>>2] |= (str.charCodeAt(j)&0xff)<<(24-(j*8)%32);
		j++;
	}
	return be;
};

// Convert an array of big-endian 32-bit words to a string
Crypto.be32sToStr = function(be)
{
	var str = "";
	for(var i=0;i<be.length*32;i+=8)
		str += String.fromCharCode((be[i>>5]>>>(24-i%32)) & 0xff);
	return str;
};

// Convert an array of big-endian 32-bit words to a hex string
Crypto.be32sToHex = function(be)
{
	var hex = "0123456789ABCDEF";
	var str = "";
	for(var i=0;i<be.length*4;i++)
		str += hex.charAt((be[i>>2]>>((3-i%4)*8+4))&0xF) + hex.charAt((be[i>>2]>>((3-i%4)*8))&0xF);
	return str;
};

// Return, in hex, the SHA-1 hash of a string
Crypto.hexSha1Str = function(str)
{
	return Crypto.be32sToHex(Crypto.sha1Str(str));
};

// Return the SHA-1 hash of a string
Crypto.sha1Str = function(str)
{
	return Crypto.sha1(Crypto.strToBe32s(str),str.length);
};

// Calculate the SHA-1 hash of an array of blen bytes of big-endian 32-bit words
Crypto.sha1 = function(x,blen)
{
	// Add 32-bit integers, wrapping at 32 bits
	add32 = function(a,b)
	{
		var lsw = (a&0xFFFF)+(b&0xFFFF);
		var msw = (a>>16)+(b>>16)+(lsw>>16);
		return (msw<<16)|(lsw&0xFFFF);
	};
	// Add five 32-bit integers, wrapping at 32 bits
	add32x5 = function(a,b,c,d,e)
	{
		var lsw = (a&0xFFFF)+(b&0xFFFF)+(c&0xFFFF)+(d&0xFFFF)+(e&0xFFFF);
		var msw = (a>>16)+(b>>16)+(c>>16)+(d>>16)+(e>>16)+(lsw>>16);
		return (msw<<16)|(lsw&0xFFFF);
	};
	// Bitwise rotate left a 32-bit integer by 1 bit
	rol32 = function(n)
	{
		return (n>>>31)|(n<<1);
	};

	var len = blen*8;
	// Append padding so length in bits is 448 mod 512
	x[len>>5] |= 0x80 << (24-len%32);
	// Append length
	x[((len+64>>9)<<4)+15] = len;
	var w = Array(80);

	var k1 = 0x5A827999;
	var k2 = 0x6ED9EBA1;
	var k3 = 0x8F1BBCDC;
	var k4 = 0xCA62C1D6;

	var h0 = 0x67452301;
	var h1 = 0xEFCDAB89;
	var h2 = 0x98BADCFE;
	var h3 = 0x10325476;
	var h4 = 0xC3D2E1F0;

	for(var i=0;i<x.length;i+=16) {
		var j,t;
		var a = h0;
		var b = h1;
		var c = h2;
		var d = h3;
		var e = h4;
		for(j = 0;j<16;j++) {
			w[j] = x[i+j];
			t = add32x5(e,(a>>>27)|(a<<5),d^(b&(c^d)),w[j],k1);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}
		for(j=16;j<20;j++) {
			w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
			t = add32x5(e,(a>>>27)|(a<<5),d^(b&(c^d)),w[j],k1);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}
		for(j=20;j<40;j++) {
			w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
			t = add32x5(e,(a>>>27)|(a<<5),b^c^d,w[j],k2);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}
		for(j=40;j<60;j++) {
			w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
			t = add32x5(e,(a>>>27)|(a<<5),(b&c)|(d&(b|c)),w[j],k3);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}
		for(j=60;j<80;j++) {
			w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
			t = add32x5(e,(a>>>27)|(a<<5),b^c^d,w[j],k4);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}

		h0 = add32(h0,a);
		h1 = add32(h1,b);
		h2 = add32(h2,c);
		h3 = add32(h3,d);
		h4 = add32(h4,e);
	}
	return Array(h0,h1,h2,h3,h4);
};


}
//}}}


首頁
/***
|''Name:''|DeprecatedFunctionsPlugin|
|''Description:''|Support for deprecated functions removed from core|
***/
//{{{
if(!version.extensions.DeprecatedFunctionsPlugin) {
version.extensions.DeprecatedFunctionsPlugin = {installed:true};

//--
//-- Deprecated code
//--

// @Deprecated: Use createElementAndWikify and this.termRegExp instead
config.formatterHelpers.charFormatHelper = function(w)
{
	w.subWikify(createTiddlyElement(w.output,this.element),this.terminator);
};

// @Deprecated: Use enclosedTextHelper and this.lookaheadRegExp instead
config.formatterHelpers.monospacedByLineHelper = function(w)
{
	var lookaheadRegExp = new RegExp(this.lookahead,"mg");
	lookaheadRegExp.lastIndex = w.matchStart;
	var lookaheadMatch = lookaheadRegExp.exec(w.source);
	if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
		var text = lookaheadMatch[1];
		if(config.browser.isIE)
			text = text.replace(/\n/g,"\r");
		createTiddlyElement(w.output,"pre",null,null,text);
		w.nextMatch = lookaheadRegExp.lastIndex;
	}
};

// @Deprecated: Use <br> or <br /> instead of <<br>>
config.macros.br = {};
config.macros.br.handler = function(place)
{
	createTiddlyElement(place,"br");
};

// Find an entry in an array. Returns the array index or null
// @Deprecated: Use indexOf instead
Array.prototype.find = function(item)
{
	var i = this.indexOf(item);
	return i == -1 ? null : i;
};

// Load a tiddler from an HTML DIV. The caller should make sure to later call Tiddler.changed()
// @Deprecated: Use store.getLoader().internalizeTiddler instead
Tiddler.prototype.loadFromDiv = function(divRef,title)
{
	return store.getLoader().internalizeTiddler(store,this,title,divRef);
};

// Format the text for storage in an HTML DIV
// @Deprecated Use store.getSaver().externalizeTiddler instead.
Tiddler.prototype.saveToDiv = function()
{
	return store.getSaver().externalizeTiddler(store,this);
};

// @Deprecated: Use store.allTiddlersAsHtml() instead
function allTiddlersAsHtml()
{
	return store.allTiddlersAsHtml();
}

// @Deprecated: Use refreshPageTemplate instead
function applyPageTemplate(title)
{
	refreshPageTemplate(title);
}

// @Deprecated: Use story.displayTiddlers instead
function displayTiddlers(srcElement,titles,template,unused1,unused2,animate,unused3)
{
	story.displayTiddlers(srcElement,titles,template,animate);
}

// @Deprecated: Use story.displayTiddler instead
function displayTiddler(srcElement,title,template,unused1,unused2,animate,unused3)
{
	story.displayTiddler(srcElement,title,template,animate);
}

// @Deprecated: Use functions on right hand side directly instead
var createTiddlerPopup = Popup.create;
var scrollToTiddlerPopup = Popup.show;
var hideTiddlerPopup = Popup.remove;

// @Deprecated: Use right hand side directly instead
var regexpBackSlashEn = new RegExp("\\\\n","mg");
var regexpBackSlash = new RegExp("\\\\","mg");
var regexpBackSlashEss = new RegExp("\\\\s","mg");
var regexpNewLine = new RegExp("\n","mg");
var regexpCarriageReturn = new RegExp("\r","mg");

}
//}}}
/***
|Name|DisableWikiLinksPlugin|
|Source|http://www.TiddlyTools.com/#DisableWikiLinksPlugin|
|Version|1.5.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|Tiddler.prototype.autoLinkWikiWords, 'wikiLink' formatter|
|Options|##Configuration|
|Description|selectively disable TiddlyWiki's automatic ~WikiWord linking behavior|
This plugin allows you to disable TiddlyWiki's automatic ~WikiWord linking behavior, so that WikiWords embedded in tiddler content will be rendered as regular text, instead of being automatically converted to tiddler links.  To create a tiddler link when automatic linking is disabled, you must enclose the link text within {{{[[...]]}}}.
!!!!!Usage
<<<
You can block automatic WikiWord linking behavior for any specific tiddler by ''tagging it with<<tag excludeWikiWords>>'' (see configuration below) or, check a plugin option to disable automatic WikiWord links to non-existing tiddler titles, while still linking WikiWords that correspond to existing tiddlers titles or shadow tiddler titles.  You can also block specific selected WikiWords from being automatically linked by listing them in [[DisableWikiLinksList]] (see configuration below), separated by whitespace.  This tiddler is optional and, when present, causes the listed words to always be excluded, even if automatic linking of other WikiWords is being permitted.  

Note: WikiWords contained in default ''shadow'' tiddlers will be automatically linked unless you select an additional checkbox option lets you disable these automatic links as well, though this is not recommended, since it can make it more difficult to access some TiddlyWiki standard default content (such as AdvancedOptions or SideBarTabs)
<<<
!!!!!Configuration
<<<
<<option chkDisableWikiLinks>> Disable ALL automatic WikiWord tiddler links
<<option chkAllowLinksFromShadowTiddlers>> ... except for WikiWords //contained in// shadow tiddlers
<<option chkDisableNonExistingWikiLinks>> Disable automatic WikiWord links for non-existing tiddlers
Disable automatic WikiWord links for words listed in: <<option txtDisableWikiLinksList>>
Disable automatic WikiWord links for tiddlers tagged with: <<option txtDisableWikiLinksTag>>
<<<
!!!!!Code
***/
//{{{
version.extensions.disableWikiLinks= {major: 1, minor: 5, revision: 0, date: new Date(2007,6,9)};

if (config.options.chkDisableNonExistingWikiLinks==undefined) config.options.chkDisableNonExistingWikiLinks= false;
if (config.options.chkDisableWikiLinks==undefined) config.options.chkDisableWikiLinks=false;
if (config.options.txtDisableWikiLinksList==undefined) config.options.txtDisableWikiLinksList="DisableWikiLinksList";
if (config.options.chkAllowLinksFromShadowTiddlers==undefined) config.options.chkAllowLinksFromShadowTiddlers=true;
if (config.options.txtDisableWikiLinksTag==undefined) config.options.txtDisableWikiLinksTag="excludeWikiWords";

// find the formatter for wikiLink and replace handler with 'pass-thru' rendering
initDisableWikiLinksFormatter();
function initDisableWikiLinksFormatter() {
	for (var i=0; i<config.formatters.length && config.formatters[i].name!="wikiLink"; i++);
	config.formatters[i].coreHandler=config.formatters[i].handler;
	config.formatters[i].handler=function(w) {
		// supress any leading "~" (if present)
		var skip=(w.matchText.substr(0,1)==config.textPrimitives.unWikiLink)?1:0;
		var title=w.matchText.substr(skip);
		var exists=store.tiddlerExists(title);
		var inShadow=w.tiddler && store.isShadowTiddler(w.tiddler.title);

		// check for excluded Tiddler
		if (w.tiddler && w.tiddler.isTagged(config.options.txtDisableWikiLinksTag))
			{ w.outputText(w.output,w.matchStart+skip,w.nextMatch); return; }
		
		// check for specific excluded wiki words
		var t=store.getTiddlerText(config.options.txtDisableWikiLinksList)
		if (t && t.length && t.indexOf(w.matchText)!=-1)
			{ w.outputText(w.output,w.matchStart+skip,w.nextMatch); return; }

		// if not disabling links from shadows (default setting)
		if (config.options.chkAllowLinksFromShadowTiddlers && inShadow)
			return this.coreHandler(w);

		// check for non-existing non-shadow tiddler
		if (config.options.chkDisableNonExistingWikiLinks && !exists)
			{ w.outputText(w.output,w.matchStart+skip,w.nextMatch); return; }

		// if not enabled, just do standard WikiWord link formatting
		if (!config.options.chkDisableWikiLinks)
			return this.coreHandler(w);

		// just return text without linking
		w.outputText(w.output,w.matchStart+skip,w.nextMatch)
	}
}

Tiddler.prototype.coreAutoLinkWikiWords = Tiddler.prototype.autoLinkWikiWords;
Tiddler.prototype.autoLinkWikiWords = function()
{
	// DEBUG alert("processing: "+this.title);
	// if all automatic links are not disabled, just return results from core function
	if (!config.options.chkDisableWikiLinks)
		return this.coreAutoLinkWikiWords.apply(this,arguments);
	return false;
}
//}}}
/*{{{*/
 
/*}}}*/
/*{{{*/
a {color:#0044BB;font-weight:bold}
/*}}}*/
<!--{{{-->
<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler deleteTiddler'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='easyEdit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler deleteTiddler'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>
<!--}}}-->
/***
|Name|ExportTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#ExportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ExportTiddlersPluginInfo|
|Version|2.7.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|select and extract tiddlers from your ~TiddlyWiki documents and save them to a separate file|
ExportTiddlersPlugin lets you select and extract tiddlers from your ~TiddlyWiki documents using interactive control panel lets you specify a destination, and then select which tiddlers to export. Tiddler data can be output as complete, stand-alone TiddlyWiki documents, or just the selected tiddlers ("~PureStore" format -- smaller files!) that can be imported directly into another ~TiddlyWiki, or as an ~RSS-compatible XML file that can be published for RSS syndication.
!!!!!Documentation
>see [[ExportTiddlersPluginInfo]]
!!!!!Code
***/
//{{{
// version
version.extensions.exportTiddlers = {major: 2, minor: 7, revision: 0, date: new Date(2008,5,27)};

// default shadow definition
config.shadowTiddlers.ExportTiddlers="<<exportTiddlers inline>>";

// add 'export' backstage task (following built-in import task)
if (config.tasks) { // TW2.2 or above
	config.tasks.exportTask = {
		text:"export",
		tooltip:"Export selected tiddlers to another file",
		content:"<<exportTiddlers inline>>"
	}
	config.backstageTasks.splice(config.backstageTasks.indexOf("importTask")+1,0,"exportTask");
}

// macro handler
config.macros.exportTiddlers = {
	label: "export tiddlers",
	prompt: "Copy selected tiddlers to an export document",
	newdefault: "export.html",
	datetimefmt: "0MM/0DD/YYYY 0hh:0mm:0ss" // for "filter date/time" edit fields
};

config.macros.exportTiddlers.handler = function(place,macroName,params) {
	if (params[0]!="inline")
		{ createTiddlyButton(place,this.label,this.prompt,onClickExportMenu); return; }
	var panel=createExportPanel(place);
	panel.style.position="static";
	panel.style.display="block";
}

function createExportPanel(place) {
	var panel=document.getElementById("exportPanel");
	if (panel) { panel.parentNode.removeChild(panel); }
	setStylesheet(config.macros.exportTiddlers.css,"exportTiddlers");
	panel=createTiddlyElement(place,"span","exportPanel",null,null)
	panel.innerHTML=config.macros.exportTiddlers.html;
	exportInitFilter();
	refreshExportList(0);
	var fn=document.getElementById("exportFilename");
	if (window.location.protocol=="file:" && !fn.value.length) {
		// get new target path/filename
		var newPath=getLocalPath(window.location.href);
		var slashpos=newPath.lastIndexOf("/"); if (slashpos==-1) slashpos=newPath.lastIndexOf("\\"); 
		if (slashpos!=-1) newPath=newPath.substr(0,slashpos+1); // trim filename
		fn.value=newPath+config.macros.exportTiddlers.newdefault;
	}
	return panel;
}

function onClickExportMenu(e)
{
	if (!e) var e = window.event;
	var parent=resolveTarget(e).parentNode;
	var panel = document.getElementById("exportPanel");
	if (panel==undefined || panel.parentNode!=parent)
		panel=createExportPanel(parent);
	var isOpen = panel.style.display=="block";
	if(config.options.chkAnimate)
		anim.startAnimating(new Slider(panel,!isOpen,e.shiftKey || e.altKey,"none"));
	else
		panel.style.display = isOpen ? "none" : "block" ;
	if (panel.style.display!="none") { // update list and set focus when panel is made visible
		refreshExportList(0);
		var fn=document.getElementById("exportFilename"); fn.focus(); fn.select();
	}
	e.cancelBubble = true;
	if (e.stopPropagation) e.stopPropagation();
	return(false);
}
//}}}

// // IE needs explicit scoping for functions called by browser events
//{{{
window.onClickExportMenu=onClickExportMenu;
window.onClickExportButton=onClickExportButton;
window.exportShowFilterFields=exportShowFilterFields;
window.refreshExportList=refreshExportList;
//}}}

// // CSS for floating export control panel
//{{{
config.macros.exportTiddlers.css = '\
#exportPanel {\
	display: none; position:absolute; z-index:12; width:45em; right:105%; top:6em;\
	background-color: #eee; color:#000; font-size: 10pt; line-height:110%;\
	border:1px solid black; border-bottom-width: 3px; border-right-width: 3px;\
	padding: 0.5em; margin:0em; -moz-border-radius:1em;\
}\
#exportPanel a, #exportPanel td a { color:#009; display:inline; margin:0px; padding:1px; }\
#exportPanel table { width:100%; border:0px; padding:0px; margin:0px; font-size:10pt; line-height:110%; background:transparent; }\
#exportPanel tr { border:0px;padding:0px;margin:0px; background:transparent; }\
#exportPanel td { color:#000; border:0px;padding:0px;margin:0px; background:transparent; }\
#exportPanel select { width:98%;margin:0px;font-size:10pt;line-height:110%;}\
#exportPanel input  { width:98%;padding:0px;margin:0px;font-size:10pt;line-height:110%; }\
#exportPanel textarea  { width:98%;padding:0px;margin:0px;overflow:auto;font-size:10pt; }\
#exportPanel .box { border:1px solid black; padding:3px; margin-bottom:5px; background:#f8f8f8; -moz-border-radius:5px; }\
#exportPanel .topline { border-top:2px solid black; padding-top:3px; margin-bottom:5px; }\
#exportPanel .rad { width:auto;border:0 }\
#exportPanel .chk { width:auto;border:0 }\
#exportPanel .btn { width:auto; }\
#exportPanel .btn1 { width:98%; }\
#exportPanel .btn2 { width:48%; }\
#exportPanel .btn3 { width:32%; }\
#exportPanel .btn4 { width:24%; }\
#exportPanel .btn5 { width:19%; }\
';
//}}}

// // HTML for export control panel interface
//{{{
config.macros.exportTiddlers.html = '\
<!-- target path/file  -->\
<div>\
export to path/filename:<br>\
<input type="text" id="exportFilename" size=40 style="width:93%"><input \
	type="button" id="exportBrowse" value="..." title="select or enter a local folder/file..." style="width:5%" \
	onclick="var fn=window.promptForExportFilename(this); if (fn.length) this.previousSibling.value=fn; ">\
</div>\
\
<!-- output format -->\
<div>\
output file format:\
<select id="exportFormat" size=1>\
<option value="TW">TiddlyWiki document (includes core code)</option>\
<option value="DIV">TiddlyWiki "PureStore" file (tiddler data only)</option>\
<option value="XML">XML (for RSS newsfeed)</option>\
</select>\
</div>\
\
<!-- notes -->\
<div>\
notes:<br>\
<textarea id="exportNotes" rows=3 cols=40 style="height:4em;margin-bottom:5px;" onfocus="this.select()"></textarea> \
</div>\
\
<!-- list of tiddlers -->\
<table><tr align="left"><td>\
	select:\
	<a href="JavaScript:;" id="exportSelectAll"\
		onclick="onClickExportButton(this)" title="select all tiddlers">\
		&nbsp;all&nbsp;</a>\
	<a href="JavaScript:;" id="exportSelectChanges"\
		onclick="onClickExportButton(this)" title="select tiddlers changed since last save">\
		&nbsp;changes&nbsp;</a> \
	<a href="JavaScript:;" id="exportSelectOpened"\
		onclick="onClickExportButton(this)" title="select tiddlers currently being displayed">\
		&nbsp;opened&nbsp;</a> \
	<a href="JavaScript:;" id="exportSelectRelated"\
		onclick="onClickExportButton(this)" title="select all tiddlers related (by link or transclusion) to the currently selected tiddlers">\
		&nbsp;related&nbsp;</a> \
	<a href="JavaScript:;" id="exportToggleFilter"\
		onclick="onClickExportButton(this)" title="show/hide selection filter">\
		&nbsp;filter&nbsp;</a>  \
</td><td align="right">\
	<a href="JavaScript:;" id="exportListSmaller"\
		onclick="onClickExportButton(this)" title="reduce list size">\
		&nbsp;&#150;&nbsp;</a>\
	<a href="JavaScript:;" id="exportListLarger"\
		onclick="onClickExportButton(this)" title="increase list size">\
		&nbsp;+&nbsp;</a>\
</td></tr></table>\
<select id="exportList" multiple size="20" style="margin-bottom:5px;"\
	onchange="refreshExportList(this.selectedIndex)">\
</select><br>\
</div><!--box-->\
\
<!-- selection filter -->\
<div id="exportFilterPanel" style="display:none">\
<table><tr align="left"><td>\
	selection filter\
</td><td align="right">\
	<a href="JavaScript:;" id="exportHideFilter"\
		onclick="onClickExportButton(this)" title="hide selection filter">hide</a>\
</td></tr></table>\
<div class="box">\
<input type="checkbox" class="chk" id="exportFilterStart" value="1"\
	onclick="exportShowFilterFields(this)"> starting date/time<br>\
<table cellpadding="0" cellspacing="0"><tr valign="center"><td width="50%">\
	<select size=1 id="exportFilterStartBy" onchange="exportShowFilterFields(this);">\
		<option value="0">today</option>\
		<option value="1">yesterday</option>\
		<option value="7">a week ago</option>\
		<option value="30">a month ago</option>\
		<option value="site">SiteDate</option>\
		<option value="file">file date</option>\
		<option value="other">other (mm/dd/yyyy hh:mm)</option>\
	</select>\
</td><td width="50%">\
	<input type="text" id="exportStartDate" onfocus="this.select()"\
		onchange="document.getElementById(\'exportFilterStartBy\').value=\'other\';">\
</td></tr></table>\
<input type="checkbox" class="chk" id="exportFilterEnd" value="1"\
	onclick="exportShowFilterFields(this)"> ending date/time<br>\
<table cellpadding="0" cellspacing="0"><tr valign="center"><td width="50%">\
	<select size=1 id="exportFilterEndBy" onchange="exportShowFilterFields(this);">\
		<option value="0">today</option>\
		<option value="1">yesterday</option>\
		<option value="7">a week ago</option>\
		<option value="30">a month ago</option>\
		<option value="site">SiteDate</option>\
		<option value="file">file date</option>\
		<option value="other">other (mm/dd/yyyy hh:mm)</option>\
	</select>\
</td><td width="50%">\
	<input type="text" id="exportEndDate" onfocus="this.select()"\
		onchange="document.getElementById(\'exportFilterEndBy\').value=\'other\';">\
</td></tr></table>\
<input type="checkbox" class="chk" id=exportFilterTags value="1"\
	onclick="exportShowFilterFields(this)"> match tags<br>\
<input type="text" id="exportTags" onfocus="this.select()">\
<input type="checkbox" class="chk" id=exportFilterText value="1"\
	onclick="exportShowFilterFields(this)"> match titles/tiddler text<br>\
<input type="text" id="exportText" onfocus="this.select()">\
</div> <!--box-->\
</div> <!--panel-->\
\
<!-- action buttons -->\
<div style="text-align:center">\
<input type=button class="btn4" onclick="onClickExportButton(this)"\
	id="exportFilter" value="apply filter">\
<input type=button class="btn4" onclick="onClickExportButton(this)"\
	id="exportStart" value="export tiddlers">\
<input type=button class="btn4" onclick="onClickExportButton(this)"\
	id="exportDelete" value="delete tiddlers">\
<input type=button class="btn4" onclick="onClickExportButton(this)"\
	id="exportClose" value="close">\
</div><!--center-->\
';
//}}}

// // initialize interface

// // exportInitFilter()
//{{{
function exportInitFilter() {
	// start date
	document.getElementById("exportFilterStart").checked=false;
	document.getElementById("exportStartDate").value="";
	// end date
	document.getElementById("exportFilterEnd").checked=false;
	document.getElementById("exportEndDate").value="";
	// tags
	document.getElementById("exportFilterTags").checked=false;
	document.getElementById("exportTags").value="";
	// text
	document.getElementById("exportFilterText").checked=false;
	document.getElementById("exportText").value="";
	// show/hide filter input fields
	exportShowFilterFields();
}
//}}}

// // exportShowFilterFields(which)
//{{{
function exportShowFilterFields(which) {
	var show;

	show=document.getElementById('exportFilterStart').checked;
	document.getElementById('exportFilterStartBy').style.display=show?"block":"none";
	document.getElementById('exportStartDate').style.display=show?"block":"none";
	var val=document.getElementById('exportFilterStartBy').value;
	document.getElementById('exportStartDate').value
		=getFilterDate(val,'exportStartDate').formatString(config.macros.exportTiddlers.datetimefmt);
	 if (which && (which.id=='exportFilterStartBy') && (val=='other'))
		document.getElementById('exportStartDate').focus();

	show=document.getElementById('exportFilterEnd').checked;
	document.getElementById('exportFilterEndBy').style.display=show?"block":"none";
	document.getElementById('exportEndDate').style.display=show?"block":"none";
	var val=document.getElementById('exportFilterEndBy').value;
	document.getElementById('exportEndDate').value
		=getFilterDate(val,'exportEndDate').formatString(config.macros.exportTiddlers.datetimefmt);
	 if (which && (which.id=='exportFilterEndBy') && (val=='other'))
		document.getElementById('exportEndDate').focus();

	show=document.getElementById('exportFilterTags').checked;
	document.getElementById('exportTags').style.display=show?"block":"none";

	show=document.getElementById('exportFilterText').checked;
	document.getElementById('exportText').style.display=show?"block":"none";
}
//}}}

// // onClickExportButton(which): control interactions
//{{{
function onClickExportButton(which)
{
	// DEBUG alert(which.id);
	var theList=document.getElementById('exportList'); if (!theList) return;
	var count = 0;
	var total = store.getTiddlers('title').length;
	switch (which.id)
		{
		case 'exportFilter':
			count=filterExportList();
			var panel=document.getElementById('exportFilterPanel');
			if (count==-1) { panel.style.display='block'; break; }
			document.getElementById("exportStart").disabled=(count==0);
			document.getElementById("exportDelete").disabled=(count==0);
			clearMessage(); displayMessage("filtered "+formatExportMessage(count,total));
			if (count==0) { alert("No tiddlers were selected"); panel.style.display='block'; }
			break;
		case 'exportStart':
			exportTiddlers();
			break;
		case 'exportDelete':
			exportDeleteTiddlers();
			break;
		case 'exportHideFilter':
		case 'exportToggleFilter':
			var panel=document.getElementById('exportFilterPanel')
			panel.style.display=(panel.style.display=='block')?'none':'block';
			break;
		case 'exportSelectChanges':
			var lastmod=new Date(document.lastModified);
			for (var t = 0; t < theList.options.length; t++) {
				if (theList.options[t].value=="") continue;
				var tiddler=store.getTiddler(theList.options[t].value); if (!tiddler) continue;
				theList.options[t].selected=(tiddler.modified>lastmod);
				count += (tiddler.modified>lastmod)?1:0;
			}
			document.getElementById("exportStart").disabled=(count==0);
			document.getElementById("exportDelete").disabled=(count==0);
			clearMessage(); displayMessage(formatExportMessage(count,total));
			if (count==0) alert("There are no unsaved changes");
			break;
		case 'exportSelectAll':
			for (var t = 0; t < theList.options.length; t++) {
				if (theList.options[t].value=="") continue;
				theList.options[t].selected=true;
				count += 1;
			}
			document.getElementById("exportStart").disabled=(count==0);
			document.getElementById("exportDelete").disabled=(count==0);
			clearMessage(); displayMessage(formatExportMessage(count,count));
			break;
		case 'exportSelectOpened':
			for (var t = 0; t < theList.options.length; t++) theList.options[t].selected=false;
			var tiddlerDisplay = document.getElementById("tiddlerDisplay"); // for TW2.1-
			if (!tiddlerDisplay) tiddlerDisplay = document.getElementById("storyDisplay"); // for TW2.2+
			for (var t=0;t<tiddlerDisplay.childNodes.length;t++) {
				var tiddler=tiddlerDisplay.childNodes[t].id.substr(7);
				for (var i = 0; i < theList.options.length; i++) {
					if (theList.options[i].value!=tiddler) continue;
					theList.options[i].selected=true; count++; break;
				}
			}
			document.getElementById("exportStart").disabled=(count==0);
			document.getElementById("exportDelete").disabled=(count==0);
			clearMessage(); displayMessage(formatExportMessage(count,total));
			if (count==0) alert("There are no tiddlers currently opened");
			break;
		case 'exportSelectRelated':
			// recursively build list of related tiddlers
			function getRelatedTiddlers(tid,tids) {
				var t=store.getTiddler(tid); if (!t || tids.contains(tid)) return tids;
				tids.push(t.title);
				if (!t.linksUpdated) t.changed();
				for (var i=0; i<t.links.length; i++)
					if (t.links[i]!=tid) tids=getRelatedTiddlers(t.links[i],tids);
				return tids;
			}
			// for all currently selected tiddlers, gather up the related tiddlers (including self) and select them as well
			var tids=[];
			for (var i=0; i<theList.options.length; i++)
				if (theList.options[i].selected) tids=getRelatedTiddlers(theList.options[i].value,tids);
			// select related tiddlers (includes original selected tiddlers)
			for (var i=0; i<theList.options.length; i++)
				theList.options[i].selected=tids.contains(theList.options[i].value);
			clearMessage(); displayMessage(formatExportMessage(tids.length,total));
			break;
		case 'exportListSmaller':	// decrease current listbox size
			var min=5;
			theList.size-=(theList.size>min)?1:0;
			break;
		case 'exportListLarger':	// increase current listbox size
			var max=(theList.options.length>25)?theList.options.length:25;
			theList.size+=(theList.size<max)?1:0;
			break;
		case 'exportClose':
			document.getElementById('exportPanel').style.display='none';
			break;
		}
}
//}}}

// // promptForFilename(msg,path,file) uses platform/browser specific functions to get local filespec
//{{{
window.promptForExportFilename=function(here)
{
	var msg=here.title; // use tooltip as dialog box message
	var path=getLocalPath(document.location.href);
	var slashpos=path.lastIndexOf("/"); if (slashpos==-1) slashpos=path.lastIndexOf("\\"); 
	if (slashpos!=-1) path = path.substr(0,slashpos+1); // remove filename from path, leave the trailing slash
	var file=config.macros.exportTiddlers.newdefault;
	var result="";
	if(window.Components) { // moz
		try {
			netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
			var nsIFilePicker = window.Components.interfaces.nsIFilePicker;
			var picker = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
			picker.init(window, msg, nsIFilePicker.modeSave);
			var thispath = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
			thispath.initWithPath(path);
			picker.displayDirectory=thispath;
			picker.defaultExtension='html';
			picker.defaultString=file;
			picker.appendFilters(nsIFilePicker.filterAll|nsIFilePicker.filterText|nsIFilePicker.filterHTML);
			if (picker.show()!=nsIFilePicker.returnCancel) var result=picker.file.persistentDescriptor;
		}
		catch(e) { alert('error during local file access: '+e.toString()) }
	}
	else { // IE
		try { // XPSP2 IE only
			var s = new ActiveXObject('UserAccounts.CommonDialog');
			s.Filter='All files|*.*|Text files|*.txt|HTML files|*.htm;*.html|';
			s.FilterIndex=3; // default to HTML files;
			s.InitialDir=path;
			s.FileName=file;
			if (s.showOpen()) var result=s.FileName;
		}
		catch(e) {  // fallback
			var result=prompt(msg,path+file);
		}
	}
	return result;
}
//}}}

// // list display
//{{{
function formatExportMessage(count,total)
{
	var txt=total+' tiddler'+((total!=1)?'s':'')+" - ";
	txt += (count==0)?"none":(count==total)?"all":count;
	txt += " selected for export";
	return txt;
}

function refreshExportList(selectedIndex)
{
	var theList  = document.getElementById("exportList");
	var sort;
	if (!theList) return;
	// get the sort order
	if (!selectedIndex)   selectedIndex=0;
	if (selectedIndex==0) sort='modified';
	if (selectedIndex==1) sort='title';
	if (selectedIndex==2) sort='modified';
	if (selectedIndex==3) sort='modifier';
	if (selectedIndex==4) sort='tags';

	// unselect headings and count number of tiddlers actually selected
	var count=0;
	for (var t=5; t < theList.options.length; t++) {
		if (!theList.options[t].selected) continue;
		if (theList.options[t].value!="")
			count++;
		else { // if heading is selected, deselect it, and then select and count all in section
			theList.options[t].selected=false;
			for ( t++; t<theList.options.length && theList.options[t].value!=""; t++) {
				theList.options[t].selected=true;
				count++;
			}
		}
	}

	// disable "export" and "delete" buttons if no tiddlers selected
	document.getElementById("exportStart").disabled=(count==0);
	document.getElementById("exportDelete").disabled=(count==0);
	// show selection count
	var tiddlers = store.getTiddlers('title');
	if (theList.options.length) { clearMessage(); displayMessage(formatExportMessage(count,tiddlers.length)); }

	// if a [command] item, reload list... otherwise, no further refresh needed
	if (selectedIndex>4)  return;

	// clear current list contents
	while (theList.length > 0) { theList.options[0] = null; }
	// add heading and control items to list
	var i=0;
	var indent=String.fromCharCode(160)+String.fromCharCode(160);
	theList.options[i++]=
		new Option(tiddlers.length+" tiddlers in document", "",false,false);
	theList.options[i++]=
		new Option(((sort=="title"        )?">":indent)+' [by title]', "",false,false);
	theList.options[i++]=
		new Option(((sort=="modified")?">":indent)+' [by date]', "",false,false);
	theList.options[i++]=
		new Option(((sort=="modifier")?">":indent)+' [by author]', "",false,false);
	theList.options[i++]=
		new Option(((sort=="tags"	)?">":indent)+' [by tags]', "",false,false);
	// output the tiddler list
	switch(sort)
		{
		case "title":
			for(var t = 0; t < tiddlers.length; t++)
				theList.options[i++] = new Option(tiddlers[t].title,tiddlers[t].title,false,false);
			break;
		case "modifier":
		case "modified":
			var tiddlers = store.getTiddlers(sort);
			// sort descending for newest date first
			tiddlers.sort(function (a,b) {if(a[sort] == b[sort]) return(0); else return (a[sort] > b[sort]) ? -1 : +1; });
			var lastSection = "";
			for(var t = 0; t < tiddlers.length; t++)
				{
				var tiddler = tiddlers[t];
				var theSection = "";
				if (sort=="modified") theSection=tiddler.modified.toLocaleDateString();
				if (sort=="modifier") theSection=tiddler.modifier;
				if (theSection != lastSection)
					{
					theList.options[i++] = new Option(theSection,"",false,false);
					lastSection = theSection;
					}
				theList.options[i++] = new Option(indent+indent+tiddler.title,tiddler.title,false,false);
				}
			 break;
		case "tags":
			var theTitles = {}; // all tiddler titles, hash indexed by tag value
			var theTags = new Array();
			for(var t=0; t<tiddlers.length; t++) {
				var title=tiddlers[t].title;
				var tags=tiddlers[t].tags;
				if (!tags || !tags.length) {
					if (theTitles["untagged"]==undefined) { theTags.push("untagged"); theTitles["untagged"]=new Array(); }
					theTitles["untagged"].push(title);
				}
				else for(var s=0; s<tags.length; s++) {
					if (theTitles[tags[s]]==undefined) { theTags.push(tags[s]); theTitles[tags[s]]=new Array(); }
					theTitles[tags[s]].push(title);
				}
			}
			theTags.sort();
			for(var tagindex=0; tagindex<theTags.length; tagindex++) {
				var theTag=theTags[tagindex];
				theList.options[i++]=new Option(theTag,"",false,false);
				for(var t=0; t<theTitles[theTag].length; t++)
					theList.options[i++]=new Option(indent+indent+theTitles[theTag][t],theTitles[theTag][t],false,false);
			}
			break;
		}
	theList.selectedIndex=selectedIndex;		  // select current control item
	document.getElementById("exportStart").disabled=true;
	document.getElementById("exportDelete").disabled=true;
	clearMessage(); displayMessage(formatExportMessage(0,tiddlers.length));
}
//}}}

// // list filtering
//{{{
function getFilterDate(val,id)
{
	var result=0;
	switch (val) {
		case 'site':
			var timestamp=store.getTiddlerText("SiteDate");
			if (!timestamp) timestamp=document.lastModified;
			result=new Date(timestamp);
			break;
		case 'file':
			result=new Date(document.lastModified);
			break;
		case 'other':
			result=new Date(document.getElementById(id).value);
			break;
		default: // today=0, yesterday=1, one week=7, two weeks=14, a month=31
			var now=new Date(); var tz=now.getTimezoneOffset()*60000; now-=tz;
			var oneday=86400000;
			if (id=='exportStartDate')
				result=new Date((Math.floor(now/oneday)-val)*oneday+tz);
			else
				result=new Date((Math.floor(now/oneday)-val+1)*oneday+tz-1);
			break;
	}
	// DEBUG alert('getFilterDate('+val+','+id+')=='+result+"\nnow="+now);
	return result;
}

function filterExportList()
{
	var theList  = document.getElementById("exportList"); if (!theList) return -1;

	var filterStart=document.getElementById("exportFilterStart").checked;
	var val=document.getElementById("exportFilterStartBy").value;
	var startDate=getFilterDate(val,'exportStartDate');

	var filterEnd=document.getElementById("exportFilterEnd").checked;
	var val=document.getElementById("exportFilterEndBy").value;
	var endDate=getFilterDate(val,'exportEndDate');

	var filterTags=document.getElementById("exportFilterTags").checked;
	var tags=document.getElementById("exportTags").value;

	var filterText=document.getElementById("exportFilterText").checked;
	var text=document.getElementById("exportText").value;

	if (!(filterStart||filterEnd||filterTags||filterText)) {
		alert("Please set the selection filter");
		document.getElementById('exportFilterPanel').style.display="block";
		return -1;
	}
	if (filterStart&&filterEnd&&(startDate>endDate)) {
		var msg="starting date/time:\n"
		msg+=startDate.toLocaleString()+"\n";
		msg+="is later than ending date/time:\n"
		msg+=endDate.toLocaleString()
		alert(msg);
		return -1;
	}

	// if filter by tags, set up conditional expression
	if (filterTags) {
		var all = store.getTags(); // get list of all tags
		for (var i=0; i<all.length; i++) all[i]=all[i][0]; // remove tag counts
		// convert "tag1 AND ( tag2 OR NOT tag3 )"
		// into javascript expression containing regexp tests:
		// "/\~tag1\~/.test(...) && ( /\~tag2\~/.test(...) || ! /\~tag2\~/.test(...) )"
		var c=tags;
		c = c.replace(/[\[\]]/g,""); // remove [[...]] quoting around tagvalues
		// change AND/OR/NOT/parens to javascript operators and delimit terms with "~"
		c = c.replace(/\sand\s/ig,"~&&~");
		c = c.replace(/\sor\s/ig,"~||~");
		c = c.replace(/(\s)?not([\s\(])/ig,"~!~$2");
		c = c.replace(/([\(\)])/ig,"~$1~");
		// change existing tags to regexp tests and non-existing tags to "false"
		var terms=c.split("~");
		for (var i=0; i<terms.length; i++) { var t=terms[i];
			if (/(&&)|(\|\|)|[!\(\)]/.test(t) || t=="") continue; // skip operators/parens/spaces
			terms[i]=!all.contains(t)?"false":("/\\~"+t+"\\~/.test(tiddlertags)");
		}
		c=terms.join(" ");
	}
	function matchTags(t,c) {
		if (!c||!c.trim().length) return false;
		// assemble tags from tiddler into string "~tag1~tag2~tag3~"
		var tiddlertags = "~"+t.tags.join("~")+"~";
		// eval string against boolean test expression
		try { if(eval(c)) return true; }
		catch(e) { displayMessage(e.toString()); }
		return false;
	}
	
	// scan list and select tiddlers that match all applicable criteria
	var total=0;
	var count=0;
	for (var i=0; i<theList.options.length; i++) {
		// get item, skip non-tiddler list items (section headings)
		var opt=theList.options[i]; if (opt.value=="") continue;
		// get tiddler, skip missing tiddlers (this should NOT happen)
		var tiddler=store.getTiddler(opt.value); if (!tiddler) continue; 
		var sel=true;
		if ( (filterStart && tiddler.modified<startDate)
		|| (filterEnd && tiddler.modified>endDate)
		|| (filterTags && !matchTags(tiddler,c))
		|| (filterText && (tiddler.text.indexOf(text)==-1) && (tiddler.title.indexOf(text)==-1)))
			sel=false;
		opt.selected=sel;
		count+=sel?1:0;
		total++;
	}
	return count;
}
//}}}

// // OUTPUT FORMATTING AND FILE I/O
//{{{
function exportTWHeader()
{
	// get the TiddlyWiki core code source
	var sourcefile=getLocalPath(document.location.href);
	var source=loadFile(sourcefile);
	if(source==null) { alert(config.messages.cantSaveError); return null; }
	// reset existing HTML source markup
	source=updateMarkupBlock(source,"PRE-HEAD");
	source=updateMarkupBlock(source,"POST-HEAD");
	source=updateMarkupBlock(source,"PRE-BODY");
	source=updateMarkupBlock(source,"POST-BODY");
	// find store area
	var posOpeningDiv=source.indexOf(startSaveArea);
	var posClosingDiv=source.lastIndexOf(endSaveArea);
	if((posOpeningDiv==-1)||(posClosingDiv==-1))
		{ alert(config.messages.invalidFileError.format([sourcefile])); return; }
	// return everything up to store area
	return source.substr(0,posOpeningDiv+startSaveArea.length);
}

function exportTWFooter()
{
	// get the TiddlyWiki core code source
	var sourcefile=getLocalPath(document.location.href);
	var source=loadFile(sourcefile);
	if(source==null) { alert(config.messages.cantSaveError); return null; }
	// reset existing HTML source markup
	source=updateMarkupBlock(source,"PRE-HEAD");
	source=updateMarkupBlock(source,"POST-HEAD");
	source=updateMarkupBlock(source,"PRE-BODY");
	source=updateMarkupBlock(source,"POST-BODY");
	// find store area
	var posOpeningDiv=source.indexOf(startSaveArea);
	var posClosingDiv=source.lastIndexOf(endSaveArea);
	if((posOpeningDiv==-1)||(posClosingDiv==-1))
		{ alert(config.messages.invalidFileError.format([sourcefile])); return; }
	// return everything after store area
	return source.substr(posClosingDiv);
}

function exportDIVHeader()
{
	var out=[];
	var now = new Date();
	var title = convertUnicodeToUTF8(wikifyPlain("SiteTitle").htmlEncode());
	var subtitle = convertUnicodeToUTF8(wikifyPlain("SiteSubtitle").htmlEncode());
	var user = convertUnicodeToUTF8(config.options.txtUserName.htmlEncode());
	var twver = version.major+"."+version.minor+"."+version.revision;
	var pver = version.extensions.exportTiddlers.major+"."
		+version.extensions.exportTiddlers.minor+"."+version.extensions.exportTiddlers.revision;
	out.push("<html><body>");
	out.push("<style type=\"text/css\">");
	out.push("#storeArea {display:block;margin:1em;}");
	out.push("#storeArea div");
	out.push("{padding:0.5em;margin:1em;border:2px solid black;height:10em;overflow:auto;}");
	out.push("#javascriptWarning");
	out.push("{width:100%;text-align:left;background-color:#eeeeee;padding:1em;}");
	out.push("</style>");
	out.push("<div id=\"javascriptWarning\">");
	out.push("TiddlyWiki export file<br>");
	out.push("Source"+": <b>"+convertUnicodeToUTF8(document.location.href)+"</b><br>");
	out.push("Title: <b>"+title+"</b><br>");
	out.push("Subtitle: <b>"+subtitle+"</b><br>");
	out.push("Created: <b>"+now.toLocaleString()+"</b> by <b>"+user+"</b><br>");
	out.push("TiddlyWiki "+twver+" / "+"ExportTiddlersPlugin "+pver+"<br>");
	out.push("Notes:<hr><pre>"+document.getElementById("exportNotes").value.replace(/\n/g,"<br>")+"</pre>");
	out.push("</div>");
	out.push("<div id=\"storeArea\">");
	return out;
}

function exportDIVFooter()
{
	return ["</div><!--POST-BODY-START-->\n<!--POST-BODY-END--></body></html>"];
}

function exportXMLHeader()
{
	var out=[];
	var now = new Date();
	var u = store.getTiddlerText("SiteUrl",null);
	var title = convertUnicodeToUTF8(wikifyPlain("SiteTitle").htmlEncode());
	var subtitle = convertUnicodeToUTF8(wikifyPlain("SiteSubtitle").htmlEncode());
	var user = convertUnicodeToUTF8(config.options.txtUserName.htmlEncode());
	var twver = version.major+"."+version.minor+"."+version.revision;
	var pver = version.extensions.exportTiddlers.major+"."
		+version.extensions.exportTiddlers.minor+"."+version.extensions.exportTiddlers.revision;
	out.push("<" + "?xml version=\"1.0\"?" + ">");
	out.push("<rss version=\"2.0\">");
	out.push("<channel>");
	out.push("<title>" + title + "</title>");
	if(u) out.push("<link>" + convertUnicodeToUTF8(u.htmlEncode()) + "</link>");
	out.push("<description>" + subtitle + "</description>");
	out.push("<language>en-us</language>");
	out.push("<copyright>Copyright " + now.getFullYear() + " " + user + "</copyright>");
	out.push("<pubDate>" + now.toGMTString() + "</pubDate>");
	out.push("<lastBuildDate>" + now.toGMTString() + "</lastBuildDate>");
	out.push("<docs>http://blogs.law.harvard.edu/tech/rss</docs>");
	out.push("<generator>TiddlyWiki "+twver+" plus ExportTiddlersPlugin "+pver+"</generator>");
	return out;
}

function exportXMLFooter()
{
	return ["</channel></rss>"];
}

function exportData(target,list,fmt)
{
	function getData(s,f,t) { var r="";
		switch (f) {
			case "TW": r=s.getSaver().externalizeTiddler(s,t); break;
			case "DIV": r=t.title+"\n"+s.getSaver().externalizeTiddler(s,t); break;
			case "XML": r=t.saveToRss(store.getTiddlerText("SiteUrl","")); break;
		}
		return convertUnicodeToUTF8(r);
	}

	var out=[]; var tids=[];
	// get selected tiddlers
	for (var i=0; i<list.options.length; i++) {
		var opt=list.options[i]; if (!opt.selected||!opt.value.length) continue;
		var tid=store.getTiddler(opt.value); if (!tid) continue;
		tids.push(tid.title);
		out.push(getData(store,fmt,tid));
	}
	var count=out.length;
	// merge with existing tiddlers
	var text=loadFile(target);
	if (text && text.length) {
		var msg=target+"\nalready contains tiddler definitions.\n";
		msg+="\nPress OK to add new/revised tiddlers to current file contents.";
		msg+="\nPress Cancel to completely replace file contents";
		var remoteStore=new TiddlyWiki();
		if (remoteStore.importTiddlyWiki(text) && confirm(msg)) {
			var existing=remoteStore.getTiddlers("title");
			for (var i=0; i<existing.length; i++)
				if (!tids.contains(existing[i].title))
					out.push(getData(remoteStore,fmt,existing[i]));
			var msg="Merged %0 new/revised tiddlers and %1 existing tiddlers";
			displayMessage(msg.format([count,out.length-count]));
		}
	}
	return out;
}
//}}}

// // exportTiddlers(): output selected data to local file
//{{{
function exportTiddlers()
{
	clearMessage();
	var list  = document.getElementById("exportList"); if (!list) return;
	var fmt = document.getElementById("exportFormat").value;
	var target = document.getElementById("exportFilename").value.trim();
	if (!target.length) {
		displayMessage("A local target path/filename is required",target);
		return;
	}
	switch (fmt) {
		case "TW":	var head=exportTWHeader(); break;
		case "DIV":	var head=exportDIVHeader(); break;
		case "XML":	var head=exportXMLHeader(); break;
	}
	var theData=exportData(target,list,fmt);
	var c=theData.length;
	switch (fmt) {
		case "TW":	var foot=exportTWFooter(); break;
		case "DIV":	var foot=exportDIVFooter(); break;
		case "XML":	var foot=exportXMLFooter(); break;
	}
	var out=[]; var txt=out.concat(head,theData,foot).join("\n");
	var msg="An error occurred while saving to "+target;
	if (saveFile(target,txt)) msg=c+" tiddler"+((c!=1)?"s":"")+" written to "+target;
	displayMessage(msg,"file:///"+target);
}
//}}}

// // exportDeleteTiddlers(): delete selected tiddlers from file
//{{{
function exportDeleteTiddlers()
{
	var list=document.getElementById("exportList"); if (!list) return;
	var tids=[];
	for (i=0;i<list.length;i++)
		if (list.options[i].selected && list.options[i].value.length)
			tids.push(list.options[i].value);
	if (!confirm("Are you sure you want to delete these tiddlers:\n\n"+tids.join(', '))) return;
	store.suspendNotifications();
	for (t=0;t<tids.length;t++) {
		var tid=store.getTiddler(tids[t]); if (!tid) continue;
		if (tid.tags.contains("systemConfig"))
			if (!confirm("'"+tid.title+"' is tagged with 'systemConfig'.\n\nRemoving this tiddler may cause unexpected results.  Are you sure?"))
				continue;
		store.removeTiddler(tid.title);
		story.closeTiddler(tid.title);
	}
	store.resumeNotifications();
	alert(tids.length+" tiddlers deleted");
	refreshExportList(0); // reload listbox
	store.notifyAll(); // update page display
}
//}}}
/***
|''Name:''|FieldsEditorPlugin|
|''Description:''|//create//, //edit//, //view// and //delete// commands in toolbar <<toolbar fields>>.|
|''Version:''|1.0.2|
|''Date:''|Dec 21,2007|
|''Source:''|http://visualtw.ouvaton.org/VisualTW.html|
|''Author:''|Pascal Collin|
|''License:''|[[BSD open source license|License]]|
|''~CoreVersion:''|2.2.0|
|''Browser:''|Firefox 2.0; InternetExplorer 6.0, others|
!Demo:
On [[homepage|http://visualtw.ouvaton.org/VisualTW.html]], see [[FieldEditor example]]
!Installation:
*import this tiddler from [[homepage|http://visualtw.ouvaton.org/VisualTW.html]] (tagged as systemConfig)
*save and reload
*optionnaly : add the following css text in your StyleSheet : {{{#popup tr.fieldTableRow td {padding:1px 3px 1px 3px;}}}}
!Code
***/

//{{{

config.commands.fields.handlePopup = function(popup,title) {
	var tiddler = store.fetchTiddler(title);
	if(!tiddler)
		return;
	var fields = {};
	store.forEachField(tiddler,function(tiddler,fieldName,value) {fields[fieldName] = value;},true);
	var items = [];
	for(var t in fields) {
		var editCommand = "<<untiddledCall editFieldDialog "+escape(title)+" "+escape(t)+">>";
		var deleteCommand = "<<untiddledCall deleteField "+escape(title)+" "+escape(t)+">>";
		var renameCommand = "<<untiddledCall renameField "+escape(title)+" "+escape(t)+">>";
		items.push({field: t,value: fields[t], actions: editCommand+renameCommand+deleteCommand});
	}
	items.sort(function(a,b) {return a.field < b.field ? -1 : (a.field == b.field ? 0 : +1);});
	var createNewCommand = "<<untiddledCall createField "+escape(title)+">>";
	items.push({field : "", value : "", actions:createNewCommand });
	if(items.length > 0)
		ListView.create(popup,items,this.listViewTemplate);
	else
		createTiddlyElement(popup,"div",null,null,this.emptyText);
}

config.commands.fields.listViewTemplate = {
	columns: [
		{name: 'Field', field: 'field', title: "Field", type: 'String'},
		{name: 'Actions', field: 'actions', title: "Actions", type: 'WikiText'},
		{name: 'Value', field: 'value', title: "Value", type: 'WikiText'}
	],
	rowClasses: [
			{className: 'fieldTableRow', field: 'actions'}
	],
	buttons: [	//can't use button for selected then delete, because click on checkbox will hide the popup
	]
}

config.macros.untiddledCall = {  // when called from listview, tiddler is unset, so we need to pass tiddler as parameter
	handler : function(place,macroName,params,wikifier,paramString) {
		var macroName = params.shift();
		if (macroName) var macro = config.macros[macroName];
		var title = params.shift();
		if (title) var tiddler = store.getTiddler(unescape(title));
		if (macro) macro.handler(place,macroName,params,wikifier,paramString,tiddler);		
	}
}

config.macros.deleteField = {
	handler : function(place,macroName,params,wikifier,paramString,tiddler) {
		if(!readOnly && params[0]) {
			fieldName = unescape(params[0]);
			var btn = createTiddlyButton(place,"delete", "delete "+fieldName,this.onClickDeleteField);
			btn.setAttribute("title",tiddler.title);
			btn.setAttribute("fieldName", fieldName);
		}
	},
	onClickDeleteField : function() {
		var title=this.getAttribute("title");
		var fieldName=this.getAttribute("fieldName");
		var tiddler = store.getTiddler(title);
		if (tiddler && fieldName && confirm("delete field " + fieldName+" from " + title +" tiddler ?")) {
			delete tiddler.fields[fieldName];
			store.saveTiddler(tiddler.title,tiddler.title,tiddler.text,tiddler.modifier,tiddler.modified,tiddler.tags,tiddler.fields);
			story.refreshTiddler(title,"ViewTemplate",true);
		}
		return false;
	}
}

config.macros.createField = {
	handler : function(place,macroName,params,wikifier,paramString,tiddler) {
		if(!readOnly) {
			var btn = createTiddlyButton(place,"create new", "create a new field",this.onClickCreateField);
			btn.setAttribute("title",tiddler.title);
		}
	},
	onClickCreateField : function() {
		var title=this.getAttribute("title");
		var tiddler = store.getTiddler(title);
		if (tiddler) {
			var fieldName = prompt("Field name","");
			if (store.getValue(tiddler,fieldName)) {
				window.alert("This field already exists.");
			}
			else if (fieldName) {
				var v = prompt("Field value","");
				tiddler.fields[fieldName]=v;
				store.saveTiddler(tiddler.title,tiddler.title,tiddler.text,tiddler.modifier,tiddler.modified,tiddler.tags,tiddler.fields);
				story.refreshTiddler(title,"ViewTemplate",true);
			}
		}
		return false;
	}
}

config.macros.editFieldDialog = {
	handler : function(place,macroName,params,wikifier,paramString,tiddler) {
		if(!readOnly && params[0]) {
			fieldName = unescape(params[0]);
			var btn = createTiddlyButton(place,"edit", "edit this field",this.onClickEditFieldDialog);
			btn.setAttribute("title",tiddler.title);
			btn.setAttribute("fieldName", fieldName);
		}
	},
	onClickEditFieldDialog : function() {
		var title=this.getAttribute("title");
		var tiddler = store.getTiddler(title);
		var fieldName=this.getAttribute("fieldName");
		if (tiddler && fieldName) {
			var value = tiddler.fields[fieldName];
			value = value ? value : "";
			var lines = value.match(/\n/mg);
			lines = lines ? true : false;
			if (!lines || confirm("This field contains more than one line. Only the first line will be kept if you edit it here. Proceed ?")) {
				var v = prompt("Field value",value);
				tiddler.fields[fieldName]=v;
				store.saveTiddler(tiddler.title,tiddler.title,tiddler.text,tiddler.modifier,tiddler.modified,tiddler.tags,tiddler.fields);
				story.refreshTiddler(title,"ViewTemplate",true);
			}
		}
		return false;
	}
}

config.macros.renameField = {
	handler : function(place,macroName,params,wikifier,paramString,tiddler) {
		if(!readOnly && params[0]) {
			fieldName = unescape(params[0]);
			var btn = createTiddlyButton(place,"rename", "rename "+fieldName,this.onClickRenameField);
			btn.setAttribute("title",tiddler.title);
			btn.setAttribute("fieldName", fieldName);
		}
	},
	onClickRenameField : function() {
		var title=this.getAttribute("title");
		var fieldName=this.getAttribute("fieldName");
		var tiddler = store.getTiddler(title);
		if (tiddler && fieldName) {
			var newName = prompt("Rename " + fieldName + " as ?", fieldName);
			if (newName) {
				tiddler.fields[newName]=tiddler.fields[fieldName];
				delete tiddler.fields[fieldName];
				store.saveTiddler(tiddler.title,tiddler.title,tiddler.text,tiddler.modifier,tiddler.modified,tiddler.tags,tiddler.fields);
				story.refreshTiddler(title,"ViewTemplate",true);
			}
		}
		return false;
	}
}

config.shadowTiddlers.StyleSheetFieldsEditor = "/*{{{*/\n";
config.shadowTiddlers.StyleSheetFieldsEditor += ".fieldTableRow td {padding : 1px 3px}\n";
config.shadowTiddlers.StyleSheetFieldsEditor += ".fieldTableRow .button {border:0; padding : 0 0.2em}\n";
config.shadowTiddlers.StyleSheetFieldsEditor +="/*}}}*/";
store.addNotification("StyleSheetFieldsEditor", refreshStyles);

//}}}
/***
|''Name:''|ForEachTiddlerPlugin|
|''Version:''|1.0.8 (2007-04-12)|
|''Source:''|http://tiddlywiki.abego-software.de/#ForEachTiddlerPlugin|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]|
|''Copyright:''|&copy; 2005-2007 [[abego Software|http://www.abego-software.de]]|
|''TiddlyWiki:''|1.2.38+, 2.0|
|''Browser:''|Firefox 1.0.4+; Firefox 1.5; InternetExplorer 6.0|
!Description

Create customizable lists, tables etc. for your selections of tiddlers. Specify the tiddlers to include and their order through a powerful language.

''Syntax:'' 
|>|{{{<<}}}''forEachTiddler'' [''in'' //tiddlyWikiPath//] [''where'' //whereCondition//] [''sortBy'' //sortExpression// [''ascending'' //or// ''descending'']] [''script'' //scriptText//] [//action// [//actionParameters//]]{{{>>}}}|
|//tiddlyWikiPath//|The filepath to the TiddlyWiki the macro should work on. When missing the current TiddlyWiki is used.|
|//whereCondition//|(quoted) JavaScript boolean expression. May refer to the build-in variables {{{tiddler}}} and  {{{context}}}.|
|//sortExpression//|(quoted) JavaScript expression returning "comparable" objects (using '{{{<}}}','{{{>}}}','{{{==}}}'. May refer to the build-in variables {{{tiddler}}} and  {{{context}}}.|
|//scriptText//|(quoted) JavaScript text. Typically defines JavaScript functions that are called by the various JavaScript expressions (whereClause, sortClause, action arguments,...)|
|//action//|The action that should be performed on every selected tiddler, in the given order. By default the actions [[addToList|AddToListAction]] and [[write|WriteAction]] are supported. When no action is specified [[addToList|AddToListAction]]  is used.|
|//actionParameters//|(action specific) parameters the action may refer while processing the tiddlers (see action descriptions for details). <<tiddler [[JavaScript in actionParameters]]>>|
|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|

See details see [[ForEachTiddlerMacro]] and [[ForEachTiddlerExamples]].

!Code
***/
//{{{

	
//============================================================================
//============================================================================
//		   ForEachTiddlerPlugin
//============================================================================
//============================================================================

// Only install once
if (!version.extensions.ForEachTiddlerPlugin) {

if (!window.abego) window.abego = {};

version.extensions.ForEachTiddlerPlugin = {
	major: 1, minor: 0, revision: 8, 
	date: new Date(2007,3,12), 
	source: "http://tiddlywiki.abego-software.de/#ForEachTiddlerPlugin",
	licence: "[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]",
	copyright: "Copyright (c) abego Software GmbH, 2005-2007 (www.abego-software.de)"
};

// For backward compatibility with TW 1.2.x
//
if (!TiddlyWiki.prototype.forEachTiddler) {
	TiddlyWiki.prototype.forEachTiddler = function(callback) {
		for(var t in this.tiddlers) {
			callback.call(this,t,this.tiddlers[t]);
		}
	};
}

//============================================================================
// forEachTiddler Macro
//============================================================================

version.extensions.forEachTiddler = {
	major: 1, minor: 0, revision: 8, date: new Date(2007,3,12), provider: "http://tiddlywiki.abego-software.de"};

// ---------------------------------------------------------------------------
// Configurations and constants 
// ---------------------------------------------------------------------------

config.macros.forEachTiddler = {
	 // Standard Properties
	 label: "forEachTiddler",
	 prompt: "Perform actions on a (sorted) selection of tiddlers",

	 // actions
	 actions: {
		 addToList: {},
		 write: {}
	 }
};

// ---------------------------------------------------------------------------
//  The forEachTiddler Macro Handler 
// ---------------------------------------------------------------------------

config.macros.forEachTiddler.getContainingTiddler = function(e) {
	while(e && !hasClass(e,"tiddler"))
		e = e.parentNode;
	var title = e ? e.getAttribute("tiddler") : null; 
	return title ? store.getTiddler(title) : null;
};

config.macros.forEachTiddler.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
	// config.macros.forEachTiddler.traceMacroCall(place,macroName,params,wikifier,paramString,tiddler);

	if (!tiddler) tiddler = config.macros.forEachTiddler.getContainingTiddler(place);
	// --- Parsing ------------------------------------------

	var i = 0; // index running over the params
	// Parse the "in" clause
	var tiddlyWikiPath = undefined;
	if ((i < params.length) && params[i] == "in") {
		i++;
		if (i >= params.length) {
			this.handleError(place, "TiddlyWiki path expected behind 'in'.");
			return;
		}
		tiddlyWikiPath = this.paramEncode((i < params.length) ? params[i] : "");
		i++;
	}

	// Parse the where clause
	var whereClause ="true";
	if ((i < params.length) && params[i] == "where") {
		i++;
		whereClause = this.paramEncode((i < params.length) ? params[i] : "");
		i++;
	}

	// Parse the sort stuff
	var sortClause = null;
	var sortAscending = true; 
	if ((i < params.length) && params[i] == "sortBy") {
		i++;
		if (i >= params.length) {
			this.handleError(place, "sortClause missing behind 'sortBy'.");
			return;
		}
		sortClause = this.paramEncode(params[i]);
		i++;

		if ((i < params.length) && (params[i] == "ascending" || params[i] == "descending")) {
			 sortAscending = params[i] == "ascending";
			 i++;
		}
	}

	// Parse the script
	var scriptText = null;
	if ((i < params.length) && params[i] == "script") {
		i++;
		scriptText = this.paramEncode((i < params.length) ? params[i] : "");
		i++;
	}

	// Parse the action. 
	// When we are already at the end use the default action
	var actionName = "addToList";
	if (i < params.length) {
	   if (!config.macros.forEachTiddler.actions[params[i]]) {
			this.handleError(place, "Unknown action '"+params[i]+"'.");
			return;
		} else {
			actionName = params[i]; 
			i++;
		}
	} 
	
	// Get the action parameter
	// (the parsing is done inside the individual action implementation.)
	var actionParameter = params.slice(i);


	// --- Processing ------------------------------------------
	try {
		this.performMacro({
				place: place, 
				inTiddler: tiddler,
				whereClause: whereClause, 
				sortClause: sortClause, 
				sortAscending: sortAscending, 
				actionName: actionName, 
				actionParameter: actionParameter, 
				scriptText: scriptText, 
				tiddlyWikiPath: tiddlyWikiPath});

	} catch (e) {
		this.handleError(place, e);
	}
};

// Returns an object with properties "tiddlers" and "context".
// tiddlers holds the (sorted) tiddlers selected by the parameter,
// context the context of the execution of the macro.
//
// The action is not yet performed.
//
// @parameter see performMacro
//
config.macros.forEachTiddler.getTiddlersAndContext = function(parameter) {

	var context = config.macros.forEachTiddler.createContext(parameter.place, parameter.whereClause, parameter.sortClause, parameter.sortAscending, parameter.actionName, parameter.actionParameter, parameter.scriptText, parameter.tiddlyWikiPath, parameter.inTiddler);

	var tiddlyWiki = parameter.tiddlyWikiPath ? this.loadTiddlyWiki(parameter.tiddlyWikiPath) : store;
	context["tiddlyWiki"] = tiddlyWiki;
	
	// Get the tiddlers, as defined by the whereClause
	var tiddlers = this.findTiddlers(parameter.whereClause, context, tiddlyWiki);
	context["tiddlers"] = tiddlers;

	// Sort the tiddlers, when sorting is required.
	if (parameter.sortClause) {
		this.sortTiddlers(tiddlers, parameter.sortClause, parameter.sortAscending, context);
	}

	return {tiddlers: tiddlers, context: context};
};

// Returns the (sorted) tiddlers selected by the parameter.
//
// The action is not yet performed.
//
// @parameter see performMacro
//
config.macros.forEachTiddler.getTiddlers = function(parameter) {
	return this.getTiddlersAndContext(parameter).tiddlers;
};

// Performs the macros with the given parameter.
//
// @param parameter holds the parameter of the macro as separate properties.
//				  The following properties are supported:
//
//						place
//						whereClause
//						sortClause
//						sortAscending
//						actionName
//						actionParameter
//						scriptText
//						tiddlyWikiPath
//
//					All properties are optional. 
//					For most actions the place property must be defined.
//
config.macros.forEachTiddler.performMacro = function(parameter) {
	var tiddlersAndContext = this.getTiddlersAndContext(parameter);

	// Perform the action
	var actionName = parameter.actionName ? parameter.actionName : "addToList";
	var action = config.macros.forEachTiddler.actions[actionName];
	if (!action) {
		this.handleError(parameter.place, "Unknown action '"+actionName+"'.");
		return;
	}

	var actionHandler = action.handler;
	actionHandler(parameter.place, tiddlersAndContext.tiddlers, parameter.actionParameter, tiddlersAndContext.context);
};

// ---------------------------------------------------------------------------
//  The actions 
// ---------------------------------------------------------------------------

// Internal.
//
// --- The addToList Action -----------------------------------------------
//
config.macros.forEachTiddler.actions.addToList.handler = function(place, tiddlers, parameter, context) {
	// Parse the parameter
	var p = 0;

	// Check for extra parameters
	if (parameter.length > p) {
		config.macros.forEachTiddler.createExtraParameterErrorElement(place, "addToList", parameter, p);
		return;
	}

	// Perform the action.
	var list = document.createElement("ul");
	place.appendChild(list);
	for (var i = 0; i < tiddlers.length; i++) {
		var tiddler = tiddlers[i];
		var listItem = document.createElement("li");
		list.appendChild(listItem);
		createTiddlyLink(listItem, tiddler.title, true);
	}
};

abego.parseNamedParameter = function(name, parameter, i) {
	var beginExpression = null;
	if ((i < parameter.length) && parameter[i] == name) {
		i++;
		if (i >= parameter.length) {
			throw "Missing text behind '%0'".format([name]);
		}
		
		return config.macros.forEachTiddler.paramEncode(parameter[i]);
	}
	return null;
}

// Internal.
//
// --- The write Action ---------------------------------------------------
//
config.macros.forEachTiddler.actions.write.handler = function(place, tiddlers, parameter, context) {
	// Parse the parameter
	var p = 0;
	if (p >= parameter.length) {
		this.handleError(place, "Missing expression behind 'write'.");
		return;
	}

	var textExpression = config.macros.forEachTiddler.paramEncode(parameter[p]);
	p++;

	// Parse the "begin" option
	var beginExpression = abego.parseNamedParameter("begin", parameter, p);
	if (beginExpression !== null) 
		p += 2;
	var endExpression = abego.parseNamedParameter("end", parameter, p);
	if (endExpression !== null) 
		p += 2;
	var noneExpression = abego.parseNamedParameter("none", parameter, p);
	if (noneExpression !== null) 
		p += 2;

	// Parse the "toFile" option
	var filename = null;
	var lineSeparator = undefined;
	if ((p < parameter.length) && parameter[p] == "toFile") {
		p++;
		if (p >= parameter.length) {
			this.handleError(place, "Filename expected behind 'toFile' of 'write' action.");
			return;
		}
		
		filename = config.macros.forEachTiddler.getLocalPath(config.macros.forEachTiddler.paramEncode(parameter[p]));
		p++;
		if ((p < parameter.length) && parameter[p] == "withLineSeparator") {
			p++;
			if (p >= parameter.length) {
				this.handleError(place, "Line separator text expected behind 'withLineSeparator' of 'write' action.");
				return;
			}
			lineSeparator = config.macros.forEachTiddler.paramEncode(parameter[p]);
			p++;
		}
	}
	
	// Check for extra parameters
	if (parameter.length > p) {
		config.macros.forEachTiddler.createExtraParameterErrorElement(place, "write", parameter, p);
		return;
	}

	// Perform the action.
	var func = config.macros.forEachTiddler.getEvalTiddlerFunction(textExpression, context);
	var count = tiddlers.length;
	var text = "";
	if (count > 0 && beginExpression)
		text += config.macros.forEachTiddler.getEvalTiddlerFunction(beginExpression, context)(undefined, context, count, undefined);
	
	for (var i = 0; i < count; i++) {
		var tiddler = tiddlers[i];
		text += func(tiddler, context, count, i);
	}
	
	if (count > 0 && endExpression)
		text += config.macros.forEachTiddler.getEvalTiddlerFunction(endExpression, context)(undefined, context, count, undefined);

	if (count == 0 && noneExpression) 
		text += config.macros.forEachTiddler.getEvalTiddlerFunction(noneExpression, context)(undefined, context, count, undefined);
		

	if (filename) {
		if (lineSeparator !== undefined) {
			lineSeparator = lineSeparator.replace(/\\n/mg, "\n").replace(/\\r/mg, "\r");
			text = text.replace(/\n/mg,lineSeparator);
		}
		saveFile(filename, convertUnicodeToUTF8(text));
	} else {
		var wrapper = createTiddlyElement(place, "span");
		wikify(text, wrapper, null/* highlightRegExp */, context.inTiddler);
	}
};


// ---------------------------------------------------------------------------
//  Helpers
// ---------------------------------------------------------------------------

// Internal.
//
config.macros.forEachTiddler.createContext = function(placeParam, whereClauseParam, sortClauseParam, sortAscendingParam, actionNameParam, actionParameterParam, scriptText, tiddlyWikiPathParam, inTiddlerParam) {
	return {
		place : placeParam, 
		whereClause : whereClauseParam, 
		sortClause : sortClauseParam, 
		sortAscending : sortAscendingParam, 
		script : scriptText,
		actionName : actionNameParam, 
		actionParameter : actionParameterParam,
		tiddlyWikiPath : tiddlyWikiPathParam,
		inTiddler : inTiddlerParam, // the tiddler containing the <<forEachTiddler ...>> macro call.
		viewerTiddler : config.macros.forEachTiddler.getContainingTiddler(placeParam) // the tiddler showing the forEachTiddler result
	};
};

// Internal.
//
// Returns a TiddlyWiki with the tiddlers loaded from the TiddlyWiki of 
// the given path.
//
config.macros.forEachTiddler.loadTiddlyWiki = function(path, idPrefix) {
	if (!idPrefix) {
		idPrefix = "store";
	}
	var lenPrefix = idPrefix.length;
	
	// Read the content of the given file
	var content = loadFile(this.getLocalPath(path));
	if(content === null) {
		throw "TiddlyWiki '"+path+"' not found.";
	}
	
	var tiddlyWiki = new TiddlyWiki();

	// Starting with TW 2.2 there is a helper function to import the tiddlers
	if (tiddlyWiki.importTiddlyWiki) {
		if (!tiddlyWiki.importTiddlyWiki(content))
			throw "File '"+path+"' is not a TiddlyWiki.";
		tiddlyWiki.dirty = false;
		return tiddlyWiki;
	}
	
	// The legacy code, for TW < 2.2
	
	// Locate the storeArea div's
	var posOpeningDiv = content.indexOf(startSaveArea);
	var posClosingDiv = content.lastIndexOf(endSaveArea);
	if((posOpeningDiv == -1) || (posClosingDiv == -1)) {
		throw "File '"+path+"' is not a TiddlyWiki.";
	}
	var storageText = content.substr(posOpeningDiv + startSaveArea.length, posClosingDiv);
	
	// Create a "div" element that contains the storage text
	var myStorageDiv = document.createElement("div");
	myStorageDiv.innerHTML = storageText;
	myStorageDiv.normalize();
	
	// Create all tiddlers in a new TiddlyWiki
	// (following code is modified copy of TiddlyWiki.prototype.loadFromDiv)
	var store = myStorageDiv.childNodes;
	for(var t = 0; t < store.length; t++) {
		var e = store[t];
		var title = null;
		if(e.getAttribute)
			title = e.getAttribute("tiddler");
		if(!title && e.id && e.id.substr(0,lenPrefix) == idPrefix)
			title = e.id.substr(lenPrefix);
		if(title && title !== "") {
			var tiddler = tiddlyWiki.createTiddler(title);
			tiddler.loadFromDiv(e,title);
		}
	}
	tiddlyWiki.dirty = false;

	return tiddlyWiki;
};


	
// Internal.
//
// Returns a function that has a function body returning the given javaScriptExpression.
// The function has the parameters:
// 
//	 (tiddler, context, count, index)
//
config.macros.forEachTiddler.getEvalTiddlerFunction = function (javaScriptExpression, context) {
	var script = context["script"];
	var functionText = "var theFunction = function(tiddler, context, count, index) { return "+javaScriptExpression+"}";
	var fullText = (script ? script+";" : "")+functionText+";theFunction;";
	return eval(fullText);
};

// Internal.
//
config.macros.forEachTiddler.findTiddlers = function(whereClause, context, tiddlyWiki) {
	var result = [];
	var func = config.macros.forEachTiddler.getEvalTiddlerFunction(whereClause, context);
	tiddlyWiki.forEachTiddler(function(title,tiddler) {
		if (func(tiddler, context, undefined, undefined)) {
			result.push(tiddler);
		}
	});
	return result;
};

// Internal.
//
config.macros.forEachTiddler.createExtraParameterErrorElement = function(place, actionName, parameter, firstUnusedIndex) {
	var message = "Extra parameter behind '"+actionName+"':";
	for (var i = firstUnusedIndex; i < parameter.length; i++) {
		message += " "+parameter[i];
	}
	this.handleError(place, message);
};

// Internal.
//
config.macros.forEachTiddler.sortAscending = function(tiddlerA, tiddlerB) {
	var result = 
		(tiddlerA.forEachTiddlerSortValue == tiddlerB.forEachTiddlerSortValue) 
			? 0
			: (tiddlerA.forEachTiddlerSortValue < tiddlerB.forEachTiddlerSortValue)
			   ? -1 
			   : +1; 
	return result;
};

// Internal.
//
config.macros.forEachTiddler.sortDescending = function(tiddlerA, tiddlerB) {
	var result = 
		(tiddlerA.forEachTiddlerSortValue == tiddlerB.forEachTiddlerSortValue) 
			? 0
			: (tiddlerA.forEachTiddlerSortValue < tiddlerB.forEachTiddlerSortValue)
			   ? +1 
			   : -1; 
	return result;
};

// Internal.
//
config.macros.forEachTiddler.sortTiddlers = function(tiddlers, sortClause, ascending, context) {
	// To avoid evaluating the sortClause whenever two items are compared 
	// we pre-calculate the sortValue for every item in the array and store it in a 
	// temporary property ("forEachTiddlerSortValue") of the tiddlers.
	var func = config.macros.forEachTiddler.getEvalTiddlerFunction(sortClause, context);
	var count = tiddlers.length;
	var i;
	for (i = 0; i < count; i++) {
		var tiddler = tiddlers[i];
		tiddler.forEachTiddlerSortValue = func(tiddler,context, undefined, undefined);
	}

	// Do the sorting
	tiddlers.sort(ascending ? this.sortAscending : this.sortDescending);

	// Delete the temporary property that holds the sortValue.	
	for (i = 0; i < tiddlers.length; i++) {
		delete tiddlers[i].forEachTiddlerSortValue;
	}
};


// Internal.
//
config.macros.forEachTiddler.trace = function(message) {
	displayMessage(message);
};

// Internal.
//
config.macros.forEachTiddler.traceMacroCall = function(place,macroName,params) {
	var message ="<<"+macroName;
	for (var i = 0; i < params.length; i++) {
		message += " "+params[i];
	}
	message += ">>";
	displayMessage(message);
};


// Internal.
//
// Creates an element that holds an error message
// 
config.macros.forEachTiddler.createErrorElement = function(place, exception) {
	var message = (exception.description) ? exception.description : exception.toString();
	return createTiddlyElement(place,"span",null,"forEachTiddlerError","<<forEachTiddler ...>>: "+message);
};

// Internal.
//
// @param place [may be null]
//
config.macros.forEachTiddler.handleError = function(place, exception) {
	if (place) {
		this.createErrorElement(place, exception);
	} else {
		throw exception;
	}
};

// Internal.
//
// Encodes the given string.
//
// Replaces 
//	 "$))" to ">>"
//	 "$)" to ">"
//
config.macros.forEachTiddler.paramEncode = function(s) {
	var reGTGT = new RegExp("\\$\\)\\)","mg");
	var reGT = new RegExp("\\$\\)","mg");
	return s.replace(reGTGT, ">>").replace(reGT, ">");
};

// Internal.
//
// Returns the given original path (that is a file path, starting with "file:")
// as a path to a local file, in the systems native file format.
//
// Location information in the originalPath (i.e. the "#" and stuff following)
// is stripped.
// 
config.macros.forEachTiddler.getLocalPath = function(originalPath) {
	// Remove any location part of the URL
	var hashPos = originalPath.indexOf("#");
	if(hashPos != -1)
		originalPath = originalPath.substr(0,hashPos);
	// Convert to a native file format assuming
	// "file:///x:/path/path/path..." - pc local file --> "x:\path\path\path..."
	// "file://///server/share/path/path/path..." - FireFox pc network file --> "\\server\share\path\path\path..."
	// "file:///path/path/path..." - mac/unix local file --> "/path/path/path..."
	// "file://server/share/path/path/path..." - pc network file --> "\\server\share\path\path\path..."
	var localPath;
	if(originalPath.charAt(9) == ":") // pc local file
		localPath = unescape(originalPath.substr(8)).replace(new RegExp("/","g"),"\\");
	else if(originalPath.indexOf("file://///") === 0) // FireFox pc network file
		localPath = "\\\\" + unescape(originalPath.substr(10)).replace(new RegExp("/","g"),"\\");
	else if(originalPath.indexOf("file:///") === 0) // mac/unix local file
		localPath = unescape(originalPath.substr(7));
	else if(originalPath.indexOf("file:/") === 0) // mac/unix local file
		localPath = unescape(originalPath.substr(5));
	else // pc network file
		localPath = "\\\\" + unescape(originalPath.substr(7)).replace(new RegExp("/","g"),"\\");	
	return localPath;
};

// ---------------------------------------------------------------------------
// Stylesheet Extensions (may be overridden by local StyleSheet)
// ---------------------------------------------------------------------------
//
setStylesheet(
	".forEachTiddlerError{color: #ffffff;background-color: #880000;}",
	"forEachTiddler");

//============================================================================
// End of forEachTiddler Macro
//============================================================================


//============================================================================
// String.startsWith Function
//============================================================================
//
// Returns true if the string starts with the given prefix, false otherwise.
//
version.extensions["String.startsWith"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
String.prototype.startsWith = function(prefix) {
	var n =  prefix.length;
	return (this.length >= n) && (this.slice(0, n) == prefix);
};



//============================================================================
// String.endsWith Function
//============================================================================
//
// Returns true if the string ends with the given suffix, false otherwise.
//
version.extensions["String.endsWith"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
String.prototype.endsWith = function(suffix) {
	var n = suffix.length;
	return (this.length >= n) && (this.right(n) == suffix);
};


//============================================================================
// String.contains Function
//============================================================================
//
// Returns true when the string contains the given substring, false otherwise.
//
version.extensions["String.contains"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
String.prototype.contains = function(substring) {
	return this.indexOf(substring) >= 0;
};

//============================================================================
// Array.indexOf Function
//============================================================================
//
// Returns the index of the first occurance of the given item in the array or 
// -1 when no such item exists.
//
// @param item [may be null]
//
version.extensions["Array.indexOf"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.indexOf = function(item) {
	for (var i = 0; i < this.length; i++) {
		if (this[i] == item) {
			return i;
		}
	}
	return -1;
};

//============================================================================
// Array.contains Function
//============================================================================
//
// Returns true when the array contains the given item, otherwise false. 
//
// @param item [may be null]
//
version.extensions["Array.contains"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.contains = function(item) {
	return (this.indexOf(item) >= 0);
};

//============================================================================
// Array.containsAny Function
//============================================================================
//
// Returns true when the array contains at least one of the elements 
// of the item. Otherwise (or when items contains no elements) false is returned.
//
version.extensions["Array.containsAny"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.containsAny = function(items) {
	for(var i = 0; i < items.length; i++) {
		if (this.contains(items[i])) {
			return true;
		}
	}
	return false;
};


//============================================================================
// Array.containsAll Function
//============================================================================
//
// Returns true when the array contains all the items, otherwise false.
// 
// When items is null false is returned (even if the array contains a null).
//
// @param items [may be null] 
//
version.extensions["Array.containsAll"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.containsAll = function(items) {
	for(var i = 0; i < items.length; i++) {
		if (!this.contains(items[i])) {
			return false;
		}
	}
	return true;
};


} // of "install only once"

// Used Globals (for JSLint) ==============
// ... DOM
/*global 	document */
// ... TiddlyWiki Core
/*global 	convertUnicodeToUTF8, createTiddlyElement, createTiddlyLink, 
			displayMessage, endSaveArea, hasClass, loadFile, saveFile, 
			startSaveArea, store, wikify */
//}}}


/***
!Licence and Copyright
Copyright (c) abego Software ~GmbH, 2005 ([[www.abego-software.de|http://www.abego-software.de]])

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.

Neither the name of abego Software nor the names of its contributors may be
used to endorse or promote products derived from this software without specific
prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
***/
<!--{{{-->
<div class='toolbar' macro='toolbar +saveTiddler  -cancelTiddler deleteTiddler'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='easyEdit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>
<!--}}}-->
/***
|Name|HTMLFormattingPlugin|
|Source|http://www.TiddlyTools.com/#HTMLFormattingPlugin|
|Documentation|http://www.TiddlyTools.com/#HTMLFormattingPluginInfo|
|Version|2.1.5|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|'HTML' formatter|
|Description|embed wiki syntax formatting inside of HTML content|
The shorthand Wiki-style formatting syntax of ~TiddlyWiki is very convenient and enables most content to be reasonably well presented. However, there are times when tried-and-true HTML formatting syntax allows more more precise control of the content display.  When HTML formatting syntax is embedded within a tiddler (in between {{{<}}}{{{html>}}} and {{{<}}}{{{/html>}}} markers) TiddlyWiki passes this content to the browser for processing as 'native' HTML.  However, TiddlyWiki does not also process the HTML source content for any embedded wiki-formatting syntax it may contain.  This means that while you can use HTML formatted content, you cannot mix wiki-formatted content within the HTML formatting.

The ~HTMLFormatting plugin allows you to freely ''mix wiki-style formatting syntax within HTML formatted content'' by extending the action of the standard TiddlyWiki formatting handler.
!!!!!Documentation
>see [[HTMLFormattingPluginInfo]]
!!!!!Revisions
<<<
2008.01.08 [*.*.*] plugin size reduction: documentation moved to HTMLFormattingInfo
2007.12.04 [*.*.*] update for TW2.3.0: replaced deprecated core functions, regexps, and macros
2007.06.14 [2.1.5] in formatter, removed call to e.normalize().  Creates an INFINITE RECURSION error in Safari!!!!
2006.09.10 [2.1.4] update formatter for 2.1 compatibility (use this.lookaheadRegExp instead of temp variable)
2006.05.28 [2.1.3] in wikifyTextNodes(), decode the *value* of TEXTAREA nodes, but don't wikify() its children.  (thanks to "ayj" for bug report)
2006.02.19 [2.1.2] in wikifyTextNodes(), put SPAN element into tiddler DOM (replacing text node), BEFORE wikifying the text content.  This ensures that the 'place' passed to any macros is correctly defined when the macro is evaluated, so that calls to story.findContainingTiddler(place) will work as expected. (Thanks for bug report from GeoffSlocock)
2006.02.05 [2.1.1] wrapped wikifier hijack in init function to eliminate globals and avoid FireFox 1.5.0.1 crash bug when referencing globals
2005.12.01 [2.1.0] don't wikify #TEXT nodes inside SELECT and TEXTAREA elements
2005.11.06 [2.0.1] code cleanup
2005.10.31 [2.0.0] replaced hijack wikify() with hijack config.formatters["html"] and simplified recursive WikifyTextNodes() code
2005.10.09 [1.0.2] combined documentation and code into a single tiddler
2005.08.05 [1.0.1] moved HTML and CSS definitions into plugin code instead of using separate tiddlers
2005.07.26 [1.0.1] Re-released as a plugin. Added <{{{html}}}>...</{{{nohtml}}}> and <{{{hide newlines}}}> handling
2005.06.26 [1.0.0] Initial Release (as code adaptation - pre-dates TiddlyWiki plugin architecture!!)
<<<
!!!!!Code
***/
//{{{
version.extensions.HTMLFormatting = {major: 2, minor: 1, revision: 5, date: new Date(2007,6,14)};

// find the formatter for HTML and replace the handler
initHTMLFormatter();
function initHTMLFormatter()
{
	for (var i=0; i<config.formatters.length && config.formatters[i].name!="html"; i++);
	if (i<config.formatters.length)	config.formatters[i].handler=function(w) {
		if (!this.lookaheadRegExp)  // fixup for TW2.0.x
			this.lookaheadRegExp = new RegExp(this.lookahead,"mg");
		this.lookaheadRegExp.lastIndex = w.matchStart;
		var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
			var html=lookaheadMatch[1];
			// optionally suppress wiki-style literal handling of newlines
			// strip any carriage returns added by Internet Explorer's textarea edit field
			// encode newlines as \n so Internet Explorer's HTML parser won't eat them
			// encode macro brackets (<< and >>) so HTML parser won't eat them
			if (html.indexOf('<hide linebreaks>')!=-1) html=html.replace(/\n/g,' ');
			html=html.replace(/\r/g,'');
			html=html.replace(/\n/g,'\\n');
			html=html.replace(/<</g,'%%(').replace(/>>/g,')%%');
			// create span to hold HTML
			// parse HTML and normalize the results
			// walk node tree and call wikify() on each text node
			var e = createTiddlyElement(w.output,"span");
			e.innerHTML=html;
			// REMOVED: e.normalize();  // THIS CAUSED INFINITE RECURSION IN SAFARI
			wikifyTextNodes(e);
			// advance to next parse position
			w.nextMatch = this.lookaheadRegExp.lastIndex;
		}
	}
}

// wikify text nodes remaining after HTML content is processed (pre-order recursion)
function wikifyTextNodes(theNode)
{
	// textarea node doesn't get wikified, just decoded... 
	if (theNode.nodeName.toLowerCase()=='textarea')
		theNode.value=theNode.value.replace(/\%%\(/g,'<<').replace(/\)\%%/g,'>>').replace(/\\n/g,'\n');
	else for (var i=0;i<theNode.childNodes.length;i++) {
		var theChild=theNode.childNodes.item(i);
		if (theChild.nodeName.toLowerCase()=='option') continue;
		if (theChild.nodeName.toLowerCase()=='select') continue;
		wikifyTextNodes(theChild);
		if (theChild.nodeName=='#text') {
			var txt=theChild.nodeValue;
			// decode macro brackets and newlines
			txt=txt.replace(/\%%\(/g,'<<').replace(/\)\%%/g,'>>').replace(/\\n/g,'\n');
			// replace text node with wikified() span
			var newNode=createTiddlyElement(null,"span");
			theNode.replaceChild(newNode,theChild);
			wikify(txt,newNode);
		}
	}
}
//}}}
<!--{{{-->
<div class='toolbar' macro='toolbar closeTiddler closeOthers +easyEdit > fields syncing permalink references jump'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>

<!--
<div class='tagging' macro='tagging'></div>
-->
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->

''查詢 大福.tw 網域的 DNS 資訊''
{{{
$ dig xn--pss076e.tw

; <<>> DiG 9.7.1-P2 <<>> xn--pss076e.tw
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 16082
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 0

;; QUESTION SECTION:
;xn--pss076e.tw.			IN	A

;; ANSWER SECTION:
xn--pss076e.tw.		604800	IN	A	140.137.214.45

;; AUTHORITY SECTION:
xn--pss076e.tw.		604800	IN	NS	KVMFS.xn--pss076e.tw.

;; Query time: 8 msec
;; SERVER: 168.95.1.1#53(168.95.1.1)
;; WHEN: Fri Nov 25 18:01:39 2011
;; MSG SIZE  rcvd: 68


$ nslookup
> set type=any
> xn--pss076e.tw.
Server:		168.95.1.1
Address:	168.95.1.1#53

Non-authoritative answer:
Name:	xn--pss076e.tw
Address: 140.137.214.45
xn--pss076e.tw
	origin = KVMFS.xn--pss076e.tw
	mail addr = admin.gmail.com.xn--pss076e.tw
	serial = 1
	refresh = 604800
	retry = 86400
	expire = 2419200
	minimum = 604800
xn--pss076e.tw	nameserver = KVMFS.xn--pss076e.tw.

Authoritative answers can be found from:
xn--pss076e.tw	nameserver = KVMFS.xn--pss076e.tw.

}}}


/***
|Name|ImportTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#ImportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ImportTiddlersPluginInfo|
|Version|4.3.3|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|config.macros.importTiddlers.handler|
|Description|interactive controls for import/export with filtering.|
This plugin lets you selectively combine tiddlers from any two TiddlyWiki documents.  An interactive control panel lets you pick a document to import from, and then select which tiddlers to import, with prompting for skip, rename, merge or replace actions when importing tiddlers that match existing titles.  Automatically add tags to imported tiddlers so they are easy to find later on.  Generates a detailed report of import 'history' in ImportedTiddlers.
***/
// // ''MACRO DEFINITION''
//{{{
// Version
version.extensions.importTiddlers = {major: 4, minor: 3, revision: 3, date: new Date(2008,8,12)};

// add ImportTiddlerPlugin controls to built-in backstage import task
if (config.tasks) { // TW2.2 or above
	config.tasks.importTask.content="<<tiddler ImportTiddlers>>"
}

// IE needs explicit global scoping for functions/vars called from browser events
window.onClickImportButton=onClickImportButton;
window.refreshImportList=refreshImportList;

// default cookie/option values
if (!config.options.chkImportReport) config.options.chkImportReport=true;

// default shadow definition
config.shadowTiddlers.ImportTiddlers="Use ~TiddlyWiki built-in importer (below) or, ";
config.shadowTiddlers.ImportTiddlers+="<<importTiddlers link 'Use ImportTiddlersPlugin control panel...'>>\n";
config.shadowTiddlers.ImportTiddlers+="<<importTiddlers core>>";

merge(config.macros.importTiddlers,{
	label: "import tiddlers",
	prompt: "Copy tiddlers from another document",
	openMsg: "Opening %0",
	openErrMsg: "Could not open %0 - error=%1",
	readMsg: "Read %0 bytes from %1",
	foundMsg: "Found %0 tiddlers in %1",
	filterMsg: "Filtered %0 tiddlers matching '%1'",
	summaryMsg: "%0 tiddler%1 in the list",
	summaryFilteredMsg: "%0 of %1 tiddler%2 in the list",
	plural: "s are",
	single: " is",
	countMsg: "%0 tiddlers selected for import",
	processedMsg: "Processed %0 tiddlers",
	importedMsg: "Imported %0 of %1 tiddlers from %2",
	loadText: "please load a document...",
	closeText: "close",	// text for close button when file is loaded
	doneText: "done",	// text for close button when file is not loaded
	startText: "import",	// text for import button
	stopText: "stop",	// text for import button while importing
	local: true,		// default to import from local file
	src: "",		// path/filename or URL of document to import (retrieved from SiteUrl tiddler)
	proxy: "",		// URL for remote proxy script (retrieved from SiteProxy tiddler)
	useProxy: false,	// use specific proxy script in front of remote URL
	inbound: null,		// hash-indexed array of tiddlers from other document
	newTags: "",		// text of tags added to imported tiddlers
	addTags: true,		// add new tags to imported tiddlers
	listsize: 10,		// # of lines to show in imported tiddler list
	importTags: true,	// include tags from remote source document when importing a tiddler
	keepTags: true,		// retain existing tags when replacing a tiddler
	sync: false,		// add 'server' fields to imported tiddlers (for sync function)
	lastFilter: "",		// most recent filter (URL hash) applied
	lastAction: null,	// most recent collision button performed
	index: 0,		// current processing index in import list
	sort: ""		// sort order for imported tiddler listbox
});

if (config.macros.importTiddlers.coreHandler==undefined)
	config.macros.importTiddlers.coreHandler=config.macros.importTiddlers.handler; // save built-in handler
config.macros.importTiddlers.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
	if (!params[0] || params[0].toLowerCase()=='core') { // default to built in
		if (config.macros.importTiddlers.coreHandler)
			config.macros.importTiddlers.coreHandler.apply(this,arguments);
		else 
			createTiddlyButton(place,this.label,this.prompt,onClickImportMenu);
	} else if (params[0]=='link') { // show link to floating panel
		createTiddlyButton(place,params[1]||this.label,params[2]||this.prompt,onClickImportMenu);
	} else if (params[0]=='inline') {// show panel as INLINE tiddler content
		createImportPanel(place);
		document.getElementById("importPanel").style.position="static";
		document.getElementById("importPanel").style.display="block";
	} else if (config.macros.loadTiddlers)
		config.macros.loadTiddlers.handler(place,macroName,params); // any other params: loadtiddlers
}

// // ''INTERFACE DEFINITION''
// // Handle link click to create/show/hide control panel
//{{{
function onClickImportMenu(e)
{
	if (!e) var e = window.event;
	var parent=resolveTarget(e).parentNode;
	var panel = document.getElementById("importPanel");
	if (panel==undefined || panel.parentNode!=parent)
		panel=createImportPanel(parent);
	var isOpen = panel.style.display=="block";
	if(config.options.chkAnimate)
		anim.startAnimating(new Slider(panel,!isOpen,e.shiftKey || e.altKey,"none"));
	else
		panel.style.display = isOpen ? "none" : "block" ;
	e.cancelBubble = true;
	if (e.stopPropagation) e.stopPropagation();
	return(false);
}
//}}}

// // Create control panel: HTML, CSS
//{{{
function createImportPanel(place) {
	var cmi=config.macros.importTiddlers; // abbreviation
	var panel=document.getElementById("importPanel");
	if (panel) { panel.parentNode.removeChild(panel); }
	setStylesheet(cmi.css,"importTiddlers");
	panel=createTiddlyElement(place,"span","importPanel",null,null)
	panel.innerHTML=cmi.html;
	refreshImportList();
	var siteURL=store.getTiddlerText("SiteUrl"); if (!siteURL) siteURL="";
	document.getElementById("importSourceURL").value=siteURL;
	cmi.src=siteURL;
	var siteProxy=store.getTiddlerText("SiteProxy"); if (!siteProxy) siteProxy="SiteProxy";
	document.getElementById("importSiteProxy").value=siteProxy;
	cmi.proxy=siteProxy;
	if (config.browser.isGecko) { // FF3 FIXUP
		document.getElementById("fileImportSource").style.display="none";
		document.getElementById("importLocalPanelFix").style.display="block";
	}
	return panel;
}
//}}}

// // CSS
//{{{
config.macros.importTiddlers.css = '\
#importPanel {\
	display: none; position:absolute; z-index:11; width:45em; right:105%; top:3em;\
	background-color: #eee; color:#000; font-size: 10pt; line-height:110%;\
	border:1px solid black; border-bottom-width: 3px; border-right-width: 3px;\
	padding: 0.5em; margin:0em; -moz-border-radius:1em;\
}\
#importPanel a, #importPanel td a { color:#009; display:inline; margin:0px; padding:1px; }\
#importPanel table { width:100%; border:0px; padding:0px; margin:0px; font-size:10pt; line-height:110%; background:transparent; }\
#importPanel tr { border:0px;padding:0px;margin:0px; background:transparent; }\
#importPanel td { color:#000; border:0px;padding:0px;margin:0px; background:transparent; }\
#importPanel select { width:100%;margin:0px;font-size:10pt;line-height:110%;}\
#importPanel input  { width:98%;padding:0px;margin:0px;font-size:10pt;line-height:110%}\
#importPanel .box { border:1px solid #000; background-color:#eee; padding:3px 5px; margin-bottom:5px; -moz-border-radius:5px;}\
#importPanel .topline { border-top:1px solid #999; padding-top:2px; margin-top:2px; }\
#importPanel .rad { width:auto; }\
#importPanel .chk { width:auto; margin:1px;border:0; }\
#importPanel .btn { width:auto; }\
#importPanel .btn1 { width:98%; }\
#importPanel .btn2 { width:48%; }\
#importPanel .btn3 { width:32%; }\
#importPanel .btn4 { width:23%; }\
#importPanel .btn5 { width:19%; }\
#importPanel .importButton { padding: 0em; margin: 0px; font-size:10pt; }\
#importPanel .importListButton { padding:0em 0.25em 0em 0.25em; color: #000000; display:inline }\
#backstagePanel #importPanel { left:10%; right:auto; }\
';
//}}}

// // HTML 
//{{{
config.macros.importTiddlers.html = '\
<!-- source and report -->\
<table><tr><td align=left>\
	import from\
	<input type="radio" class="rad" name="importFrom" id="importFromFile" value="file" CHECKED\
		onclick="onClickImportButton(this,event)" title="show file controls"> local file\
	<input type="radio" class="rad" name="importFrom" id="importFromWeb"  value="http"\
		onclick="onClickImportButton(this,event)" title="show web controls"> web server\
</td><td align=right>\
	<input type=checkbox class="chk" id="chkImportReport" checked\
		onClick="config.options[\'chkImportReport\']=this.checked;"> create report\
</td></tr></table>\
\
<div class="box" id="importSourcePanel" style="margin:.5em">\
<div id="importLocalPanel" style="display:block;margin-bottom:2px;"><!-- import from local file  -->\
enter or browse for source path/filename<br>\
<input type="file" id="fileImportSource" size=57 style="width:100%"\
	onKeyUp="config.macros.importTiddlers.src=this.value"\
	onChange="config.macros.importTiddlers.src=this.value;document.getElementById(\'importLoad\').onclick()">\
<div id="importLocalPanelFix" style="display:none"><!-- FF3 FIXUP -->\
	<input type="text" id="fileImportSourceFix" style="width:90%"\
		title="Enter a path/file to import"\
		onKeyUp="config.macros.importTiddlers.src=this.value"\
		onChange="config.macros.importTiddlers.src=this.value; document.getElementById(\'importLoad\').onclick()">\
	<input type="button" id="fileImportSourceFixButton" style="width:7%" value="..."\
		title="Select a path/file to import"\
		onClick="var r=config.macros.importTiddlers.askForFilename(this); if (!r||!r.length) return;\
			document.getElementById(\'fileImportSourceFix\').value=r;\
			config.macros.importTiddlers.src=r;\
			document.getElementById(\'importLoad\').onclick()">\
</div><!--end FF3 FIXUP-->\
</div><!--end local-->\
<div id="importHTTPPanel" style="display:none;margin-bottom:2px;"><!-- import from http server -->\
<table><tr><td align=left>\
	enter a URL or <a href="javascript:;" id="importSelectFeed"\
		onclick="onClickImportButton(this,event)" title="select a pre-defined \'systemServer\' URL">\
		select a server</a><br>\
</td><td align=right>\
	<input type="checkbox" class="chk" id="importUsePassword"\
		onClick="config.macros.importTiddlers.usePassword=this.checked;\
			config.macros.importTiddlers.showPanel(\'importIDPWPanel\',this.checked,true);">password\
	<input type="checkbox" class="chk" id="importUseProxy"\
		onClick="config.macros.importTiddlers.useProxy=this.checked;\
			config.macros.importTiddlers.showPanel(\'importSiteProxy\',this.checked,true);">proxy\
</td></tr></table>\
<input type="text" id="importSiteProxy" style="display:none;margin-bottom:1px" onfocus="this.select()" value="SiteProxy"\
	onKeyUp="config.macros.importTiddlers.proxy=this.value"\
	onChange="config.macros.importTiddlers.proxy=this.value;">\
<input type="text" id="importSourceURL" onfocus="this.select()" value="SiteUrl"\
	onKeyUp="config.macros.importTiddlers.src=this.value"\
	onChange="config.macros.importTiddlers.src=this.value;">\
<div id="importIDPWPanel" style="text-align:center;margin-top:2px;display:none";>\
username: <input type=text id="txtImportID" style="width:25%" \
	onChange="config.options.txtRemoteUsername=this.value;">\
 password: <input type=password id="txtImportPW" style="width:25%" \
	onChange="config.options.txtRemotePassword=this.value;">\
</div><!--end idpw-->\
</div><!--end http-->\
</div><!--end source-->\
\
<div class="box" id="importSelectPanel" style="display:none;margin:.5em;">\
<table><tr><td align=left>\
select:\
<a href="javascript:;" id="importSelectAll"\
	onclick="onClickImportButton(this);return false;" title="SELECT all tiddlers">\
	all</a>\
&nbsp;<a href="javascript:;" id="importSelectNew"\
	onclick="onClickImportButton(this);return false;" title="SELECT tiddlers not already in destination document">\
	added</a>\
&nbsp;<a href="javascript:;" id="importSelectChanges"\
	onclick="onClickImportButton(this);return false;" title="SELECT tiddlers that have been updated in source document">\
	changes</a>\
&nbsp;<a href="javascript:;" id="importSelectDifferences"\
	onclick="onClickImportButton(this);return false;" title="SELECT tiddlers that have been added or are different from existing tiddlers">\
	differences</a>\
</td><td align=right>\
<a href="javascript:;" id="importListSmaller"\
	onclick="onClickImportButton(this);return false;" title="SHRINK list size">\
	&nbsp;&#150;&nbsp;</a>\
<a href="javascript:;" id="importListLarger"\
	onclick="onClickImportButton(this);return false;" title="GROW list size">\
	&nbsp;+&nbsp;</a>\
<a href="javascript:;" id="importListMaximize"\
	onclick="onClickImportButton(this);return false;" title="MAXIMIZE/RESTORE list size">\
	&nbsp;=&nbsp;</a>\
</td></tr></table>\
<select id="importList" size=20 multiple\
	onchange="setTimeout(\'refreshImportList(\'+this.selectedIndex+\')\',1)">\
	<!-- NOTE: delay refresh so list is updated AFTER onchange event is handled -->\
</select>\
<div style="text-align:center">\
	<a href="javascript:;"\
		title="click for help using filters..."\
		onclick="alert(\'A filter consists of one or more space-separated combinations of:\\n\\ntiddler titles\\ntag:[[tagvalue]]\\ntag:[[tag expression]] (requires MatchTagsPlugin)\\nstory:[[TiddlerName]]\\nsearch:[[searchtext]]\\n\\nUse a blank filter for all tiddlers.\')"\
	>filter</a>\
	<input type="text" id="importLastFilter" style="margin-bottom:1px; width:65%"\
		title="Enter a combination of one or more filters. Use a blank filter for all tiddlers."\
		onfocus="this.select()" value=""\
		onKeyUp="config.macros.importTiddlers.lastFilter=this.value"\
		onChange="config.macros.importTiddlers.lastFilter=this.value;">\
	<input type="button" id="importApplyFilter" style="width:20%" value="apply"\
		title="filter list of tiddlers to include only those that match certain criteria"\
		onclick="onClickImportButton(this)">\
	</div>\
</div><!--end select-->\
\
<div class="box" id="importOptionsPanel" style="text-align:center;margin:.5em;display:none;">\
	apply tags: <input type=checkbox class="chk" id="chkImportTags" checked\
		onClick="config.macros.importTiddlers.importTags=this.checked;">from source&nbsp;\
	<input type=checkbox class="chk" id="chkKeepTags" checked\
		onClick="config.macros.importTiddlers.keepTags=this.checked;">keep existing&nbsp;\
	<input type=checkbox class="chk" id="chkAddTags" \
		onClick="config.macros.importTiddlers.addTags=this.checked;\
			config.macros.importTiddlers.showPanel(\'txtNewTags\',this.checked,true);\
			if (this.checked) document.getElementById(\'txtNewTags\').focus();">add tags<br>\
	<input type=text id="txtNewTags" style="margin-top:4px;display:none;" size=15\ onfocus="this.select()" \
		title="enter tags to be added to imported tiddlers" \
		onKeyUp="config.macros.importTiddlers.newTags=this.value;\
		document.getElementById(\'chkAddTags\').checked=this.value.length>0;" autocomplete=off>\
	<nobr><input type=checkbox class="chk" id="chkSync" \
		onClick="config.macros.importTiddlers.sync=this.checked;">\
		link imported tiddlers to source document (for sync later)</nobr>\
</div><!--end options-->\
\
<div id="importButtonPanel" style="text-align:center">\
	<input type=button id="importLoad"	class="importButton btn3" value="open"\
		title="load listbox with tiddlers from source document"\
		onclick="onClickImportButton(this)">\
	<input type=button id="importOptions"	class="importButton btn3" value="options..."\
		title="set options for tags, sync, etc."\
		onclick="onClickImportButton(this)">\
	<input type=button id="importStart"	class="importButton btn3" value="import"\
		title="start/stop import of selected source tiddlers into current document"\
		onclick="onClickImportButton(this)">\
	<input type=button id="importClose"	class="importButton btn3" value="done"\
		title="clear listbox or hide control panel"\
		onclick="onClickImportButton(this)">\
</div>\
\
<div class="none" id="importCollisionPanel" style="display:none;margin:.5em 0 .5em .5em;">\
	<table><tr><td style="width:65%" align="left">\
		<table><tr><td align=left>\
			tiddler already exists:\
		</td><td align=right>\
			<input type=checkbox class="chk" id="importApplyToAll" \
			onclick="document.getElementById(\'importRename\').disabled=this.checked;"\
			checked>apply to all\
		</td></tr></table>\
		<input type=text id="importNewTitle" size=15 autocomplete=off">\
	</td><td style="width:34%" align="center">\
		<input type=button id="importMerge"\
			class="importButton" style="width:47%" value="merge"\
			title="append the incoming tiddler to the existing tiddler"\
			onclick="onClickImportButton(this)"><!--\
		--><input type=button id="importSkip"\
			class="importButton" style="width:47%" value="skip"\
			title="do not import this tiddler"\
			onclick="onClickImportButton(this)"><!--\
		--><br><input type=button id="importRename"\
			class="importButton" style="width:47%" value="rename"\
			title="rename the incoming tiddler"\
			onclick="onClickImportButton(this)"><!--\
		--><input type=button id="importReplace"\
			class="importButton" style="width:47%" value="replace"\
			title="discard the existing tiddler"\
			onclick="onClickImportButton(this)">\
	</td></tr></table>\
</div><!--end collision-->\
';
//}}}

// // Control interactions
//{{{
function onClickImportButton(which,event)
{
	var cmi=config.macros.importTiddlers; // abbreviation

	var list = document.getElementById('importList');
	if (!list) return;
	var thePanel = document.getElementById('importPanel');
	var theCollisionPanel = document.getElementById('importCollisionPanel');
	var theNewTitle = document.getElementById('importNewTitle');
	var count=0;
	switch (which.id)
		{
		case 'importFromFile':	// show local panel
		case 'importFromWeb':	// show HTTP panel
			cmi.local=(which.id=='importFromFile');
			cmi.showPanel('importLocalPanel',cmi.local);
			cmi.showPanel('importHTTPPanel',!cmi.local);
			break;
		case 'importOptions':	// show/hide options panel
			cmi.showPanel('importOptionsPanel',document.getElementById('importOptionsPanel').style.display=='none');
			break;
		case 'fileImportSource':
		case 'importLoad':		// load import source into hidden frame
			importReport();		// if an import was in progress, generate a report
			cmi.inbound=null;	// clear the imported tiddler buffer
			refreshImportList();	// reset/resize the listbox
			if (cmi.src=="") break;
			// Load document, read it's DOM and fill the list
			cmi.loadRemoteFile(cmi.src,cmi.filterTiddlerList);
			break;
		case 'importSelectFeed':	// select a pre-defined systemServer feed URL
			var p=Popup.create(which); if (!p) return;
			var tids=store.getTaggedTiddlers('systemServer');
			if (!tids.length)
				createTiddlyText(createTiddlyElement(p,'li'),'no pre-defined server feeds');
			for (var t=0; t<tids.length; t++) {
				var u=store.getTiddlerSlice(tids[t].title,"URL");
				var d=store.getTiddlerSlice(tids[t].title,"Description");
				if (!d||!d.length) d=store.getTiddlerSlice(tids[t].title,"description");
				if (!d||!d.length) d=u;
				createTiddlyButton(createTiddlyElement(p,'li'),tids[t].title,d,
					function(){
						var u=this.getAttribute('url');
						document.getElementById('importSourceURL').value=u;
						config.macros.importTiddlers.src=u;
						document.getElementById('importLoad').onclick();
					},
					null,null,null,{url:u});
			}
			Popup.show(p,false);
			event.cancelBubble = true;
			if (event.stopPropagation) event.stopPropagation();
			return(false);
			// create popup with feed list
			// onselect, insert feed URL into input field.
			break;
		case 'importSelectAll':		// select all tiddler list items (i.e., not headings)
			importReport();		// if an import was in progress, generate a report
			for (var t=0,count=0; t < list.options.length; t++) {
				if (list.options[t].value=="") continue;
				list.options[t].selected=true;
				count++;
			}
			clearMessage(); displayMessage(cmi.countMsg.format([count]));
			document.getElementById('importStart').disabled=!count;
			break;
		case 'importSelectNew':		// select tiddlers not in current document
			importReport();		// if an import was in progress, generate a report
			for (var t=0,count=0; t < list.options.length; t++) {
				list.options[t].selected=false;
				if (list.options[t].value=="") continue;
				list.options[t].selected=!store.tiddlerExists(list.options[t].value);
				count+=list.options[t].selected?1:0;
			}
			clearMessage(); displayMessage(cmi.countMsg.format([count]));
			document.getElementById('importStart').disabled=!count;
			break;
		case 'importSelectChanges':		// select tiddlers that are updated from existing tiddlers
			importReport();		// if an import was in progress, generate a report
			for (var t=0,count=0; t < list.options.length; t++) {
				list.options[t].selected=false;
				if (list.options[t].value==""||!store.tiddlerExists(list.options[t].value)) continue;
				for (var i=0; i<cmi.inbound.length; i++) // find matching inbound tiddler
					{ var inbound=cmi.inbound[i]; if (inbound.title==list.options[t].value) break; }
				list.options[t].selected=(inbound.modified-store.getTiddler(list.options[t].value).modified>0); // updated tiddler
				count+=list.options[t].selected?1:0;
			}
			clearMessage(); displayMessage(cmi.countMsg.format([count]));
			document.getElementById('importStart').disabled=!count;
			break;
		case 'importSelectDifferences':		// select tiddlers that are new or different from existing tiddlers
			importReport();		// if an import was in progress, generate a report
			for (var t=0,count=0; t < list.options.length; t++) {
				list.options[t].selected=false;
				if (list.options[t].value=="") continue;
				if (!store.tiddlerExists(list.options[t].value)) { list.options[t].selected=true; count++; continue; }
				for (var i=0; i<cmi.inbound.length; i++) // find matching inbound tiddler
					{ var inbound=cmi.inbound[i]; if (inbound.title==list.options[t].value) break; }
				list.options[t].selected=(inbound.modified-store.getTiddler(list.options[t].value).modified!=0); // changed tiddler
				count+=list.options[t].selected?1:0;
			}
			clearMessage(); displayMessage(cmi.countMsg.format([count]));
			document.getElementById('importStart').disabled=!count;
			break;
		case 'importApplyFilter':	// filter list to include only matching tiddlers
			importReport();		// if an import was in progress, generate a report
			clearMessage();
			if (!cmi.all) // no tiddlers loaded = "0 selected"
				{ displayMessage(cmi.countMsg.format([0])); return false; }
			var hash=document.getElementById('importLastFilter').value;
			cmi.inbound=cmi.filterByHash("#"+hash,cmi.all);
			refreshImportList();	// reset/resize the listbox
			break;
		case 'importStart':		// initiate the import processing
			importReport();		// if an import was in progress, generate a report
			document.getElementById('importApplyToAll').checked=false;
			document.getElementById('importStart').value=cmi.stopText;
			if (cmi.index>0) cmi.index=-1; // stop processing
			else cmi.index=importTiddlers(0); // or begin processing
			importStopped();
			break;
		case 'importClose':		// unload imported tiddlers or hide the import control panel
			// if imported tiddlers not loaded, close the import control panel
			if (!cmi.inbound) { thePanel.style.display='none'; break; }
			importReport();		// if an import was in progress, generate a report
			cmi.inbound=null;	// clear the imported tiddler buffer
			refreshImportList();	// reset/resize the listbox
			break;
		case 'importSkip':	// don't import the tiddler
			cmi.lastAction=which;
			var theItem	= list.options[cmi.index];
			for (var j=0;j<cmi.inbound.length;j++)
			if (cmi.inbound[j].title==theItem.value) break;
			var theImported = cmi.inbound[j];
			theImported.status='skipped after asking';			// mark item as skipped
			theCollisionPanel.style.display='none';
			cmi.index=importTiddlers(cmi.index+1);	// resume with NEXT item
			importStopped();
			break;
		case 'importRename':		// change name of imported tiddler
			cmi.lastAction=which;
			var theItem		= list.options[cmi.index];
			for (var j=0;j<cmi.inbound.length;j++)
			if (cmi.inbound[j].title==theItem.value) break;
			var theImported		= cmi.inbound[j];
			theImported.status	= 'renamed from '+theImported.title;	// mark item as renamed
			theImported.set(theNewTitle.value,null,null,null,null);		// change the tiddler title
			theItem.value		= theNewTitle.value;			// change the listbox item text
			theItem.text		= theNewTitle.value;			// change the listbox item text
			theCollisionPanel.style.display='none';
			cmi.index=importTiddlers(cmi.index);	// resume with THIS item
			importStopped();
			break;
		case 'importMerge':	// join existing and imported tiddler content
			cmi.lastAction=which;
			var theItem	= list.options[cmi.index];
			for (var j=0;j<cmi.inbound.length;j++)
			if (cmi.inbound[j].title==theItem.value) break;
			var theImported	= cmi.inbound[j];
			var theExisting	= store.getTiddler(theItem.value);
			var theText	= theExisting.text+'\n----\n^^merged from: ';
			theText		+='[['+cmi.src+'#'+theItem.value+'|'+cmi.src+'#'+theItem.value+']]^^\n';
			theText		+='^^'+theImported.modified.toLocaleString()+' by '+theImported.modifier+'^^\n'+theImported.text;
			var theDate	= new Date();
			var theTags	= theExisting.getTags()+' '+theImported.getTags();
			theImported.set(null,theText,null,theDate,theTags);
			theImported.status   = 'merged with '+theExisting.title;	// mark item as merged
			theImported.status  += ' - '+theExisting.modified.formatString("MM/DD/YYYY 0hh:0mm:0ss");
			theImported.status  += ' by '+theExisting.modifier;
			theCollisionPanel.style.display='none';
			cmi.index=importTiddlers(cmi.index);	// resume with this item
			importStopped();
			break;
		case 'importReplace':		// substitute imported tiddler for existing tiddler
			cmi.lastAction=which;
			var theItem		  = list.options[cmi.index];
			for (var j=0;j<cmi.inbound.length;j++)
			if (cmi.inbound[j].title==theItem.value) break;
			var theImported     = cmi.inbound[j];
			var theExisting	  = store.getTiddler(theItem.value);
			theImported.status  = 'replaces '+theExisting.title;		// mark item for replace
			theImported.status += ' - '+theExisting.modified.formatString("MM/DD/YYYY 0hh:0mm:0ss");
			theImported.status += ' by '+theExisting.modifier;
			theCollisionPanel.style.display='none';
			cmi.index=importTiddlers(cmi.index);	// resume with THIS item
			importStopped();
			break;
		case 'importListSmaller':		// decrease current listbox size, minimum=5
			if (list.options.length==1) break;
			list.size-=(list.size>5)?1:0;
			cmi.listsize=list.size;
			break;
		case 'importListLarger':		// increase current listbox size, maximum=number of items in list
			if (list.options.length==1) break;
			list.size+=(list.size<list.options.length)?1:0;
			cmi.listsize=list.size;
			break;
		case 'importListMaximize':	// toggle listbox size between current and maximum
			if (list.options.length==1) break;
			list.size=(list.size==list.options.length)?cmi.listsize:list.options.length;
			break;
		}
}
//}}}

// // toggle panel
//{{{
config.macros.importTiddlers.showPanel=function(place,show,skipAnim) {
	if (typeof place == "string") var place=document.getElementById(place);
	if (!place||!place.style) return;
	if(!skipAnim && anim && config.options.chkAnimate) anim.startAnimating(new Slider(place,show,false,"none"));
	else place.style.display=show?"block":"none";
}
//}}}

// // refresh listbox
//{{{
function refreshImportList(selectedIndex)
{
	var cmi=config.macros.importTiddlers; // abbreviation

	var list  = document.getElementById("importList");
	if (!list) return;
	// if nothing to show, reset list content and size
	if (!cmi.inbound) 
	{
		while (list.length > 0) { list.options[0] = null; }
		list.options[0]=new Option(cmi.loadText,"",false,false);
		list.size=cmi.listsize;

		// toggle buttons and panels
		document.getElementById('importLoad').disabled=false;
		document.getElementById('importLoad').style.display='inline';
		document.getElementById('importStart').disabled=true;
		document.getElementById('importOptions').disabled=true;
		document.getElementById('importOptions').style.display='none';
		document.getElementById('fileImportSource').disabled=false;
		document.getElementById('importFromFile').disabled=false;
		document.getElementById('importFromWeb').disabled=false;
		document.getElementById('importStart').value=cmi.startText;
		document.getElementById('importClose').value=cmi.doneText;
		document.getElementById('importSelectPanel').style.display='none';
		document.getElementById('importOptionsPanel').style.display='none';
		return;
	}
	// there are inbound tiddlers loaded...
	// toggle buttons and panels
	document.getElementById('importLoad').disabled=true;
	document.getElementById('importLoad').style.display='none';
	document.getElementById('importOptions').style.display='inline';
	document.getElementById('importOptions').disabled=false;
	document.getElementById('fileImportSource').disabled=true;
	document.getElementById('importFromFile').disabled=true;
	document.getElementById('importFromWeb').disabled=true;
	document.getElementById('importClose').value=cmi.closeText;
	if (document.getElementById('importSelectPanel').style.display=='none')
		cmi.showPanel('importSelectPanel',true);

	// get the sort order
	if (!selectedIndex)   selectedIndex=0;
	if (selectedIndex==0) cmi.sort='title';		// heading
	if (selectedIndex==1) cmi.sort='title';
	if (selectedIndex==2) cmi.sort='modified';
	if (selectedIndex==3) cmi.sort='tags';
	if (selectedIndex>3) {
		// display selected tiddler count
		for (var t=0,count=0; t < list.options.length; t++) {
			if (!list.options[t].selected) continue;
			if (list.options[t].value!="")
				count+=1;
			else { // if heading is selected, deselect it, and then select and count all in section
				list.options[t].selected=false;
				for ( t++; t<list.options.length && list.options[t].value!=""; t++) {
					list.options[t].selected=true;
					count++;
				}
			}
		}
		clearMessage(); displayMessage(cmi.countMsg.format([count]));
	}
	document.getElementById('importStart').disabled=!count;
	if (selectedIndex>3) return; // no refresh needed

	// get the alphasorted list of tiddlers
	var tiddlers=cmi.inbound;
	tiddlers.sort(function (a,b) {if(a['title'] == b['title']) return(0); else return (a['title'] < b['title']) ? -1 : +1; });
	// clear current list contents
	while (list.length > 0) { list.options[0] = null; }
	// add heading and control items to list
	var i=0;
	var indent=String.fromCharCode(160)+String.fromCharCode(160);
	if (cmi.all.length==tiddlers.length)
		var summary=cmi.summaryMsg.format([tiddlers.length,(tiddlers.length!=1)?cmi.plural:cmi.single]);
	else
		var summary=cmi.summaryFilteredMsg.format([tiddlers.length,cmi.all.length,(cmi.all.length!=1)?cmi.plural:cmi.single]);
	list.options[i++]=new Option(summary,"",false,false);
	list.options[i++]=new Option(((cmi.sort=="title"   )?">":indent)+' [by title]',"",false,false);
	list.options[i++]=new Option(((cmi.sort=="modified")?">":indent)+' [by date]',"",false,false);
	list.options[i++]=new Option(((cmi.sort=="tags")?">":indent)+' [by tags]',"",false,false);
	// output the tiddler list
	switch(cmi.sort) {
		case "title":
			for(var t = 0; t < tiddlers.length; t++)
				list.options[i++] = new Option(tiddlers[t].title,tiddlers[t].title,false,false);
			break;
		case "modified":
			// sort descending for newest date first
			tiddlers.sort(function (a,b) {if(a['modified'] == b['modified']) return(0); else return (a['modified'] > b['modified']) ? -1 : +1; });
			var lastSection = "";
			for(var t = 0; t < tiddlers.length; t++) {
				var tiddler = tiddlers[t];
				var theSection = tiddler.modified.toLocaleDateString();
				if (theSection != lastSection) {
					list.options[i++] = new Option(theSection,"",false,false);
					lastSection = theSection;
				}
				list.options[i++] = new Option(indent+indent+tiddler.title,tiddler.title,false,false);
			}
			break;
		case "tags":
			var theTitles = {}; // all tiddler titles, hash indexed by tag value
			var theTags = new Array();
			for(var t=0; t<tiddlers.length; t++) {
				var title=tiddlers[t].title;
				var tags=tiddlers[t].tags;
				if (!tags || !tags.length) {
					if (theTitles["untagged"]==undefined) { theTags.push("untagged"); theTitles["untagged"]=new Array(); }
					theTitles["untagged"].push(title);
				}
				else for(var s=0; s<tags.length; s++) {
					if (theTitles[tags[s]]==undefined) { theTags.push(tags[s]); theTitles[tags[s]]=new Array(); }
					theTitles[tags[s]].push(title);
				}
			}
			theTags.sort();
			for(var tagindex=0; tagindex<theTags.length; tagindex++) {
				var theTag=theTags[tagindex];
				list.options[i++]=new Option(theTag,"",false,false);
				for(var t=0; t<theTitles[theTag].length; t++)
					list.options[i++]=new Option(indent+indent+theTitles[theTag][t],theTitles[theTag][t],false,false);
			}
			break;
		}
	list.selectedIndex=selectedIndex;		  // select current control item
	if (list.size<cmi.listsize) list.size=cmi.listsize;
	if (list.size>list.options.length) list.size=list.options.length;
}

config.macros.importTiddlers.filterTiddlerList=function(success,params,txt,src,xhr) {
	var cmi=config.macros.importTiddlers; // abbreviation
	var src=src.replace(/%20/g," ");
	if (!success) { displayMessage(cmi.openErrMsg.format([src,xhr.status])); return; }
	cmi.all = cmi.readTiddlersFromHTML(txt);
	var count=cmi.all?cmi.all.length:0;
	var querypos=src.lastIndexOf("?"); if (querypos!=-1) src=src.substr(0,querypos);
	displayMessage(cmi.foundMsg.format([count,src]));
	cmi.inbound=cmi.filterByHash(params,cmi.all); // use full URL including hash (if any)
	document.getElementById("importLastFilter").value=cmi.lastFilter;
	window.refreshImportList(0);
}

config.macros.importTiddlers.filterByHash=function(src,tiddlers)
{
	var hashpos=src.lastIndexOf("#"); if (hashpos==-1) return tiddlers;
	var hash=src.substr(hashpos+1); if (!hash.length) return tiddlers;
	var tids=[];
	var params=hash.parseParams("anon",null,true,false,false);
	for (var p=1; p<params.length; p++) {
		switch (params[p].name) {
			case "anon":
			case "open":
				tids.pushUnique(params[p].value);
				break;
			case "tag":
				if (store.getMatchingTiddlers) { // for boolean expressions - see MatchTagsPlugin
					var r=store.getMatchingTiddlers(params[p].value,null,tiddlers);
					for (var t=0; t<r.length; t++) tids.pushUnique(r[t].title);
				} else for (var t=0; t<tiddlers.length; t++)
					if (tiddlers[t].isTagged(params[p].value))
						tids.pushUnique(tiddlers[t].title);
				break;
			case "story":
				for (var t=0; t<tiddlers.length; t++)
					if (tiddlers[t].title==params[p].value) {
						tiddlers[t].changed();
						for (var s=0; s<tiddlers[t].links.length; s++)
							tids.pushUnique(tiddlers[t].links[s]);
						break;
					}
				break;
			case "search":
				for (var t=0; t<tiddlers.length; t++)
					if (tiddlers[t].text.indexOf(params[p].value)!=-1)
						tids.pushUnique(tiddlers[t].title);
				break;
		}
	}
	var matches=[];
	for (var t=0; t<tiddlers.length; t++)
		if (tids.contains(tiddlers[t].title))
			matches.push(tiddlers[t]);
	displayMessage(config.macros.importTiddlers.filterMsg.format([matches.length,hash]));
	config.macros.importTiddlers.lastFilter=hash;
	return matches;
}
//}}}

// // re-entrant processing for handling import with interactive collision prompting
//{{{
function importTiddlers(startIndex)
{
	var cmi=config.macros.importTiddlers; // abbreviation

	if (!cmi.inbound) return -1;

	var list = document.getElementById('importList');
	if (!list) return;
	var t;
	// if starting new import, reset import status flags
	if (startIndex==0)
		for (var t=0;t<cmi.inbound.length;t++)
			cmi.inbound[t].status="";
	for (var i=startIndex; i<list.options.length; i++)
		{
		// if list item is not selected or is a heading (i.e., has no value), skip it
		if ((!list.options[i].selected) || ((t=list.options[i].value)==""))
			continue;
		for (var j=0;j<cmi.inbound.length;j++)
			if (cmi.inbound[j].title==t) break;
		var inbound = cmi.inbound[j];
		var theExisting = store.getTiddler(inbound.title);
		// avoid redundant import for tiddlers that are listed multiple times (when 'by tags')
		if (inbound.status=="added")
			continue;
		// don't import the "ImportedTiddlers" history from the other document...
		if (inbound.title=='ImportedTiddlers')
			continue;
		// if tiddler exists and import not marked for replace or merge, stop importing
		if (theExisting && (inbound.status.substr(0,7)!="replace") && (inbound.status.substr(0,5)!="merge"))
			return i;
		// assemble tags (remote + existing + added)
		var newTags = "";
		if (cmi.importTags)
			newTags+=inbound.getTags()	// import remote tags
		if (cmi.keepTags && theExisting)
			newTags+=" "+theExisting.getTags(); // keep existing tags
		if (cmi.addTags && cmi.newTags.trim().length)
			newTags+=" "+cmi.newTags; // add new tags
		inbound.set(null,null,null,null,newTags.trim());
		// set the status to 'added' (if not already set by the 'ask the user' UI)
		inbound.status=(inbound.status=="")?'added':inbound.status;
		// set sync fields
		if (cmi.sync) {
			if (!inbound.fields) inbound.fields={}; // for TW2.1.x backward-compatibility
			inbound.fields["server.page.revision"]=inbound.modified.convertToYYYYMMDDHHMM();
			inbound.fields["server.type"]="file";
			inbound.fields["server.host"]=(cmi.local?"file://":"")+cmi.src;
		}
		// do the import!
		store.suspendNotifications();
		store.saveTiddler(inbound.title, inbound.title, inbound.text, inbound.modifier, inbound.modified, inbound.tags, inbound.fields, true, inbound.created);
                store.fetchTiddler(inbound.title).created = inbound.created; // force creation date to imported value (needed for TW2.1.x and earlier)
		store.resumeNotifications();
		}
	return(-1);	// signals that we really finished the entire list
}
//}}}

//{{{
function importStopped()
{
	var cmi=config.macros.importTiddlers; // abbreviation
	var list = document.getElementById('importList');
	var theNewTitle = document.getElementById('importNewTitle');
	if (!list) return;
	if (cmi.index==-1){ 
		document.getElementById('importStart').value=cmi.startText;
		importReport();		// import finished... generate the report
	} else {
		// import collision...
		// show the collision panel and set the title edit field
		document.getElementById('importStart').value=cmi.stopText;
		cmi.showPanel('importCollisionPanel',true);
		theNewTitle.value=list.options[cmi.index].value;
		if (document.getElementById('importApplyToAll').checked
			&& cmi.lastAction
			&& cmi.lastAction.id!="importRename") {
			onClickImportButton(cmi.lastAction);
		}
	}
}
//}}}

// // ''REPORT GENERATOR''
//{{{
function importReport()
{
	var cmi=config.macros.importTiddlers; // abbreviation
	if (!cmi.inbound) return;

	// if import was not completed, the collision panel will still be open... close it now.
	var panel=document.getElementById('importCollisionPanel'); if (panel) panel.style.display='none';

	// get the alphasorted list of tiddlers
	var tiddlers = cmi.inbound;
	// gather the statistics
	var count=0; var total=0;
	for (var t=0; t<tiddlers.length; t++) {
		if (!tiddlers[t].status || !tiddlers[t].status.trim().length) continue;
		if (tiddlers[t].status.substr(0,7)!="skipped") count++;
		total++;
	}
	// generate a report
	if (total) displayMessage(cmi.processedMsg.format([total]));
	if (count && config.options.chkImportReport) {
		// get/create the report tiddler
		var theReport = store.getTiddler('ImportedTiddlers');
		if (!theReport) { theReport= new Tiddler(); theReport.title = 'ImportedTiddlers'; theReport.text  = ""; }
		// format the report content
		var now = new Date();
		var newText = "On "+now.toLocaleString()+", "+config.options.txtUserName
		newText +=" imported "+count+" tiddler"+(count==1?"":"s")+" from\n[["+cmi.src+"|"+cmi.src+"]]:\n";
		if (cmi.addTags && cmi.newTags.trim().length)
			newText += "imported tiddlers were tagged with: \""+cmi.newTags+"\"\n";
		newText += "<<<\n";
		for (var t=0; t<tiddlers.length; t++) if (tiddlers[t].status) newText += "#[["+tiddlers[t].title+"]] - "+tiddlers[t].status+"\n";
		newText += "<<<\n";
		// update the ImportedTiddlers content and show the tiddler
		theReport.text	 = newText+((theReport.text!="")?'\n----\n':"")+theReport.text;
		theReport.modifier = config.options.txtUserName;
		theReport.modified = new Date();
                store.saveTiddler(theReport.title, theReport.title, theReport.text, theReport.modifier, theReport.modified, theReport.tags, theReport.fields);
		story.displayTiddler(null,theReport.title,1,null,null,false);
		story.refreshTiddler(theReport.title,1,true);
	}

	// reset status flags
	for (var t=0; t<cmi.inbound.length; t++) cmi.inbound[t].status="";

	// mark document as dirty and let display update as needed
	if (count) { store.setDirty(true); store.notifyAll(); }

	// always show final message when tiddlers were actually loaded
	if (count) displayMessage(cmi.importedMsg.format([count,tiddlers.length,cmi.src.replace(/%20/g," ")]));
}
//}}}

// // File and XMLHttpRequest I/O
//{{{
config.macros.importTiddlers.askForFilename=function(here) {
	var msg=here.title; // use tooltip as dialog box message
	var path=getLocalPath(document.location.href);
	var slashpos=path.lastIndexOf("/"); if (slashpos==-1) slashpos=path.lastIndexOf("\\"); 
	if (slashpos!=-1) path = path.substr(0,slashpos+1); // remove filename from path, leave the trailing slash
	var file="";
	var result="";
	if(window.Components) { // moz
		try {
			netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
			var nsIFilePicker = window.Components.interfaces.nsIFilePicker;
			var picker = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
			picker.init(window, msg, nsIFilePicker.modeOpen);
			var thispath = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
			thispath.initWithPath(path);
			picker.displayDirectory=thispath;
			picker.defaultExtension='html';
			picker.defaultString=file;
			picker.appendFilters(nsIFilePicker.filterAll|nsIFilePicker.filterText|nsIFilePicker.filterHTML);
			if (picker.show()!=nsIFilePicker.returnCancel) var result=picker.file.persistentDescriptor;
		}
		catch(e) { alert('error during local file access: '+e.toString()) }
	}
	else { // IE
		try { // XPSP2 IE only
			var s = new ActiveXObject('UserAccounts.CommonDialog');
			s.Filter='All files|*.*|Text files|*.txt|HTML files|*.htm;*.html|';
			s.FilterIndex=3; // default to HTML files;
			s.InitialDir=path;
			s.FileName=file;
			if (s.showOpen()) var result=s.FileName;
		}
		catch(e) {  // fallback
			var result=prompt(msg,path+file);
		}
	}
	return result;
}

config.macros.importTiddlers.loadRemoteFile = function(src,callback) {
	if (src==undefined || !src.length) return null; // filename is required
	var original=src; // URL as specified
	var hashpos=src.indexOf("#"); if (hashpos!=-1) src=src.substr(0,hashpos); // URL with #... suffix removed (needed for IE)
	clearMessage();
	displayMessage(this.openMsg.format([src.replace(/%20/g," ")]));
	if (src.substr(0,5)!="http:" && src.substr(0,5)!="file:") { // if not a URL, read from local filesystem
		var txt=loadFile(src);
		if (!txt) { // file didn't load, might be relative path.. try fixup
			var pathPrefix=document.location.href;  // get current document path and trim off filename
			var slashpos=pathPrefix.lastIndexOf("/"); if (slashpos==-1) slashpos=pathPrefix.lastIndexOf("\\"); 
			if (slashpos!=-1 && slashpos!=pathPrefix.length-1) pathPrefix=pathPrefix.substr(0,slashpos+1);
			src=pathPrefix+src;
			if (pathPrefix.substr(0,5)!="http:") src=getLocalPath(src);
			var txt=loadFile(src);
		}
		if (!txt) { // file still didn't load, report error
			displayMessage(config.macros.importTiddlers.openErrMsg.format([src.replace(/%20/g," "),"(filesystem error)"]));
		} else {
			displayMessage(config.macros.importTiddlers.readMsg.format([txt.length,src.replace(/%20/g," ")]));
			if (callback) callback(true,original,convertUTF8ToUnicode(txt),src,null);
		}
	} else {
		var name=config.options.txtRemoteUsername; var pass=config.options.txtRemotePassword;
		var xhr=doHttp("GET",src,null,null,name,pass,callback,original,null)
		if (!xhr) displayMessage(config.macros.importTiddlers.openErrMsg.format([src,"(XMLHTTPRequest error)"]));
	}
}

config.macros.importTiddlers.readTiddlersFromHTML=function(html)
{
	var remoteStore=new TiddlyWiki();
	remoteStore.importTiddlyWiki(html);
	return remoteStore.getTiddlers("title");	
}
//}}}
/***
|''Name:''|IntelliTaggerPlugin|
|''Version:''|1.0.2 (2007-07-25)|
|''Type:''|plugin|
|''Source:''|http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin|
|''Author:''|Udo Borkowski (ub [at] abego-software [dot] de)|
|''Documentation:''|[[IntelliTaggerPlugin Documentation]]|
|''~SourceCode:''|[[IntelliTaggerPlugin SourceCode]]|
|''Licence:''|[[BSD open source license (abego Software)]]|
|''~CoreVersion:''|2.0.8|
|''Browser:''|Firefox 1.5.0.2 or better|
***/
/***
!Version History
* 1.0.2 (2007-07-25): 
** Feature: "Return" key may be used to accept first tag suggestion (beside "Alt-1")
** Bugfix: Keyboard shortcuts (Alt+3 etc.) shifted
* 1.0.1 (2007-05-18): Improvement: Speedup when using TiddlyWikis with many tags
* 1.0.0 (2006-04-26): Initial release

***/
// /%
if(!version.extensions.IntelliTaggerPlugin){if(!window.abego){window.abego={};}if(!abego.internal){abego.internal={};}abego.alertAndThrow=function(s){alert(s);throw s;};if(version.major<2){abego.alertAndThrow("Use TiddlyWiki 2.0.8 or better to run the IntelliTagger Plugin.");}version.extensions.IntelliTaggerPlugin={major:1,minor:0,revision:2,date:new Date(2007,6,25),type:"plugin",source:"http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin",documentation:"[[IntelliTaggerPlugin Documentation]]",sourcecode:"[[IntelliTaggerPlugin SourceCode]]",author:"Udo Borkowski (ub [at] abego-software [dot] de)",licence:"[[BSD open source license (abego Software)]]",tiddlywiki:"Version 2.0.8 or better",browser:"Firefox 1.5.0.2 or better"};abego.createEllipsis=function(_2){var e=createTiddlyElement(_2,"span");e.innerHTML="&hellip;";};abego.isPopupOpen=function(_4){return _4&&_4.parentNode==document.body;};abego.openAsPopup=function(_5){if(_5.parentNode!=document.body){document.body.appendChild(_5);}};abego.closePopup=function(_6){if(abego.isPopupOpen(_6)){document.body.removeChild(_6);}};abego.getWindowRect=function(){return {left:findScrollX(),top:findScrollY(),height:findWindowHeight(),width:findWindowWidth()};};abego.moveElement=function(_7,_8,_9){_7.style.left=_8+"px";_7.style.top=_9+"px";};abego.centerOnWindow=function(_a){if(_a.style.position!="absolute"){throw "abego.centerOnWindow: element must have absolute position";}var _b=abego.getWindowRect();abego.moveElement(_a,_b.left+(_b.width-_a.offsetWidth)/2,_b.top+(_b.height-_a.offsetHeight)/2);};abego.isDescendantOrSelf=function(_c,e){while(e){if(_c==e){return true;}e=e.parentNode;}return false;};abego.toSet=function(_e){var _f={};for(var i=0;i<_e.length;i++){_f[_e[i]]=true;}return _f;};abego.filterStrings=function(_11,_12,_13){var _14=[];for(var i=0;i<_11.length&&(_13===undefined||_14.length<_13);i++){var s=_11[i];if(s.match(_12)){_14.push(s);}}return _14;};abego.arraysAreEqual=function(a,b){if(!a){return !b;}if(!b){return false;}var n=a.length;if(n!=b.length){return false;}for(var i=0;i<n;i++){if(a[i]!=b[i]){return false;}}return true;};abego.moveBelowAndClip=function(_1b,_1c){if(!_1c){return;}var _1d=findPosX(_1c);var _1e=findPosY(_1c);var _1f=_1c.offsetHeight;var _20=_1d;var _21=_1e+_1f;var _22=findWindowWidth();if(_22<_1b.offsetWidth){_1b.style.width=(_22-100)+"px";}var _23=_1b.offsetWidth;if(_20+_23>_22){_20=_22-_23-30;}if(_20<0){_20=0;}_1b.style.left=_20+"px";_1b.style.top=_21+"px";_1b.style.display="block";};abego.compareStrings=function(a,b){return (a==b)?0:(a<b)?-1:1;};abego.sortIgnoreCase=function(arr){var _27=[];var n=arr.length;for(var i=0;i<n;i++){var s=arr[i];_27.push([s.toString().toLowerCase(),s]);}_27.sort(function(a,b){return (a[0]==b[0])?0:(a[0]<b[0])?-1:1;});for(i=0;i<n;i++){arr[i]=_27[i][1];}};abego.getTiddlerField=function(_2d,_2e,_2f){var _30=document.getElementById(_2d.idPrefix+_2e);var e=null;if(_30!=null){var _32=_30.getElementsByTagName("*");for(var t=0;t<_32.length;t++){var c=_32[t];if(c.tagName.toLowerCase()=="input"||c.tagName.toLowerCase()=="textarea"){if(!e){e=c;}if(c.getAttribute("edit")==_2f){e=c;}}}}return e;};abego.setRange=function(_35,_36,end){if(_35.setSelectionRange){_35.setSelectionRange(_36,end);var max=0+_35.scrollHeight;var len=_35.textLength;var top=max*_36/len,bot=max*end/len;_35.scrollTop=Math.min(top,(bot+top-_35.clientHeight)/2);}else{if(_35.createTextRange!=undefined){var _3b=_35.createTextRange();_3b.collapse();_3b.moveEnd("character",end);_3b.moveStart("character",_36);_3b.select();}else{_35.select();}}};abego.internal.TagManager=function(){var _3c=null;var _3d=function(){if(_3c){return;}_3c={};store.forEachTiddler(function(_3e,_3f){for(var i=0;i<_3f.tags.length;i++){var tag=_3f.tags[i];var _42=_3c[tag];if(!_42){_42=_3c[tag]={count:0,tiddlers:{}};}_42.tiddlers[_3f.title]=true;_42.count+=1;}});};var _43=TiddlyWiki.prototype.saveTiddler;TiddlyWiki.prototype.saveTiddler=function(_44,_45,_46,_47,_48,_49){var _4a=this.fetchTiddler(_44);var _4b=_4a?_4a.tags:[];var _4c=(typeof _49=="string")?_49.readBracketedList():_49;_43.apply(this,arguments);if(!abego.arraysAreEqual(_4b,_4c)){abego.internal.getTagManager().reset();}};var _4d=TiddlyWiki.prototype.removeTiddler;TiddlyWiki.prototype.removeTiddler=function(_4e){var _4f=this.fetchTiddler(_4e);var _50=_4f&&_4f.tags.length>0;_4d.apply(this,arguments);if(_50){abego.internal.getTagManager().reset();}};this.reset=function(){_3c=null;};this.getTiddlersWithTag=function(tag){_3d();var _52=_3c[tag];return _52?_52.tiddlers:null;};this.getAllTags=function(_53){_3d();var _54=[];for(var i in _3c){_54.push(i);}for(i=0;_53&&i<_53.length;i++){_54.pushUnique(_53[i],true);}abego.sortIgnoreCase(_54);return _54;};this.getTagInfos=function(){_3d();var _56=[];for(var _57 in _3c){_56.push([_57,_3c[_57]]);}return _56;};var _58=function(a,b){var a1=a[1];var b1=b[1];var d=b[1].count-a[1].count;return d!=0?d:abego.compareStrings(a[0].toLowerCase(),b[0].toLowerCase());};this.getSortedTagInfos=function(){_3d();var _5e=this.getTagInfos();_5e.sort(_58);return _5e;};this.getPartnerRankedTags=function(_5f){var _60={};for(var i=0;i<_5f.length;i++){var _62=this.getTiddlersWithTag(_5f[i]);for(var _63 in _62){var _64=store.getTiddler(_63);if(!(_64 instanceof Tiddler)){continue;}for(var j=0;j<_64.tags.length;j++){var tag=_64.tags[j];var c=_60[tag];_60[tag]=c?c+1:1;}}}var _68=abego.toSet(_5f);var _69=[];for(var n in _60){if(!_68[n]){_69.push(n);}}_69.sort(function(a,b){var d=_60[b]-_60[a];return d!=0?d:abego.compareStrings(a.toLowerCase(),b.toLowerCase());});return _69;};};abego.internal.getTagManager=function(){if(!abego.internal.gTagManager){abego.internal.gTagManager=new abego.internal.TagManager();}return abego.internal.gTagManager;};(function(){var _6e=2;var _6f=1;var _70=30;var _71;var _72;var _73;var _74;var _75;var _76;if(!abego.IntelliTagger){abego.IntelliTagger={};}var _77=function(){return _72;};var _78=function(tag){return _75[tag];};var _7a=function(s){var i=s.lastIndexOf(" ");return (i>=0)?s.substr(0,i):"";};var _7d=function(_7e){var s=_7e.value;var len=s.length;return (len>0&&s[len-1]!=" ");};var _81=function(_82){var s=_82.value;var len=s.length;if(len>0&&s[len-1]!=" "){_82.value+=" ";}};var _85=function(tag,_87,_88){if(_7d(_87)){_87.value=_7a(_87.value);}story.setTiddlerTag(_88.title,tag,0);_81(_87);abego.IntelliTagger.assistTagging(_87,_88);};var _89=function(n){if(_76&&_76.length>n){return _76[n];}return (_74&&_74.length>n)?_74[n]:null;};var _8b=function(n,_8d,_8e){var _8f=_89(n);if(_8f){_85(_8f,_8d,_8e);}};var _90=function(_91){var pos=_91.value.lastIndexOf(" ");var _93=(pos>=0)?_91.value.substr(++pos,_91.value.length):_91.value;return new RegExp(_93.escapeRegExp(),"i");};var _94=function(_95,_96){var _97=0;for(var i=0;i<_95.length;i++){if(_96[_95[i]]){_97++;}}return _97;};var _99=function(_9a,_9b,_9c){var _9d=1;var c=_9a[_9b];for(var i=_9b+1;i<_9a.length;i++){if(_9a[i][1].count==c){if(_9a[i][0].match(_9c)){_9d++;}}else{break;}}return _9d;};var _a0=function(_a1,_a2){var _a3=abego.internal.getTagManager().getSortedTagInfos();var _a4=[];var _a5=0;for(var i=0;i<_a3.length;i++){var c=_a3[i][1].count;if(c!=_a5){if(_a2&&(_a4.length+_99(_a3,i,_a1)>_a2)){break;}_a5=c;}if(c==1){break;}var s=_a3[i][0];if(s.match(_a1)){_a4.push(s);}}return _a4;};var _a9=function(_aa,_ab){return abego.filterStrings(abego.internal.getTagManager().getAllTags(_ab),_aa);};var _ac=function(){if(!_71){return;}var _ad=store.getTiddlerText("IntelliTaggerMainTemplate");if(!_ad){_ad="<b>Tiddler IntelliTaggerMainTemplate not found</b>";}_71.innerHTML=_ad;applyHtmlMacros(_71,null);refreshElements(_71,null);};var _ae=function(e){if(!e){var e=window.event;}var tag=this.getAttribute("tag");if(_73){_73.call(this,tag,e);}return false;};var _b2=function(_b3){createTiddlyElement(_b3,"span",null,"tagSeparator"," | ");};var _b4=function(_b5,_b6,_b7,_b8,_b9){if(!_b6){return;}var _ba=_b8?abego.toSet(_b8):{};var n=_b6.length;var c=0;for(var i=0;i<n;i++){var tag=_b6[i];if(_ba[tag]){continue;}if(c>0){_b2(_b5);}if(_b9&&c>=_b9){abego.createEllipsis(_b5);break;}c++;var _bf="";var _c0=_b5;if(_b7<10){_c0=createTiddlyElement(_b5,"span",null,"numberedSuggestion");_b7++;var key=_b7<10?""+(_b7):"0";createTiddlyElement(_c0,"span",null,"suggestionNumber",key+") ");var _c2=_b7==1?"Return or ":"";_bf=" (Shortcut: %1Alt-%0)".format([key,_c2]);}var _c3=config.views.wikified.tag.tooltip.format([tag]);var _c4=(_78(tag)?"Remove tag '%0'%1":"Add tag '%0'%1").format([tag,_bf]);var _c5="%0; Shift-Click: %1".format([_c4,_c3]);var btn=createTiddlyButton(_c0,tag,_c5,_ae,_78(tag)?"currentTag":null);btn.setAttribute("tag",tag);}};var _c7=function(){if(_71){window.scrollTo(0,ensureVisible(_71));}if(_77()){window.scrollTo(0,ensureVisible(_77()));}};var _c8=function(e){if(!e){var e=window.event;}if(!_71){return;}var _cb=resolveTarget(e);if(_cb==_77()){return;}if(abego.isDescendantOrSelf(_71,_cb)){return;}abego.IntelliTagger.close();};addEvent(document,"click",_c8);var _cc=Story.prototype.gatherSaveFields;Story.prototype.gatherSaveFields=function(e,_ce){_cc.apply(this,arguments);var _cf=_ce.tags;if(_cf){_ce.tags=_cf.trim();}};var _d0=function(_d1){story.focusTiddler(_d1,"tags");var _d2=abego.getTiddlerField(story,_d1,"tags");if(_d2){var len=_d2.value.length;abego.setRange(_d2,len,len);window.scrollTo(0,ensureVisible(_d2));}};var _d4=config.macros.edit.handler;config.macros.edit.handler=function(_d5,_d6,_d7,_d8,_d9,_da){_d4.apply(this,arguments);var _db=_d7[0];if((_da instanceof Tiddler)&&_db=="tags"){var _dc=_d5.lastChild;_dc.onfocus=function(e){abego.IntelliTagger.assistTagging(_dc,_da);setTimeout(function(){_d0(_da.title);},100);};_dc.onkeyup=function(e){if(!e){var e=window.event;}if(e.altKey&&!e.ctrlKey&&!e.metaKey&&(e.keyCode>=48&&e.keyCode<=57)){_8b(e.keyCode==48?9:e.keyCode-49,_dc,_da);}else{if(e.ctrlKey&&e.keyCode==32){_8b(0,_dc,_da);}}if(!e.ctrlKey&&(e.keyCode==13||e.keyCode==10)){_8b(0,_dc,_da);}setTimeout(function(){abego.IntelliTagger.assistTagging(_dc,_da);},100);return false;};_81(_dc);}};var _e0=function(e){if(!e){var e=window.event;}var _e3=resolveTarget(e);var _e4=_e3.getAttribute("tiddler");if(_e4){story.displayTiddler(_e3,_e4,"IntelliTaggerEditTagsTemplate",false);_d0(_e4);}return false;};var _e5=config.macros.tags.handler;config.macros.tags.handler=function(_e6,_e7,_e8,_e9,_ea,_eb){_e5.apply(this,arguments);abego.IntelliTagger.createEditTagsButton(_eb,createTiddlyElement(_e6.lastChild,"li"));};var _ec=function(){if(_71&&_72&&!abego.isDescendantOrSelf(document,_72)){abego.IntelliTagger.close();}};setInterval(_ec,100);abego.IntelliTagger.displayTagSuggestions=function(_ed,_ee,_ef,_f0,_f1){_74=_ed;_75=abego.toSet(_ee);_76=_ef;_72=_f0;_73=_f1;if(!_71){_71=createTiddlyElement(document.body,"div",null,"intelliTaggerSuggestions");_71.style.position="absolute";}_ac();abego.openAsPopup(_71);if(_77()){var w=_77().offsetWidth;if(_71.offsetWidth<w){_71.style.width=(w-2*(_6e+_6f))+"px";}abego.moveBelowAndClip(_71,_77());}else{abego.centerOnWindow(_71);}_c7();};abego.IntelliTagger.assistTagging=function(_f3,_f4){var _f5=_90(_f3);var s=_f3.value;if(_7d(_f3)){s=_7a(s);}var _f7=s.readBracketedList();var _f8=_f7.length>0?abego.filterStrings(abego.internal.getTagManager().getPartnerRankedTags(_f7),_f5,_70):_a0(_f5,_70);abego.IntelliTagger.displayTagSuggestions(_a9(_f5,_f7),_f7,_f8,_f3,function(tag,e){if(e.shiftKey){onClickTag.call(this,e);}else{_85(tag,_f3,_f4);}});};abego.IntelliTagger.close=function(){abego.closePopup(_71);_71=null;return false;};abego.IntelliTagger.createEditTagsButton=function(_fb,_fc,_fd,_fe,_ff,id,_101){if(!_fd){_fd="[edit]";}if(!_fe){_fe="Edit the tags";}if(!_ff){_ff="editTags";}var _102=createTiddlyButton(_fc,_fd,_fe,_e0,_ff,id,_101);_102.setAttribute("tiddler",(_fb instanceof Tiddler)?_fb.title:String(_fb));return _102;};abego.IntelliTagger.getSuggestionTagsMaxCount=function(){return 100;};config.macros.intelliTagger={label:"intelliTagger",handler:function(_103,_104,_105,_106,_107,_108){var _109=_107.parseParams("list",null,true);var _10a=_109[0]["action"];for(var i=0;_10a&&i<_10a.length;i++){var _10c=_10a[i];var _10d=config.macros.intelliTagger.subhandlers[_10c];if(!_10d){abego.alertAndThrow("Unsupported action '%0'".format([_10c]));}_10d(_103,_104,_105,_106,_107,_108);}},subhandlers:{showTags:function(_10e,_10f,_110,_111,_112,_113){_b4(_10e,_74,_76?_76.length:0,_76,abego.IntelliTagger.getSuggestionTagsMaxCount());},showFavorites:function(_114,_115,_116,_117,_118,_119){_b4(_114,_76,0);},closeButton:function(_11a,_11b,_11c,_11d,_11e,_11f){var _120=createTiddlyButton(_11a,"close","Close the suggestions",abego.IntelliTagger.close);},version:function(_121){var t="IntelliTagger %0.%1.%2".format([version.extensions.IntelliTaggerPlugin.major,version.extensions.IntelliTaggerPlugin.minor,version.extensions.IntelliTaggerPlugin.revision]);var e=createTiddlyElement(_121,"a");e.setAttribute("href","http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin");e.innerHTML="<font color=\"black\" face=\"Arial, Helvetica, sans-serif\">"+t+"<font>";},copyright:function(_124){var e=createTiddlyElement(_124,"a");e.setAttribute("href","http://tiddlywiki.abego-software.de");e.innerHTML="<font color=\"black\" face=\"Arial, Helvetica, sans-serif\">&copy; 2006-2007 <b><font color=\"red\">abego</font></b> Software<font>";}}};})();config.shadowTiddlers["IntelliTaggerStyleSheet"]="/***\n"+"!~IntelliTagger Stylesheet\n"+"***/\n"+"/*{{{*/\n"+".intelliTaggerSuggestions {\n"+"\tposition: absolute;\n"+"\twidth: 600px;\n"+"\n"+"\tpadding: 2px;\n"+"\tlist-style: none;\n"+"\tmargin: 0;\n"+"\n"+"\tbackground: #eeeeee;\n"+"\tborder: 1px solid DarkGray;\n"+"}\n"+"\n"+".intelliTaggerSuggestions .currentTag   {\n"+"\tfont-weight: bold;\n"+"}\n"+"\n"+".intelliTaggerSuggestions .suggestionNumber {\n"+"\tcolor: #808080;\n"+"}\n"+"\n"+".intelliTaggerSuggestions .numberedSuggestion{\n"+"\twhite-space: nowrap;\n"+"}\n"+"\n"+".intelliTaggerSuggestions .intelliTaggerFooter {\n"+"\tmargin-top: 4px;\n"+"\tborder-top-width: thin;\n"+"\tborder-top-style: solid;\n"+"\tborder-top-color: #999999;\n"+"}\n"+".intelliTaggerSuggestions .favorites {\n"+"\tborder-bottom-width: thin;\n"+"\tborder-bottom-style: solid;\n"+"\tborder-bottom-color: #999999;\n"+"\tpadding-bottom: 2px;\n"+"}\n"+"\n"+".intelliTaggerSuggestions .normalTags {\n"+"\tpadding-top: 2px;\n"+"}\n"+"\n"+".intelliTaggerSuggestions .intelliTaggerFooter .button {\n"+"\tfont-size: 10px;\n"+"\n"+"\tpadding-left: 0.3em;\n"+"\tpadding-right: 0.3em;\n"+"}\n"+"\n"+"/*}}}*/\n";config.shadowTiddlers["IntelliTaggerMainTemplate"]="<!--\n"+"{{{\n"+"-->\n"+"<div class=\"favorites\" macro=\"intelliTagger action: showFavorites\"></div>\n"+"<div class=\"normalTags\" macro=\"intelliTagger action: showTags\"></div>\n"+"<!-- The Footer (with the Navigation) ============================================ -->\n"+"<table class=\"intelliTaggerFooter\" border=\"0\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\"><tbody>\n"+"  <tr>\n"+"\t<td align=\"left\">\n"+"\t\t<span macro=\"intelliTagger action: closeButton\"></span>\n"+"\t</td>\n"+"\t<td align=\"right\">\n"+"\t\t<span macro=\"intelliTagger action: version\"></span>, <span macro=\"intelliTagger action: copyright \"></span>\n"+"\t</td>\n"+"  </tr>\n"+"</tbody></table>\n"+"<!--\n"+"}}}\n"+"-->\n";config.shadowTiddlers["IntelliTaggerEditTagsTemplate"]="<!--\n"+"{{{\n"+"-->\n"+"<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler'></div>\n"+"<div class='title' macro='view title'></div>\n"+"<div class='tagged' macro='tags'></div>\n"+"<div class='viewer' macro='view text wikified'></div>\n"+"<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler'></div>\n"+"<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>\n"+"<!--\n"+"}}}\n"+"-->\n";config.shadowTiddlers["BSD open source license (abego Software)"]="See [[Licence|http://tiddlywiki.abego-software.de/#%5B%5BBSD%20open%20source%20license%5D%5D]].";config.shadowTiddlers["IntelliTaggerPlugin Documentation"]="[[Documentation on abego Software website|http://tiddlywiki.abego-software.de/doc/IntelliTagger.pdf]].";config.shadowTiddlers["IntelliTaggerPlugin SourceCode"]="[[Plugin source code on abego Software website|http://tiddlywiki.abego-software.de/archive/IntelliTaggerPlugin/Plugin-IntelliTagger-src.1.0.2.js]]\n";(function(){var _126=restart;restart=function(){setStylesheet(store.getTiddlerText("IntelliTaggerStyleSheet"),"IntelliTaggerStyleSheet");_126.apply(this,arguments);};})();}
// %/
/***
|''Name:''|IntelliTagsEditCommandPlugin|
|''Version:''|1.0.0 (2007-10-03)|
|''Type:''|plugin|
|''Description:''|A command for your tiddler's toolbar to directly edit the tiddler's tags using the IntelliTaggerPlugin, without switching to "edit mode".|
|''Source:''|http://tiddlywiki.abego-software.de/#IntelliTagsEditCommandPlugin|
|''Requires:''|IntelliTaggerPlugin http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin|
|''Author:''|Udo Borkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license (abego Software)]]|
|''~CoreVersion:''|2.0.8|
|''Browser:''|Firefox 1.5.0.2 or better|
***/
/***
!Using the "IntelliTagsEditCommandPlugin"
Add the command {{{intelliTagsEdit}}} into the 'macro' attribute of the 'toolbar' {{{<div...>}}} in your ViewTemplate.

''Example:''
{{{
<div class='toolbar' 
        macro='toolbar -closeTiddler closeOthers +editTiddler intelliTagsEdit permalink references jump'>
</div>
}}}

This adds a "tags" button to the toolbar of the tiddlers (next to the ''edit'' button). Pressing the "tags" button will open the input field for the tiddler's tags and let you edit the tags with all the [[IntelliTaggerPlugin|http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin]] features.
***/
/***
!Source Code
***/
//{{{
(function(){

if (!version.extensions.IntelliTaggerPlugin)
    throw Error("IntelliTagsEditCommandPlugin requires the IntelliTaggerPlugin (http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin)");

if (config.commands.intelliTagsEdit) 
    return;

config.commands.intelliTagsEdit = {
	text: "tags",
	tooltip: "edit the tags"
};

config.commands.intelliTagsEdit.handler = function(event,src,title) {
	var button = abego.IntelliTagger.createEditTagsButton(title, null, "tags", "edit the tags");
	button.onclick(event);
	return false;
};

})();
//}}}

同機房,不同硬體,但是都安裝Ubuntu 9.10。如果想要讓帳號資料、Apache2、Bind 9設定檔,以及MySQL等,都能做到備援,請問如何設定?

回答 1 :
同機房,不同硬體,但是都安裝Ubuntu 9.10。如果想要讓帳號資料、Apache2、Bind 9設定檔,以及MySQL等,都能做到備援,請問讓如何設定? 

回答 2:
你可以搜尋有關Linux HA軟體,應該可以找到一些可用的資訊。不過沒有Shared Storage可以用,會比較麻煩。你需要做到MySQL Replication將資料庫抄寫到另一臺主機。至於Apache、Bind等設定檔,直接複製一份過去就好了,畢竟變動不大。一般來說,要做HA最少需要兩臺設備。 

回答 3:
資料庫可以使用兩種方法達到異機備援的目的,我拿MySQL 5.4版來說明:

1. 使用mysqldump:mysqldump可以把資料庫備份到另一臺機器上。但是當上線的資料庫伺服器當掉時,必須要重新安裝伺服器,然後由dump檔案回存資料庫。你可以參考MySQL提供的備份策略。

2. 使用Replication:這種方式可以把上線中的資料庫伺服器,直接備援到另一臺主機。當上線的資料庫伺服器掛掉時,就能自動切換過來支援。由於設置方法較複雜,要研究一下MySQL文件的做法再去測試。

我是兩種方法都會用,用Replication來做異機線上備援,再用mysqldump定期備下來,將備份放到別的地方存好,有備無患。 
駭客入侵後修改SSH連線後的相關設定,並埋入一個木馬程式到系統開機啟動程式中。不過由於Linux創始人Linus Torvalds發明一套GIT版本管理系統,當有人在正式發行後修改程式碼內容,很容易因為SHA-1雜湊函數值不符而被發現。

Linux核心開發團隊周三(8/31)在官方網站公布一則消息,表示該團隊在8/28發現駭客入侵,該名駭客取得網站最高權限root,並埋入一個木馬。

Linux核心開發團隊懷疑駭客竊取認證進入系統,再使用rootkit工具取得root權限,但截至目前為止還不清楚其手法。駭客入侵後修改SSH連線後的相關設定,並埋入一個木馬程式到系統開機啟動程式中。

該團隊發現Linux核心3.1 - RC2版有問題,但不確定與入侵有關。目前他們已經要求448位Linux核心系統開發人員變更密碼及SSH連線加密金鑰,並通知美國及歐洲執法單位。Linux核心團隊重新安裝新的伺服器,逐一審核網站資安政策,以避免事件重演。

在Linux核心程式原始碼方面,由於Linux創始人Linus Torvalds發明一套GIT版本管理系統,核心程式四萬多個檔案均有對應的加密SHA-1雜湊函數值,當有人在正式發行後修改程式碼內容,很容易因為SHA-1雜湊函數值不符而被發現。

不過並非所有的使用者均透過GIT系統取得這些原始碼。許多開放源碼網站均將軟體打包成Tar壓縮檔或安裝檔,僅能檢查PGP簽名是否正確,而Linux核心團隊並未針對Tar檔及修補程式是否遭竄改提出說明。

Linux自創始人Linus Torvalds公布以來,已經在8月25日度過20週年慶,此次入侵事件可以說是駭客送給Linux最尷尬的生日禮物。自去年底以來,已經有GNU Savannah、Fedora、Apache等開放源碼專案網站遭駭客入侵。(編譯/沈經) 
/***
|Name|LoadTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#LoadTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#LoadTiddlersPluginInfo|
|Version|3.6.2|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Options|##Configuration|
|Description|macro for automated updates or one-click installations of tiddlers from remote sources|
***/
//{{{
version.extensions.loadTiddlers = {major: 3, minor: 6, revision: 2, date: new Date(2008,8,5)};

config.macros.loadTiddlers = {
	label: "",
	tip: "add/update tiddlers from '%0'",
	lockedTag: "noReload",	// if existing tiddler has this tag value, don't overwrite it, even if inbound tiddler is newer
	askMsg: "Please enter a local path/filename or a remote URL",
	openMsg: "Opening %0",
	openErrMsg: "Could not open %0 - error=%1",
	readMsg: "Read %0 bytes from %1",
	foundMsg: "Found %0 tiddlers in %1",
	nochangeMsg: "'%0' is up-to-date... skipped.",
	lockedMsg: "'%0' is tagged '%1'... skipped.",
	skippedMsg: "skipped (cancelled by user)",
	loadedMsg: "Loaded %0 of %1 tiddlers from %2",
	reportTitle: "ImportedTiddlers",
	warning: "Warning!!  Processing '%0' as a systemConfig (plugin) tiddler may produce unexpected results! Are you sure you want to proceed?",
	handler: function(place,macroName,params) {
		var label=(params[0] && params[0].substr(0,6)=='label:')?params.shift().substr(6):this.label;
		var tip=(params[0] && params[0].substr(0,7)=='prompt:')?params.shift().substr(7):this.tip;
		var filter="updates";
		if (params[0] && (params[0]=='all' || params[0]=='new' || params[0]=='changes' || params[0]=='updates'
			|| params[0].substr(0,8)=='tiddler:' || params[0].substr(0,4)=='tag:'))
			filter=params.shift();
		var src=params.shift(); if (!src || !src.length) return; // filename is required
		var quiet=(params[0]=="quiet"); if (quiet) params.shift();
		var ask=(params[0]=="confirm"); if (ask) params.shift();
		var force=(params[0]=="force"); if (force) params.shift();
		var init=(params[0]=="init"); if (init) params.shift();
		var noreport=(params[0]=="noreport"); if (noreport) params.shift();
		this.newTags=[]; if (params[0]) this.newTags=params; // any remaining params are used as "autotags"
		if (label.trim().length) {
			// link triggers load tiddlers from another file/URL and then applies filtering rules to add/replace tiddlers in the store
			createTiddlyButton(place,label.format([src.replace(/%20/g," ")]),tip.format([src.replace(/%20/g," ")]), function() {
				if (src=="ask") src=prompt(this.askMsg);
				config.macros.loadTiddlers.loadFile(src,config.macros.loadTiddlers.doImport,{quiet:quiet,ask:ask,filter:filter,force:force,init:init,noreport:noreport});
			})
		}
		else {
			// load tiddlers from another file/URL and then apply filtering rules to add/replace tiddlers in the store
			if (src=="ask") src=prompt(this.askMsg);
			config.macros.loadTiddlers.loadFile(src,config.macros.loadTiddlers.doImport,{quiet:quiet,ask:ask,filter:filter,force:force,init:init,noreport:noreport});
		}
	},
	loadFile: function(src,callback,params) {
		var quiet=params.quiet;
		if (src==undefined || !src.length) return null; // filename is required
		if (!quiet) clearMessage();
		if (!quiet) displayMessage(this.openMsg.format([src.replace(/%20/g," ")]));
		if (src.substr(0,5)!="http:" && src.substr(0,5)!="file:") { // if not a URL, read from local filesystem
			var txt=loadFile(src);
			if (!txt) { // file didn't load, might be relative path.. try fixup
				var pathPrefix=document.location.href;  // get current document path and trim off filename
				var slashpos=pathPrefix.lastIndexOf("/"); if (slashpos==-1) slashpos=pathPrefix.lastIndexOf("\\"); 
				if (slashpos!=-1 && slashpos!=pathPrefix.length-1) pathPrefix=pathPrefix.substr(0,slashpos+1);
				src=pathPrefix+src;
				if (pathPrefix.substr(0,5)!="http:") src=getLocalPath(src);
				var txt=loadFile(src);
			}
			if (!txt) { // file still didn't load, report error
				if (!quiet) displayMessage(this.openErrMsg.format([src.replace(/%20/g," "),"(unknown)"]));
			} else {
				if (!quiet) displayMessage(this.readMsg.format([txt.length,src.replace(/%20/g," ")]));
				if (callback) callback(true,params,convertUTF8ToUnicode(txt),src,null);
			}
		} else {
			var name=config.options.txtRemoteUsername; var pass=config.options.txtRemotePassword;
			var x=doHttp("GET",src,null,null,name,pass,callback,params,null);
		}
	},
	readTiddlersFromHTML: function(html) {
		// for TW2.2+
		if (TiddlyWiki.prototype.importTiddlyWiki!=undefined) {
			var remoteStore=new TiddlyWiki();
			remoteStore.importTiddlyWiki(html);
			return remoteStore.getTiddlers("title");	
		}
	},
	doImport: function(status,params,html,src,xhr) {
		var quiet=params.quiet;
		var ask=params.ask;
		var filter=params.filter;
		var force=params.force;
		var init=params.init;
		var noreport=params.noreport;
		var tiddlers = config.macros.loadTiddlers.readTiddlersFromHTML(html);
		var count=tiddlers?tiddlers.length:0;
		var querypos=src.lastIndexOf("?"); if (querypos!=-1) src=src.substr(0,querypos);
		if (!quiet) displayMessage(config.macros.loadTiddlers.foundMsg.format([count,src.replace(/%20/g," ")]));
		store.suspendNotifications();
		var count=0;
		if (tiddlers) for (var t=0;t<tiddlers.length;t++) {
			var inbound = tiddlers[t];
			var theExisting = store.getTiddler(inbound.title);
			if (inbound.title==config.macros.loadTiddlers.reportTitle)
				continue; // skip "ImportedTiddlers" history from the other document...
			if (theExisting && theExisting.tags.contains(config.macros.loadTiddlers.lockedTag)) {
				if (!quiet) displayMessage(config.macros.loadTiddlers.lockedMsg.format([theExisting.title,config.macros.loadTiddlers.lockedTag]));
				continue; // skip existing tiddler if tagged with 'noReload'
			}
			// apply the all/new/changes/updates filter (if any)
			if (filter && filter!="all") {
				if ((filter=="new") && theExisting) // skip existing tiddlers
					continue;
				if ((filter=="changes") && !theExisting) // skip new tiddlers
					continue;
				if ((filter.substr(0,4)=="tag:") && inbound.tags.indexOf(filter.substr(4))==-1) // must match specific tag value
					continue;
				if ((filter.substr(0,8)=="tiddler:") && inbound.title!=filter.substr(8)) // must match specific tiddler name
					continue;
				if (!force && store.tiddlerExists(inbound.title) && ((theExisting.modified.getTime()-inbound.modified.getTime())>=0))
					{ if (!quiet) displayMessage(config.macros.loadTiddlers.nochangeMsg.format([inbound.title])); continue; }
			}
			// get confirmation if required
			if (ask && !confirm((theExisting?"Update":"Add")+" tiddler '"+inbound.title+"'\nfrom "+src.replace(/%20/g," ")+"\n\nOK to proceed?"))
				{ tiddlers[t].status=config.macros.loadTiddlers.skippedMsg; continue; }
			// DO IT!
			var tags=Array.concat(inbound.tags,config.macros.loadTiddlers.newTags);
	                store.saveTiddler(inbound.title, inbound.title, inbound.text, inbound.modifier, inbound.modified, tags, inbound.fields, true, inbound.created);
	                store.fetchTiddler(inbound.title).created = inbound.created; // force creation date to imported value - needed for TW2.1.3 or earlier
			tiddlers[t].status=theExisting?"updated":"added"
			if (init && tags.contains("systemConfig") && !tags.contains("systemConfigDisable")) {
				var ok=true;
				if (ask||!quiet) ok=confirm(config.macros.loadTiddlers.warning.format([inbound.title]))
				if (ok) { // run the plugin
					try { window.eval(inbound); tiddlers[t].status+=" (plugin initialized)"; }
					catch(ex) { displayMessage(config.messages.pluginError.format([exceptionText(ex)])); }
				}
			}
			count++;
		}
		store.resumeNotifications();
		if (count) {
			// refresh display
			store.setDirty(true); store.notifyAll();
			// generate a report
			if (!noreport) config.macros.loadTiddlers.report(src,tiddlers,count,quiet);
		}
		// always show final message when tiddlers were actually loaded
		if (!quiet||count) displayMessage(config.macros.loadTiddlers.loadedMsg.format([count,tiddlers.length,src.replace(/%20/g," ")]));
	},
	report: function(src,tiddlers,count,quiet) {
		// format the new report content
		var newText = "On "+(new Date()).toLocaleString()+", ";
		newText += config.options.txtUserName+" loaded "+count+" tiddlers ";
		newText += "from\n[["+src+"|"+src+"]]:\n";
		newText += "<<<\n";
		for (var t=0; t<tiddlers.length; t++)
			if (tiddlers[t].status)
				newText += "#[["+tiddlers[t].title+"]] - "+tiddlers[t].status+"\n";
		newText += "<<<\n";
		// get current report (if any)
		var title=config.macros.loadTiddlers.reportTitle;
		var currText="";
		var theReport = store.getTiddler(title);
		if (theReport) currText=((theReport.text!="")?'\n----\n':"")+theReport.text;
		// update the ImportedTiddlers content and show the tiddler
		store.saveTiddler(title, title, newText+currText, config.options.txtUserName, new Date(), theReport?theReport.tags:null, theReport?theReport.fields:null);
		if (!quiet) { story.displayTiddler(null,title,1,null,null,false); story.refreshTiddler(title,1,true); }
	}
}
//}}}
本文網址 : http://www.zdnet.com.tw/enterprise/blog/0,2000085759,20146760,00.htm

MIS算是一份可大可小的工作,大可以大到一人之下,很多人之上,小的話...,應該連工讀生都可以把你使喚來、使喚去。當然,我們不能用這樣子來評斷一個工作的優劣,畢竟每種工作都有它的專精之處,以及它應該受到的尊重,只是像MIS這種衝突性很高的工作,應該也不是多數。畢竟一般的工作場合,經常是「以時間論英雄、用職稱論成敗...」。但是MIS經常得採取縱向的模式才能工作,因此,除非是人力及階層相當分明的大型公司,我想一般人力吃緊的中、小企業,MIS應該都得兼顧校長、工友兼撞鐘的多重身分。

但是,也因為如此,其實很多事情MIS看見的角度跟作為,卻也是其它人不一定能夠涉獵的範圍。或者說,其它人就算可以理解,也不見得就一定能在該層面施上力,有時候就是這份工作的獨特性,甚至可以說是另外一種的優越感,不過,也很容易被視為階段性任務的絕佳代言人,至於每個人對於階段性任務的定位也略有不同,是否能夠被自己所接受,當然也就決定著未來的出路與走向。

MIS的立場險峻

其實MIS的立場,主要也是與時間有很密切的關係,因為經過了幾年的努力之後,至少Routine的工作都已經有了一定的流程,這時候對於老闆來說,MIS很容易就被視為"閒置人力",或許這麼被看待是一件不太公平的事,因為MIS「看」起來沒事,並不代表他們就沒有為公司付出,但是對於老闆或主管的觀感來說,這卻又是另外一個層面的思考。

同時也千萬不要成為"裝忙"的人,畢竟那就等於是拿自己的職場生涯和學習心態當賭注,雖然職場上有很多時候裝忙是劑良藥,尤其是對體質特異的公司來說,但是,一旦自己開始陷入選擇性裝忙的輪迴之後,漸漸地就會下意識的避開挑戰,這對於職場上的生涯規畫著實不是件好事,這時候我們可以看看某些身居特定職位者,是否就有這樣子的病症存在,同時也只要觀察一下它周遭的部屬,也能夠很快地瞭解到他的用人處事之道,或許「吃虧就是佔便宜」,在自己還能夠負載的工作量之下,其實是句蠻貼切的話,當然也得要量力而為,否則也會陷入多做多錯的窘境當中。

說了這麼多,其實對MIS來說,在很多公司裡的組織圖中,它通常都是直接隸屬於總經理(董事長)之下,重點是要能夠快速且正確地提供,他們想要的任何一種數據與資料(MIS有權限可觸及的部分),有時看起來會很像是主官的左、右手或特助,因此,很多時候都要習慣用他們的角度去看待問題,而不是用一個員工的角色來看待問題本身,不然就會發生言不及義,或者是做了一堆虛功...,這會讓老闆痛苦也會讓自己難過。

所以MIS最常要學習的心態,就是用老闆的角度看待問題,這一點其實跟主管很像,但是在執行的層面上還是有所差別,有時還是要限縮自己的觸角,以免誤傷它人甚至是惹禍上身(畢竟暗箭難防),縱使老闆有給予足夠的授權,但是在跨部門、牽涉人員愈多、階層愈高,MIS就得愈要小心,還得視平日累積的「經驗」來判斷該怎麼做,才有辦法完成上面所交待的任務。

MIS的處置手腕
以公司內部來說,我想除了打掃的阿桑之外,最圓融、最常在大家身旁奔走的人,一定少不了「MIS」,因為他通常都得要火裡來、水裡去,那邊需要救火就往那邊去,所以對於MIS來說,對於每個人的處事原則,或多或少都有一定程度的瞭解,知道對那些人應該強硬,那些人適合委婉,這一點在處理上面交辦事務的時候,絕對可以派上用場。

當然也是有冷面的MIS存在,通常都是讓人敬畏三分,非到必要絕不找他上門的隱藏人物,雖然這種型態的MIS也能處置好某些事務(尤其是要硬派作風才能夠推行的事),但是,對於要處理更細膩與人互動的問題時,這類MIS就會相當為難,畢竟他對於其它同儕的心性,瞭解的並不夠深,很容易就會弄巧成拙或是把自己搞的焦頭爛額。

除此之外,MIS應該採用的處置方式,除了考量人性之外,最好在資訊專業上也要有所堅持,千萬不要因為使用者的諸多要求而自亂陣腳,很多時候使用者的習慣並不代表唯一途徑,有時他們的做法不太合乎邏輯(延用舊法),這時候最好的方式就是以身作則,自己實際去體驗一次他們的做法,再跟自己所設想的方式來比較,如果能夠為他們來爭取到更多的休息時間,我想對於使用者來說,也就會有更多的誘因,千萬不要一昧的為改變而改變,因為有時他們看見的點,遠比我們這些臨危受命的空降部隊來的精闢。

雖然事必躬親不是一件完全正確的事,但是對於很多基層員工來說,那是一種最能夠讓他們信服的方式,同時也可以跟他們心中對那種愛唱高調的主管的區隔,也不妨是一種好的問題解決方式,只不過使用的時機得要經過評估,畢竟還是有時效壓力存在。

結論

從上述看來,MIS的立場與處置其實跟主管很類似,只不過它卻是最直接的執行者,他並不像很多主管,下面還有很多人可以使喚,因此,自己得要面對很多心態上的調整跟轉換,同時還要考量自己對於時間分配的功力,因為MIS同時還要處理自己手邊的庶務,畢竟MIS手上東西之雜,早已經是眾所皆知。

其實我只是想要突顯每個IT工作者,很有可能會因為自己的立場而有不同的處置方式,像程式開發者可能會因為自己的立場,忽略了使用者體驗所產生的負面影響;專案經理會因為自己的高度,忘記下面新鮮肝的戰力還有多少?

有時候置身處地的去"思考",或許能夠得到更多不一樣的腦內革命,縱使不一定得要親力親為,但是在立場跟處置方式之間,應該不僅只有一種方式,有時候繞個圈反而能夠走得比較遠,端看你是想要比氣長,還是想要搶時機,有時也可看出你的工作哲學及生涯規畫,並非每件事都非黑即白,有時多點不一樣的光彩,或許能有無限的可能,只是差在一念之間。 

<<tagsTree twcms "" 1 4 index label>>
<<tagsTree lns01 "" 1 4 index label>>
<<tagsTree lns02 "" 1 4 index label>>
<<tagsTree lns03 "" 1 4 index label>>
<<tagsTree lns04 "" 1 4 index label>>
<<tagsTree lns05 "" 1 4 index label>>
<<tagsTree lns06 "" 1 4 index label>>
<<tagsTree lns07 "" 1 4 index label>>
<<tagsTree lns08 "" 1 4 index label>>
<<tagsTree lns09 "" 1 4 index label>>
<<tagsTree KMKConfig "" 1 4 index label>>
<!--{{{-->
<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml'/>
<!--}}}-->

<!--{{{-->
<style type="text/css">
#contentWrapper {display:none;}
</style>

<div id="SplashScreen" style="border: 3px solid #ccc; display: block; text-align: center; width: 320px; margin: 100px auto; padding: 50px; color:#000; font-size: 28px; font-family:Tahoma; background-color:#eee;">
<b>toBala KM King</b><br><br><img src="loader.gif"><br>
<span style="font-size: 14px; color:red;">Requires Javascript.</span>
</div>
<!--}}}-->
本文網址 : http://www.zdnet.com.tw/news/software/0,2000085678,20145168,00.htm

McAfee暢銷的防毒軟體21日闖出大禍,造成數十萬台Windows XP電腦當機或不斷重開機。

該公司當日上午發佈的一次有問題的更新,讓該軟體強大的防惡意軟體機制搞錯防禦方向,轉而攻擊一項重要的Windows元件。

這次更新在傳送給企業顧客4小時後緊急中止,但已造成大規模的傷害:密西根大學醫學院的2.5萬台電腦中,有8,000台當機。肯塔基州萊辛頓市警局必須改用手寫報告,並關閉巡邏車的總機。若干監獄取消探視,羅德島各醫院的急診室也暫時拒收非創傷病患,並延後部分外科手術。

英特爾也無法倖免。該公司內部的消息人士證實,英特爾在美國境內使用McAfee的所有電腦,和許多其他主機都受到影響,但不確定是否衝擊到工廠生產。

有問題的更新是在美西時間早上6點發佈(台灣時間21日晚間9點),造成PC的免疫系統轉向,進而攻擊合法的作業系統元件SVCHOST.EXE。這種情形就像人類的免疫系統轉而傷害人體本身的健康。這次的事件中,McAfee的防毒軟體將Windows元件誤認為W32/Wecorl.a病毒。

受害的主要是使用微軟Windows XP Service Pack 3的電腦。McAfee在當天下午2點(台灣時間今日凌晨5點)發出聲明向顧客道歉,但刻意淡化衝擊:「我們尚未發現消費者部分有受到顯著的影響。」

一紙聲明無法澆熄企業顧客的怒火,尤其是必須親自到每一台電腦,手動安裝補救程式的系統管理員。目前還不清楚受影響的顧客數量,McAfee的代表也說,她沒有最新的資料。

科技相關的郵寄名單很快被讀者的抱怨淹沒,透過Twitter發出的譴責多不勝數。華府特區副資訊長Sonny Hashmi稱此為「大崩潰」,並說McAfee已被列入他的「黑名單」。一位舊金山的工程師說,多謝McAfee「我的待辦工作量累積到兩天以上…」其他人也抱怨,問題發生後6個小時,McAfee的首頁仍未貼出公告,虧他們還自稱為「增強您網路安全的科技」。

CNET News一位波特蘭編輯,在21日上午開機後便無法連線,McAfee的更新讓她無法啟動或移除任何東西。

Internet Storm Center報導,有問題的McAfee更新將Windows檔案svchost.exe視為病毒。McAfee最初建議使用者到其支援網站下載一個檔案,這或許是這次大混亂的元兇。但數萬名憤怒的使用者湧入該論壇後,那個網站現已關閉。

McAfee已在另一個網站上,公佈如何處理相關問題的詳細步驟。該公司建議手動下載和安裝一個"EXTRA.DAT"檔,然後恢復之前被錯誤隔離的檔案。但這些步驟需要一定程度的技術能力,而直到21日下午4點(今日上午7點),McAfee仍未提出更好的方法。網頁上的公告寫道:「McAfee仍在持續研究自動的解決方案。」(陳智文/譯)
這些設定將暫存於瀏覽器
請簽名<<option txtUserName>>
 (範例:WikiWord)

 <<option chkSaveBackups>> 儲存備份
 <<option chkAutoSave>> 自動儲存
 <<option chkRegExpSearch>> 正規式搜尋
 <<option chkCaseSensitiveSearch>> 區分大小寫搜尋
 <<option chkAnimate>> 使用動畫顯示
----
 [[進階選項|AdvancedOptions]]
本文網址 : http://www.ithome.com.tw/itadm/article.php?c=60814

文/吳其勳 (iThome電腦報副總編輯) 2010-04-26 	

它不是軟體漏洞,並非靠軟體廠商修補好漏洞即可,而且整個作法又屬於合法行為,讓資安軟體難以分辨

前兩個禮拜,陸續有國外資安研究人員指出PDF根本性的安全問題,並驗證了攻擊手法的可行性。由於這個攻擊手法並不是利用PDF Reader軟體的漏洞,而是利用PDF提供的合法指令,來啟動其他程式,使得這個問題相當棘手。而目前尚無有效防堵這種攻擊的方法,因此我們緊急利用本期封面故事報導這個問題,希望使用者在開啟PDF文件檔時能多加注意。

在3月底時,資安研究員Dider Stevens指出,只要利用PDF檔案的「/Launch」指令,就能讓PDF檔案去啟動其他程式,他表示,再搭配社交工程手法,在PDF檔案開啟時同步跳出一個對話框,欺騙使用者按下對話框中的按鈕,就能夠啟動其他程式。他並且提供了一個示範檔案,證實開啟該PDF檔案之後,使用者一按下對話框的確認按鈕,就會如他所說地執行cmd.exe檔。

緊接著在4月1日,另一位資安研究員Jeremy Conway則再進一步證實此法不僅可發展為攻擊模式,並可藉由惡意的PDF檔案去感染一般正常的PDF檔案。

從Conway錄下來的程式執行過程來看,他準備了兩個PDF檔案,其中一個已經被動過了手腳,另一個則是一般正常的PDF檔。首先,他先開啟正常的 PDF檔案,確認了PDF Reader閱讀軟體已經關閉JavaScript功能。(一般會建議關閉JavaScript功能,也是為了避免有心人士利用JavaScript,在背景中下載安裝惡意程式。)接著,他開啟被動了手腳的惡意PDF檔,然後再開啟原本是正常的PDF檔,結果這個檔案一開啟之後,就又跳出了瀏覽器視窗,而且自動連結到一個特定的網站。

Jeremy Conway這個概念驗證指出,透過「/Launch」指令、OpenAction功能以及社交工程手法,他可以利用一個被動了手腳的PDF檔案,去改寫另一個PDF檔案,讓這個檔案被開啟時,自動去呼叫瀏覽器,並連結到一個惡意網站、下載惡意程式。而這一切所利用到的,都是PDF允許的合法指令。

其中,如何讓惡意的PDF檔案去感染正常的PDF檔案,Conway並沒有公布,因此尚無法得知這種感染的做法,是需要先知道被攻擊目標檔案的所在位置,還是它能夠自動搜尋所有的PDF檔案。

不過,就在Conway公布這個手法可行的兩個禮拜之後,就有網友在他的網站上指出,目前已經有人發展出模仿這個手法的套裝工具了。由於這個問題是PDF 的根本性問題,除非是完全切除這些指令的功用,不然這種運用合法指令的攻擊手法是最難預防的。因為,它不是軟體漏洞,並非靠軟體廠商修補好漏洞即可,而且整個作法又屬於合法行為,讓資安軟體難以分辨。因此不論是否有人已經發展出成套的攻擊工具,這個問題都非常難處理,需要高度重視。

雖然Adobe在4月13日發布了Adobe Reader新的修補檔,一次補強了好幾個軟體上的安全漏洞,不過都不是針對這個問題。所以,對於企業而言,PDF這個根本性的安全問題仍是一大威脅,因為現今的企業使用PDF檔案的情形很頻繁,因而這樣的攻擊手法能成功的機會很高。

由於目前尚無有效的防堵方法,企業能做的是及早意識到這個問題,並且開始對員工宣導相關的知識,讓他們在開啟PDF檔案時能提高警覺,知道對話框的按鈕所潛在的危險,先透過這樣的預防宣導來降低風險。
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>

<div id='toolBar' refresh='content' force='true' tiddler='toBalaToolBar'></div>
<div id='mainMenu' refresh='content' force='true' tiddler='MainMenu'></div>

<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlersBar' refresh='none' ondblclick='config.macros.tiddlersBar.onTiddlersBarAction(event)'></div>
<div id='tiddlerDisplay'></div>
</div>

<iframe id='ApplicationArea' width='100%' height='100%'></iframe>
<!--}}}-->
//{{{
//============================================================================
//                           PartTiddlerPlugin

// Ensure that the PartTiddler Plugin is only installed once.
//
if (!version.extensions.PartTiddlerPlugin) {

version.extensions.PartTiddlerPlugin = {
    major: 1, minor: 0, revision: 9,
    date: new Date(2007, 6, 14), 
    type: 'plugin',
    source: "http://tiddlywiki.abego-software.de/#PartTiddlerPlugin"
};

if (!window.abego) window.abego = {};
if (version.major < 2) alertAndThrow("PartTiddlerPlugin requires TiddlyWiki 2.0 or newer.");

//============================================================================
// Common Helpers

// Looks for the next newline, starting at the index-th char of text. 
//
// If there are only whitespaces between index and the newline 
// the index behind the newline is returned, 
// otherwise (or when no newline is found) index is returned.
//
var skipEmptyEndOfLine = function(text, index) {
	var re = /(\n|[^\s])/g;
	re.lastIndex = index;
	var result = re.exec(text);
	return (result && text.charAt(result.index) == '\n') 
			? result.index+1
			: index;
}


//============================================================================
// Constants

var partEndOrStartTagRE = /(<\/part>)|(<part(?:\s+)((?:[^>])+)>)/mg;
var partEndTagREString = "<\\/part>";
var partEndTagString = "</part>";

//============================================================================
// Plugin Specific Helpers

// Parse the parameters inside a <part ...> tag and return the result.
//
// @return [may be null] {partName: ..., isHidden: ...}
//
var parseStartTagParams = function(paramText) {
	var params = paramText.readMacroParams();
	if (params.length == 0 || params[0].length == 0) return null;
	
	var name = params[0];
	var paramsIndex = 1;
	var hidden = false;
	if (paramsIndex < params.length) {
		hidden = params[paramsIndex] == "hidden";
		paramsIndex++;
	}
	
	return {
		partName: name, 
		isHidden: hidden
	};
}

// Returns the match to the next (end or start) part tag in the text, 
// starting the search at startIndex.
// 
// When no such tag is found null is returned, otherwise a "Match" is returned:
// [0]: full match
// [1]: matched "end" tag (or null when no end tag match)
// [2]: matched "start" tag (or null when no start tag match)
// [3]: content of start tag (or null if no start tag match)
//
var findNextPartEndOrStartTagMatch = function(text, startIndex) {
	var re = new RegExp(partEndOrStartTagRE);
	re.lastIndex = startIndex;
	var match = re.exec(text);
	return match;
}

//============================================================================
// Formatter

// Process the <part ...> ... </part> starting at (w.source, w.matchStart) for formatting.
//
// @return true if a complete part section (including the end tag) could be processed, false otherwise.
//
var handlePartSection = function(w) {
	var tagMatch = findNextPartEndOrStartTagMatch(w.source, w.matchStart);
	if (!tagMatch) return false;
	if (tagMatch.index != w.matchStart || !tagMatch[2]) return false;

	// Parse the start tag parameters
	var arguments = parseStartTagParams(tagMatch[3]);
	if (!arguments) return false;
	
	// Continue processing
	var startTagEndIndex = skipEmptyEndOfLine(w.source, tagMatch.index + tagMatch[0].length);
	var endMatch = findNextPartEndOrStartTagMatch(w.source, startTagEndIndex);
	if (endMatch && endMatch[1]) {
		if (!arguments.isHidden) {
			w.nextMatch = startTagEndIndex;
			w.subWikify(w.output,partEndTagREString);
		}
		w.nextMatch = skipEmptyEndOfLine(w.source, endMatch.index + endMatch[0].length);
		
		return true;
	}
	return false;
}

config.formatters.push( {
    name: "part",
    match: "<part\\s+[^>]+>",
	
	handler: function(w) {
		if (!handlePartSection(w)) {
			w.outputText(w.output,w.matchStart,w.matchStart+w.matchLength);
		}
	}
} )

//============================================================================
// Extend "fetchTiddler" functionality to also recognize "part"s of tiddlers 
// as tiddlers.

var currentParent = null; // used for the "." parent (e.g. in the "tiddler" macro)

// Return the match to the first <part ...> tag of the text that has the
// requrest partName.
//
// @return [may be null]
//
var findPartStartTagByName = function(text, partName) {
	var i = 0;
	
	while (true) {
		var tagMatch = findNextPartEndOrStartTagMatch(text, i);
		if (!tagMatch) return null;

		if (tagMatch[2]) {
			// Is start tag
	
			// Check the name
			var arguments = parseStartTagParams(tagMatch[3]);
			if (arguments && arguments.partName == partName) {
				return tagMatch;
			}
		}
		i = tagMatch.index+tagMatch[0].length;
	}
}

// Return the part "partName" of the given parentTiddler as a "readOnly" Tiddler 
// object, using fullName as the Tiddler's title. 
//
// All remaining properties of the new Tiddler (tags etc.) are inherited from 
// the parentTiddler.
// 
// @return [may be null]
//
var getPart = function(parentTiddler, partName, fullName) {
	var text = parentTiddler.text;
	var startTag = findPartStartTagByName(text, partName);
	if (!startTag) return null;
	
	var endIndexOfStartTag = skipEmptyEndOfLine(text, startTag.index+startTag[0].length);
	var indexOfEndTag = text.indexOf(partEndTagString, endIndexOfStartTag);

	if (indexOfEndTag >= 0) {
		var partTiddlerText = text.substring(endIndexOfStartTag,indexOfEndTag);
		var partTiddler = new Tiddler();
		partTiddler.set(
						fullName,
						partTiddlerText,
						parentTiddler.modifier,
						parentTiddler.modified,
						parentTiddler.tags,
						parentTiddler.created);
		partTiddler.abegoIsPartTiddler = true;
		return partTiddler;
	}
	
	return null;
}

// Hijack the store.fetchTiddler to recognize the "part" addresses.
//
var hijackFetchTiddler = function() {
	var oldFetchTiddler = store.fetchTiddler ;
	store.fetchTiddler = function(title) {
		var result = oldFetchTiddler.apply(this, arguments);
		if (!result && title) {
			var i = title.lastIndexOf('/');
			if (i > 0) {
				var parentName = title.substring(0, i);
				var partName = title.substring(i+1);
				var parent = (parentName == ".") 
						? store.resolveTiddler(currentParent)
						: oldFetchTiddler.apply(this, [parentName]);
				if (parent) {
					return getPart(parent, partName, parent.title+"/"+partName);
				}
			}
		}
		return result;	
	};
};

// for debugging the plugin is not loaded through the systemConfig mechanism but via a script tag. 
// At that point in the "store" is not yet defined. In that case hijackFetchTiddler through the restart function.
// Otherwise hijack now.
if (!store) {
	var oldRestartFunc = restart;
	window.restart = function() {
		hijackFetchTiddler();
		oldRestartFunc.apply(this,arguments);
	};
} else
	hijackFetchTiddler();




// The user must not edit a readOnly/partTiddler
//

config.commands.editTiddler.oldIsReadOnlyFunction = Tiddler.prototype.isReadOnly;

Tiddler.prototype.isReadOnly = function() {
	// Tiddler.isReadOnly was introduced with TW 2.0.6.
	// For older version we explicitly check the global readOnly flag
	if (config.commands.editTiddler.oldIsReadOnlyFunction) {
		if (config.commands.editTiddler.oldIsReadOnlyFunction.apply(this, arguments)) return true;
	} else {
		if (readOnly) return true;
	}

	return this.abegoIsPartTiddler;
}

config.commands.editTiddler.handler = function(event,src,title)
{
	var t = store.getTiddler(title);
	// Edit the tiddler if it either is not a tiddler (but a shadowTiddler)
	// or the tiddler is not readOnly
	if(!t || !t.abegoIsPartTiddler)
		{
		clearMessage();
		story.displayTiddler(null,title,DEFAULT_EDIT_TEMPLATE);
		story.focusTiddler(title,"text");
		return false;
		}
}

// To allow the "./partName" syntax in macros we need to hijack 
// the invokeMacro to define the "currentParent" while it is running.
// 
var oldInvokeMacro = window.invokeMacro;
function myInvokeMacro(place,macro,params,wikifier,tiddler) {
	var oldCurrentParent = currentParent;
	if (tiddler) currentParent = tiddler;
	try {
		oldInvokeMacro.apply(this, arguments);
	} finally {
		currentParent = oldCurrentParent;
	}
}
window.invokeMacro = myInvokeMacro;

// To correctly support the "./partName" syntax while refreshing we need to hijack 
// the config.refreshers.tiddlers to define the "currentParent" while it is running.
// 
(function() {
	var oldTiddlerRefresher= config.refreshers.tiddler;
	config.refreshers.tiddler = function(e,changeList) {
		var oldCurrentParent = currentParent;
		try {
			currentParent = e.getAttribute("tiddler");
			return oldTiddlerRefresher.apply(this,arguments);
		} finally {
			currentParent = oldCurrentParent;
		}
	};
})();

// Support "./partName" syntax inside <<tabs ...>> macro
(function() {
	var extendRelativeNames = function(e, title) {
		var nodes = e.getElementsByTagName("a");
		for(var i=0; i<nodes.length; i++) {
			var node = nodes[i];
			var s = node.getAttribute("content");
			if (s && s.indexOf("./") == 0)
				node.setAttribute("content",title+s.substr(1));
		}
	};
	var oldHandler = config.macros.tabs.handler;
	config.macros.tabs.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
		var result = oldHandler.apply(this,arguments);
		if (tiddler)
			extendRelativeNames(place, tiddler.title);
		return result;
	};
})();

// Scroll the anchor anchorName in the viewer of the given tiddler visible.
// When no tiddler is defined use the tiddler of the target given event is used.
window.scrollAnchorVisible = function(anchorName, tiddler, evt) {
	var tiddlerElem = null;
	if (tiddler) {
		tiddlerElem = document.getElementById(story.idPrefix + tiddler);
	}
	if (!tiddlerElem && evt) {
		var target = resolveTarget(evt);
		tiddlerElem = story.findContainingTiddler(target);
	}
	if (!tiddlerElem) return;

	var children = tiddlerElem.getElementsByTagName("a");
	for (var i = 0; i < children.length; i++) {
		var child = children[i];
		var name = child.getAttribute("name");
		if (name == anchorName) {
			var y = findPosY(child);
			window.scrollTo(0,y);
			return;
		}
	}
}

} // of "install only once"
//}}}

<<tabs txtMainTab "最近更新" "依更新日期排序" TabTimeline "分類" "所有標籤" TabTags "設定文章" "說所有設定文章" TabMoreShadowed>>
V1.2 (2011/06/22) 由土芭樂知識聯盟設計與維護
Linux 網路服務 - 學習筆記本
/***
|''Name:''|SparklinePlugin|
|''Description:''|Sparklines macro|
***/
//{{{
if(!version.extensions.SparklinePlugin) {
version.extensions.SparklinePlugin = {installed:true};

//--
//-- Sparklines
//--

config.macros.sparkline = {};
config.macros.sparkline.handler = function(place,macroName,params)
{
	var data = [];
	var min = 0;
	var max = 0;
	var v;
	for(var t=0; t<params.length; t++) {
		v = parseInt(params[t]);
		if(v < min)
			min = v;
		if(v > max)
			max = v;
		data.push(v);
	}
	if(data.length < 1)
		return;
	var box = createTiddlyElement(place,"span",null,"sparkline",String.fromCharCode(160));
	box.title = data.join(",");
	var w = box.offsetWidth;
	var h = box.offsetHeight;
	box.style.paddingRight = (data.length * 2 - w) + "px";
	box.style.position = "relative";
	for(var d=0; d<data.length; d++) {
		var tick = document.createElement("img");
		tick.border = 0;
		tick.className = "sparktick";
		tick.style.position = "absolute";
		tick.src = "data:image/gif,GIF89a%01%00%01%00%91%FF%00%FF%FF%FF%00%00%00%C0%C0%C0%00%00%00!%F9%04%01%00%00%02%00%2C%00%00%00%00%01%00%01%00%40%02%02T%01%00%3B";
		tick.style.left = d*2 + "px";
		tick.style.width = "2px";
		v = Math.floor(((data[d] - min)/(max-min)) * h);
		tick.style.top = (h-v) + "px";
		tick.style.height = v + "px";
		box.appendChild(tick);
	}
};


}
//}}}
/***

''Inspired by [[TiddlyPom|http://www.warwick.ac.uk/~tuspam/tiddlypom.html]]''

|Name|SplashScreenPlugin|
|Created by|SaqImtiaz|
|Location|http://tw.lewcid.org/#SplashScreenPlugin|
|Version|0.21 |
|Requires|~TW2.08+|
!Description:
Provides a simple splash screen that is visible while the TW is loading.

!Installation
Copy the source text of this tiddler to your TW in a new tiddler, tag it with systemConfig and save and reload. The SplashScreen will now be installed and will be visible the next time you reload your TW.

!Customizing
Once the SplashScreen has been installed and you have reloaded your TW, the splash screen html will be present in the MarkupPreHead tiddler. You can edit it and customize to your needs.

!History
* 20-07-06 : version 0.21, modified to hide contentWrapper while SplashScreen is displayed.
* 26-06-06 : version 0.2, first release

!Code
***/
//{{{
var old_lewcid_splash_restart=restart;

restart = function()
{   if (document.getElementById("SplashScreen"))
        document.getElementById("SplashScreen").style.display = "none";
      if (document.getElementById("contentWrapper"))
        document.getElementById("contentWrapper").style.display = "block";
    
    old_lewcid_splash_restart();
   
    if (splashScreenInstall)
       {if(config.options.chkAutoSave)
			{saveChanges();}
        displayMessage("TW SplashScreen has been installed, please save and refresh your TW.");
        }
}


var oldText = store.getTiddlerText("MarkupPreHead");
if (oldText.indexOf("SplashScreen")==-1)
   {var siteTitle = store.getTiddlerText("SiteTitle");
   var splasher='\n\n<style type="text/css">#contentWrapper {display:none;}</style><div id="SplashScreen" style="border: 3px solid #ccc; display: block; text-align: center; width: 320px; margin: 100px auto; padding: 50px; color:#000; font-size: 28px; font-family:Tahoma; background-color:#eee;"><b>'+siteTitle +'</b> is loading<blink> ...</blink><br><br><span style="font-size: 14px; color:red;">Requires Javascript.</span></div>';
   if (! store.tiddlerExists("MarkupPreHead"))
       {var myTiddler = store.createTiddler("MarkupPreHead");}
   else
      {var myTiddler = store.getTiddler("MarkupPreHead");}
      myTiddler.set(myTiddler.title,oldText+splasher,config.options.txtUserName,null,null);
      store.setDirty(true);
      var splashScreenInstall = true;
}
//}}}
/*{{{*/

/* 應用模式的樣式設定 */
#ApplicationArea {display:none;width:100px;height:100%;}


/* option 巨集文字欄位的長度 */
.txtOptionInput {width:40em;}


/* 主要項目樣式 

    在 Tiddler 中的使用格式如下 :
    {{item1{Item description}}}

*/
.item1{
 line-height:28px;
 font-weight:bold; 
 font-size:14px;
 border-left: 10px solid blue;
 margin:0px 0px 0px 0px;
 padding: 0px 0px 0px 3px;
 background-color:transparent;
}

/* 實作項目樣式 

    在 Tiddler 中的使用格式如下 :
    {{op1{operation description}}}

*/
.op1{
 line-height:28px;
 font-weight:bold; 
 font-size:14px;
 margin:0px 0px 0px 0px;
 padding: 0px 0px 0px 0px;
 background-color:transparent;
}


/*
Making preformated <pre> text wrap in CSS3, Mozilla, Opera and IE

word-wrap: break-word; - 視窗邊界換行,僅 IE 支援。也可以用 word-brak: break-all; 但不會保持英文單字的完整性。
white-space: pre; - 對某標籤作預先格式化,所有標準瀏覽器皆支援。
white-space: -moz-pre-wrap; - 預先格式化,但在元素邊界換行,僅 Mozilla (Firefox) 支援。
white-space: pre-wrap; - 預先格式化,但在元素邊界換行,僅 Opera 支援。
*/
.viewer pre {
  font-size:12px;
  white-space: pre-wrap;       /* css-3 */
  white-space: -moz-pre-wrap;  /* Mozilla, since 1999 */
  white-space: -pre-wrap;      /* Opera 4-6 */
  white-space: -o-pre-wrap;    /* Opera 7 */
  word-wrap: break-word;       /* Internet Explorer 5.5+ */
}
.viewer pre {border:1px solid [[ColorPalette::SecondaryLight]]; background:[[ColorPalette::SecondaryPale]];}


/*
無框線表格樣式設定, 以下是使用範例:

|!Col1|!Col2|!Col3|
|r1c1| r1r2c2 |r1c3|
|r2c1|~|r2c3|
|borderless|k    // 使用格式

*/
.borderless, .borderless table, .borderless td, .borderless tr, .borderless th, .borderless tbody { 
   border:0 !important; margin:0 !important; padding:2px !important; 
   td.vertical-align:top !important;margin-left: auto !important; 
   margin-right: auto !important;
}

.externalLink {text-decoration:none}

#toolBar { 
 background-color: #eee; 
 color:#ccc;
 width: auto;
 text-align:left;
 padding: 0.4em 0.6em 0.4em 0.6em;
}

h1,h2,h3 {padding-bottom:1px; margin-top:0.1em;margin-bottom:0.1em;}
h4,h5,h6 {margin-top:0.1em;}
h1 {font-size:1.2em;}
h2 {font-size:1.0em;}
h3 {font-size:1.0em;}
h4 {font-size:0.8em;}
h5 {font-size:.0.8em;}

.headerShadow {position:relative; padding:2.0em 0em 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:2.0em 0em 1em 1em; left:0px; top:0px;}

#mainMenu {
position:absolute; left:0; width:15.5em; text-align:left; line-height:1.2em; 
padding:1.0em 0.5em 0.2em 0.5em; font-size:1em;
}

#displayArea {margin:1em 1em 0em 17em;}

/*
 toBalaFile 巨集的 Style 設定
*/
.toBalaFile {background:#fff; border:0px solid #ccc; padding:1px 7px 1px 3px; margin:2px;}
.toBalaFileEdit {border:1px solid #841;padding:2px;margin:2px 5px 2px 5px;}
.toBalaFileCancel {border:1px solid #841;padding:2px;margin:2px 5px 2px 5px;}
.toBalaFileToolBar {background:#fff;border-bottom: 3px solid #841;padding:3px 0px 5px 0px;margin:5px 0px 0px 5px;}
.toBalaFileSave {border:1px solid #841;padding:2px;margin:2px 5px 2px 5px;}

/*}}}*/
/*{{{*/
/***** LAYOUT STYLES -  DO NOT EDIT! *****/
ul.suckerfish, ul.suckerfish ul {
	margin: 0;
	padding: 0;
	list-style: none;
	line-height:1.4em;
}

ul.suckerfish  li {
	display: inline-block; 
	display: block;
	float: left; 
}

ul.suckerfish li ul {
	position: absolute;
	left: -999em;
}

ul.suckerfish li:hover ul, ul.suckerfish li.sfhover ul {
	left: auto;
}

ul.suckerfish ul li {
	float: none;
	border-right: 0;
	border-left:0;
}

ul.suckerfish a, ul.suckerfish a:hover {
	display: block;
}

ul.suckerfish li a.tiddlyLink, ul.suckerfish li a, #mainMenu ul.suckerfish li a {font-weight:bold;}
/**** END LAYOUT STYLES *****/


/**** COLORS AND APPEARANCE - DEFAULT *****/
ul.suckerfish li a {
	padding: 0.5em 1.5em;
	color: #FFF;
	background: #0066aa;
	border-bottom: 0;
	font-weight:bold;
}

ul.suckerfish li:hover a, ul.suckerfish li.sfhover a{
	background: #00558F;
}

ul.suckerfish li:hover ul a, ul.suckerfish li.sfhover ul a{
	color: #000;
	background: #eff3fa;
	border-top:1px solid #FFF;
}

ul.suckerfish ul li a:hover {
	background: #e0e8f5;
}

ul.suckerfish li a{
	width:9em;
}

ul.suckerfish ul li a, ul.suckerfish ul li a:hover{
	display:inline-block;
	width:9em;
}

ul.suckerfish li {
	border-left: 1px solid #00558F;
}
/***** END COLORS AND APPEARANCE - DEFAULT *****/


/***** LAYOUT AND APPEARANCE: VERTICAL *****/
ul.suckerfish.vertical li{
	width:10em;
	border-left: 0px solid #00558f;
}

ul.suckerfish.vertical ul li, ul.suckerfish.vertical li a, ul.suckerfish.vertical li:hover a, ul.suckerfish.vertical li.sfhover a {
	border-left: 0.8em solid #00558f;
}

ul.suckerfish.vertical li a, ul.suckerfish.vertical li:hover a, ul.suckerfish.vertical li.sfhover a,  ul.suckerfish.vertical li.sfhover a:hover{
	width:8em;
}

ul.suckerfish.vertical {
	width:10em; text-align:left;
	float:left;
}

ul.suckerfish.vertical li a {
	padding: 0.5em 1em 0.5em 1em;
	border-top:1px solid  #fff;
}

ul.suckerfish.vertical, ul.suckerfish.vertical ul {
	line-height:1.4em;
}

ul.suckerfish.vertical li:hover ul, ul.suckerfish.vertical li.sfhover ul { 
	margin: -2.4em 0 0 10.9em;
}

ul.suckerfish.vertical li:hover ul li a, ul.suckerfish.vertical li.sfhover ul li a {
	border: 0px solid #FFF;
}

ul.suckerfish.vertical li:hover a, ul.suckerfish.vertical li.sfhover a{
	padding-right:1.1em;
}

ul.suckerfish.vertical li:hover ul li, ul.suckerfish.vertical li.sfhover ul li {
	border-bottom:1px solid  #fff;
}

/***** END LAYOUT AND APPEARANCE: VERTICAL *****/
/*}}}*/
/*{{{*/
* html .tiddler {height:1%;}

body {font-size:.75em; font-family:arial,helvetica; margin:0; padding:0;}

h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
h4,h5,h6 {margin-top:1em;}
h1 {font-size:1.35em;}
h2 {font-size:1.25em;}
h3 {font-size:1.1em;}
h4 {font-size:1em;}
h5 {font-size:.9em;}

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

ol {list-style-type:decimal;}
ol ol {list-style-type:lower-alpha;}
ol ol ol {list-style-type:lower-roman;}
ol ol ol ol {list-style-type:decimal;}
ol ol ol ol ol {list-style-type:lower-alpha;}
ol ol ol ol ol ol {list-style-type:lower-roman;}
ol ol ol ol ol ol ol {list-style-type:decimal;}

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

.indent {margin-left:3em;}
.outdent {margin-left:3em; text-indent:-3em;}
code.escaped {white-space:nowrap;}

.tiddlyLinkExisting {font-weight:bold;}
.tiddlyLinkNonExisting {font-style:italic;}

/* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
a.tiddlyLinkNonExisting.shadow {font-weight:bold;}

#mainMenu .tiddlyLinkExisting,
	#mainMenu .tiddlyLinkNonExisting,
	#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
#sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}

.header {position:relative;}
.header a:hover {background:transparent;}
.headerShadow {position:relative; padding:4.5em 0em 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0em 1em 1em; left:0px; top:0px;}

.siteTitle {font-size:3em;}
.siteSubtitle {font-size:1.2em;}

#mainMenu {position:absolute; left:0; width:10em; text-align:right; line-height:1.6em; padding:1.5em 0.5em 0.5em 0.5em; font-size:1.1em;}

#sidebar {position:absolute; right:3px; width:16em; font-size:.9em;}
#sidebarOptions {padding-top:0.3em;}
#sidebarOptions a {margin:0em 0.2em; padding:0.2em 0.3em; display:block;}
#sidebarOptions input {margin:0.4em 0.5em;}
#sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
#sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
#sidebarOptions .sliderPanel input {margin:0 0 .3em 0;}
#sidebarTabs .tabContents {width:15em; overflow:hidden;}

.wizard {padding:0.1em 1em 0em 2em;}
.wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizardStep {padding:1em 1em 1em 1em;}
.wizard .button {margin:0.5em 0em 0em 0em; font-size:1.2em;}
.wizardFooter {padding:0.8em 0.4em 0.8em 0em;}
.wizardFooter .status {padding:0em 0.4em 0em 0.4em; margin-left:1em;}
.wizard .button {padding:0.1em 0.2em 0.1em 0.2em;}

#messageArea {position:fixed; top:2em; right:0em; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
.messageToolbar {display:block; text-align:right; padding:0.2em 0.2em 0.2em 0.2em;}
#messageArea a {text-decoration:underline;}

.tiddlerPopupButton {padding:0.2em 0.2em 0.2em 0.2em;}
.popupTiddler {position: absolute; z-index:300; padding:1em 1em 1em 1em; margin:0;}

.popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
.popup .popupMessage {padding:0.4em;}
.popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0em;}
.popup li.disabled {padding:0.4em;}
.popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
.listBreak {font-size:1px; line-height:1px;}
.listBreak div {margin:2px 0;}

.tabset {padding:1em 0em 0em 0.5em;}
.tab {margin:0em 0em 0em 0.25em; padding:2px;}
.tabContents {padding:0.5em;}
.tabContents ul, .tabContents ol {margin:0; padding:0;}
.txtMainTab .tabContents li {list-style:none;}
.tabContents li.listLink { margin-left:.75em;}

#contentWrapper {display:block;}
#splashScreen {display:none;}

#displayArea {margin:1em 17em 0em 14em;}

.toolbar {text-align:right; font-size:.9em;}

.tiddler {padding:1em 1em 0em 1em;}

.missing .viewer,.missing .title {font-style:italic;}

.title {font-size:1.6em; font-weight:bold;}

.missing .subtitle {display:none;}
.subtitle {font-size:1.1em;}

.tiddler .button {padding:0.2em 0.4em;}

.tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
.isTag .tagging {display:block;}
.tagged {margin:0.5em; float:right;}
.tagging, .tagged {font-size:0.9em; padding:0.25em;}
.tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
.tagClear {clear:both;}

.footer {font-size:.9em;}
.footer li {display:inline;}

.annotation {padding:0.5em; margin:0.5em;}

* html .viewer pre {width:99%; padding:0 0 1em 0;}
.viewer {line-height:1.4em; padding-top:0.5em;}
.viewer .button {margin:0em 0.25em; padding:0em 0.25em;}
.viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
.viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}

.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
table.listView th, table.listView td, table.listView tr {padding:0px 3px 0px 3px;}

.viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
.viewer code {font-size:1.2em; line-height:1.4em;}

.editor {font-size:1.1em;}
.editor input, .editor textarea {display:block; width:100%; font:inherit;}
.editorFooter {padding:0.25em 0em; font-size:.9em;}
.editorFooter .button {padding-top:0px; padding-bottom:0px;}

.fieldsetFix {border:0; padding:0; margin:1px 0px 1px 0px;}

.sparkline {line-height:1em;}
.sparktick {outline:0;}

.zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
.zoomer div {padding:1em;}

* html #backstage {width:99%;}
* html #backstageArea {width:99%;}
#backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0em; right:0em;}
#backstageButton a {padding:0.1em 0.4em 0.1em 0.4em; margin:0.1em 0.1em 0.1em 0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; margin:0em 3em 0em 3em; padding:1em 1em 1em 1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding:0.2em 0.4em 0.2em 0.4em;}
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
<<tabs txtMoreTab "未完成" "內容空白的文章" TabMoreMissing "未引用" "未被引用的文章" TabMoreOrphans "預設文章" "已預設內容的隱藏文章" TabMoreShadowed>>
<<list shadowed>>
<<allTags excludeLists>>
<<timeline>>
/***
|Name|TaggedTemplateTweak|
|Source|http://www.TiddlyTools.com/#TaggedTemplateTweak|
|Version|1.1.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|Story.prototype.chooseTemplateForTiddler()|
|Description|use alternative ViewTemplate/EditTemplate for tiddler's tagged with specific tag values|
The core function, "story.chooseTemplateForTiddler(title,template)" is essentially a "pass-thru" that returns the same template it was given, and is provided by the core so that plugins can customize the template selection logic to select alternative templates, based on whatever programmatic criteria is appropriate.  This tweak extends story.chooseTemplateForTiddler() so that ''whenever a tiddler is marked with a specific tag value, it can be viewed and/or edited using alternatives to the standard tiddler templates.'' 
!!!!!Usage
<<<
Each alternative template is associated with a specific tiddler tag value by using that tag value as a prefix added to the standard TiddlyWiki template titles, [[ViewTemplate]] and [[EditTemplate]].

For example, any tiddlers that are tagged with ''<<tag media>>'' will look for alternative templates named [[mediaViewTemplate]] and [[mediaEditTemplate]].  Additionally, in order to find templates that have proper WikiWord tiddler titles (e.g., [[MediaViewTemplate]] and [[MediaEditTemplate]]), the plugin will also attempt to use a capitalized form of the tag value (e.g., ''Media'') as a prefix.  //This capitalization is for comparison purposes only and will not alter the actual tag values that are stored in the tiddler.//

If no matching alternative template can be found by using //any// of the tiddler's tags (either "as-is" or capitalized), the tiddler defaults to using the appropriate standard [[ViewTemplate]] or [[EditTemplate]] definition.

''To add your own custom templates:''
>First, decide upon a suitable tag keyword to uniquely identify your custom templates and create custom view and/or edit templates using that keyword as a prefix (e.g., "KeywordViewTemplate" and "KeywordEditTemplate").  Then, simply create a tiddler and tag it with your chosen keyword... that's it!  As long as the tiddler is tagged with your keyword, it will be displayed using the corresponding alternative templates.  If you remove the tag or rename/delete the alternative templates, the tiddler will revert to using the standard viewing and editing templates.
<<<
!!!!!Examples
<<<
|Sample tiddler| tag | view template | edit template |
|[[MediaSample - QuickTime]]| <<tag media>> | [[MediaViewTemplate]] | [[MediaEditTemplate]] |
|[[MediaSample - Windows]]| <<tag media>> | [[MediaViewTemplate]] | [[MediaEditTemplate]] |
|[[CDSample]]| <<tag CD>> | [[CDViewTemplate]] | [[CDEditTemplate]] |
|<<newTiddler label:"create new task..." title:SampleTask tag:task text:"Type some text and then press DONE to view the task controls">> | <<tag task>> | [[TaskViewTemplate]] | [[EditTemplate]] |

//(note: if these samples are not present in your document, please visit// http://www.TiddlyTools.com/ //to view these sample tiddlers on-line)//
<<<
!!!!!Revisions
<<<
2007.06.23 [1.1.0] re-written to use automatic 'tag prefix' search instead of hard coded check for each tag.  Allows new custom tags to be used without requiring code changes to this plugin.
2007.06.11 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.taggedTemplate= {major: 1, minor: 1, revision: 0, date: new Date(2007,6,18)};
Story.prototype.taggedTemplate_chooseTemplateForTiddler = Story.prototype.chooseTemplateForTiddler
Story.prototype.chooseTemplateForTiddler = function(title,template)
{
	// get default template from core
	var template=this.taggedTemplate_chooseTemplateForTiddler.apply(this,arguments);

	// if the tiddler to be rendered doesn't exist yet, just return core result
	var tiddler=store.getTiddler(title); if (!tiddler) return template;

	// look for template whose prefix matches a tag on this tiddler
	for (t=0; t<tiddler.tags.length; t++) {
		var tag=tiddler.tags[t];
		if (store.tiddlerExists(tag+template)) { template=tag+template; break; }
		// try capitalized tag (to match WikiWord template titles)
		var cap=tag.substr(0,1).toUpperCase()+tag.substr(1);
		if (store.tiddlerExists(cap+template)) { template=cap+template; break; }
	}

	return template;
}
//}}}
/***
|''Name:''|~TaggerPlugin|
|''Version:''|1.0.1 (2006-06-01)|
|''Source:''|http://tw.lewcid.org//#TaggerPlugin|
|''Author:''|SaqImtiaz|
|''Description:''|Provides a drop down listing current tiddler tags, and allowing toggling of tags.|
|''Documentation:''|[[TaggerPluginDocumentation]]|
|''Source Code:''|[[TaggerPluginSource]]|
|''~TiddlyWiki:''|Version 2.0.8 or better|
***/
// /%
config.tagger={defaults:{label:"Tags: ",tooltip:"Manage tiddler tags",taglist:"true",excludeTags:"",notags:"tiddler has no tags",aretags:"current tiddler tags:",toggletext:"add tags:"}};config.macros.tagger={};config.macros.tagger.arrow=(document.all?"▼":"▾");config.macros.tagger.handler=function(_1,_2,_3,_4,_5,_6){var _7=config.tagger.defaults;var _8=_5.parseParams("tagman",null,true);var _9=((_8[0].label)&&(_8[0].label[0])!=".")?_8[0].label[0]+this.arrow:_7.label+this.arrow;var _a=((_8[0].tooltip)&&(_8[0].tooltip[0])!=".")?_8[0].tooltip[0]:_7.tooltip;var _b=((_8[0].taglist)&&(_8[0].taglist[0])!=".")?_8[0].taglist[0]:_7.taglist;var _c=((_8[0].exclude)&&(_8[0].exclude[0])!=".")?(_8[0].exclude[0]).readBracketedList():_7.excludeTags.readBracketedList();if((_8[0].source)&&(_8[0].source[0])!="."){var _d=_8[0].source[0];}if(_d&&!store.getTiddler(_d)){return false;}var _e=function(e){if(!e){var e=window.event;}var _11=Popup.create(this);var _12=store.getTags();var _13=new Array();for(var i=0;i<_12.length;i++){_13.push(_12[i][0]);}if(_d){var _15=store.getTiddler(_d);_13=_15.tags.sort();}var _16=_6.tags.sort();var _17=function(_18,_19,_1a){var sp=createTiddlyElement(createTiddlyElement(_11,"li"),"span",null,"tagger");var _1c=createTiddlyButton(sp,_18,_1a+" '"+_19+"'",taggerOnToggle,"button","toggleButton");_1c.setAttribute("tiddler",_6.title);_1c.setAttribute("tag",_19);insertSpacer(sp);if(window.createTagButton_orig_mptw){createTagButton_orig_mptw(sp,_19)}else{createTagButton(sp,_19);}};createTiddlyElement(_11,"li",null,"listTitle",(_6.tags.length==0?_7.notags:_7.aretags));for(var t=0;t<_16.length;t++){_17("[x]",_16[t],"remove tag ");}createTiddlyElement(createTiddlyElement(_11,"li"),"hr");if(_b!="false"){createTiddlyElement(_11,"li",null,"listTitle",_7.toggletext);for(var i=0;i<_13.length;i++){if(!_6.tags.contains(_13[i])&&!_c.contains(_13[i])){_17("[ ]",_13[i],"add tag ");}}createTiddlyElement(createTiddlyElement(_11,"li"),"hr");}var _1f=createTiddlyButton(createTiddlyElement(_11,"li"),("Create new tag"),null,taggerOnToggle);_1f.setAttribute("tiddler",_6.title);if(_d){_1f.setAttribute("source",_d);}Popup.show(_11,false);e.cancelBubble=true;if(e.stopPropagation){e.stopPropagation();}return (false);};createTiddlyButton(_1,_9,_a,_e,"button","taggerDrpBtn");};window.taggerOnToggle=function(e){var tag=this.getAttribute("tag");var _22=this.getAttribute("tiddler");var _23=store.getTiddler(_22);if(!tag){var _24=prompt("Enter new tag:","");if(_24!=""&&_24!=null){var tag=_24;if(this.getAttribute("source")){var _26=store.getTiddler(this.getAttribute("source"));_26.tags.pushUnique(_24);}}else{return false;}}if(!_23||!_23.tags){store.saveTiddler(_22,_22,"",config.options.txtUserName,new Date(),tag);}else{if(_23.tags.find(tag)==null){_23.tags.push(tag);}else{if(!_24){_23.tags.splice(_23.tags.find(tag),1);}}store.saveTiddler(_23.title,_23.title,_23.text,_23.modifier,_23.modified,_23.tags);}story.refreshTiddler(_22,null,true);if(config.options.chkAutoSave){saveChanges();}return false;};setStylesheet(".tagger a.button {font-weight: bold;display:inline; padding:0px;}\n"+".tagger #toggleButton {padding-left:2px; padding-right:2px; margin-right:1px; font-size:110%;}\n"+"#nestedtagger {background:#2E5ADF; border: 1px solid #0331BF;}\n"+".popup .listTitle {color:#000;}\n"+"","TaggerStyles");window.lewcidTiddlerSwapTag=function(_27,_28,_29){for(var i=0;i<_27.tags.length;i++){if(_27.tags[i]==_28){_27.tags[i]=_29;return true;}}return false;};window.lewcidRenameTag=function(e){var tag=this.getAttribute("tag");var _2d=prompt("Rename tag '"+tag+"' to:",tag);if((_2d==tag)||(_2d==null)){return false;}if(store.tiddlerExists(_2d)){if(confirm(config.messages.overwriteWarning.format([_2d.toString()]))){story.closeTiddler(_2d,false,false);}else{return null;}}tagged=store.getTaggedTiddlers(tag);if(tagged.length!=0){for(var j=0;j<tagged.length;j++){lewcidTiddlerSwapTag(tagged[j],tag,_2d);}}if(store.tiddlerExists(tag)){store.saveTiddler(tag,_2d);}if(document.getElementById("tiddler"+tag)){var _2f=document.getElementById(story.idPrefix+tag);var _30=story.positionTiddler(_2f);var _31=document.getElementById(story.container);story.closeTiddler(tag,false,false);story.createTiddler(_31,_30,_2d,null);story.saveTiddler(_2d);}if(config.options.chkAutoSave){saveChanges();}return false;};window.onClickTag=function(e){if(!e){var e=window.event;}var _34=resolveTarget(e);var _35=(!isNested(_34));if((Popup.stack.length>1)&&(_35==true)){Popup.removeFrom(1);}else{if(Popup.stack.length>0&&_35==false){Popup.removeFrom(0);}}var _36=(_35==false)?"popup":"nestedtagger";var _37=createTiddlyElement(document.body,"ol",_36,"popup",null);Popup.stack.push({root:this,popup:_37});var tag=this.getAttribute("tag");var _39=this.getAttribute("tiddler");if(_37&&tag){var _3a=store.getTaggedTiddlers(tag);var _3b=[];var li,r;for(r=0;r<_3a.length;r++){if(_3a[r].title!=_39){_3b.push(_3a[r].title);}}var _3d=config.views.wikified.tag;if(_3b.length>0){var _3e=createTiddlyButton(createTiddlyElement(_37,"li"),_3d.openAllText.format([tag]),_3d.openAllTooltip,onClickTagOpenAll);_3e.setAttribute("tag",tag);createTiddlyElement(createTiddlyElement(_37,"li"),"hr");for(r=0;r<_3b.length;r++){createTiddlyLink(createTiddlyElement(_37,"li"),_3b[r],true);}}else{createTiddlyText(createTiddlyElement(_37,"li",null,"disabled"),_3d.popupNone.format([tag]));}createTiddlyElement(createTiddlyElement(_37,"li"),"hr");var h=createTiddlyLink(createTiddlyElement(_37,"li"),tag,false);createTiddlyText(h,_3d.openTag.format([tag]));createTiddlyElement(createTiddlyElement(_37,"li"),"hr");var _40=createTiddlyButton(createTiddlyElement(_37,"li"),("Rename tag '"+tag+"'"),null,lewcidRenameTag);_40.setAttribute("tag",tag);}Popup.show(_37,false);e.cancelBubble=true;if(e.stopPropagation){e.stopPropagation();}return (false);};if(!window.isNested){window.isNested=function(e){while(e!=null){var _42=document.getElementById("contentWrapper");if(_42==e){return true;}e=e.parentNode;}return false;};}config.shadowTiddlers.TaggerPluginDocumentation="The documentation is available [[here.|http://tw.lewcid.org/#TaggerPluginDocumentation]]";config.shadowTiddlers.TaggerPluginSource="The uncompressed source code is available [[here.|http://tw.lewcid.org/#TaggerPluginSource]]";
// %/
/***
|''Name:''|TagsTreePlugin|
|''Description:''|Displays tags hierachy as a tree of tagged tiddlers.<br>Can be used to create dynamic outline navigation.|
|''Version:''|1.0.1|
|''Date:''|Jan 04,2008|
|''Source:''|http://visualtw.ouvaton.org/VisualTW.html|
|''Author:''|Pascal Collin|
|''License:''|[[BSD open source license|License]]|
|''~CoreVersion:''|2.1.0|
|''Browser:''|Firefox 2.0; InternetExplorer 6.0|
!Demo
On the plugin [[homepage|http://visualtw.ouvaton.org/VisualTW.html]] :
*Try to tag some <<newTiddler>> with a tag displayed in the menu and edit MainMenu.
*Look at some tags like [[Plugins]] or [[menu]].
!Installation
#import the plugin,
#save and reload,
#optionally, edit TagsTreeStyleSheet.
! Usage
{{{<<tagsTree>>}}} macro accepts the following //optional// parameters.
|!#|!parameter|!description|!by default|
|1|{{{root}}}|Uses {{{root}}} tag as tree root|- In a //tiddler// content or template : uses the tiddler as root tag.<br>- In the //page// content or template (by ex MainMenu) : displays all untagged tags.|
|2|{{{excludeTag}}}|Excludes all such tagged tiddlers from the tree|Uses default excludeLists tag|
|3|{{{level}}}|Expands nodes until level {{{level}}}.<br>Value {{{0}}} hides expand/collapse buttons.|Nodes are collapsed on first level|
|4|{{{depth}}}|Hierachy depth|6 levels depth (H1 to H6 header styles)|
|5|{{{sortField}}}|Alternate sort field. By example : "index".|Sorts tags and tiddlers alphabetically (on their title)|
|6|{{{labelField}}}|Alertnate label field. By example : "label".|Displays tiddler's title|

!Useful addons
*[[FieldsEditorPlugin]] : //create//, //edit//, //view// and //delete// commands in toolbar <<toolbar fields>>.
*[[TaggerPlugin]] : Provides a drop down listing current tiddler tags, and allowing toggling of tags.
!Advanced Users
You can change the global defaults for TagsTreePlugin, like default {{{level}}} value or level styles, by editing or overriding the first config.macros.tagsTree attributes below.
!Code
***/
//{{{
config.macros.tagsTree = {
	expand : "+",
	collapse : "–",
	depth : 6,
	level : 1,
	sortField : "",	
	labelField : "",
	styles : ["h1","h2","h3","h4","h5","h6"],
	trees : {}
}

config.macros.tagsTree.handler = function(place,macroName,params,wikifier,paramString,tiddler)
{
	var root = params[0] ? params[0] : (tiddler ? tiddler.title : null);
	var excludeTag = params[1] ? params[1] : "excludeTagsTree";
	var level = params[2] ? params[2] : config.macros.tagsTree.level;
	var depth = params[3] ? params[3] : config.macros.tagsTree.depth;
	var sortField = params[4] ? params[4] : config.macros.tagsTree.sortField;
	var labelField = params[5] ? params[5] : config.macros.tagsTree.labelField;
	var showButtons = (level>0);
	var id = config.macros.tagsTree.getId(place);
	if (config.macros.tagsTree.trees[id]==undefined) config.macros.tagsTree.trees[id]={};
	config.macros.tagsTree.createSubTree(place,id,root,excludeTag,[],level>0 ? level : 1,depth, sortField, labelField,showButtons);
}

config.macros.tagsTree.createSubTree = function(place, id, root, excludeTag, ancestors, level, depth, sortField, labelField,showButtons){
	var childNodes = root ? this.getChildNodes(root, ancestors) : this.getRootTags(excludeTag);
	var isOpen = (level>0) || (!showButtons);
	if (root && this.trees[id][root]!=undefined) isOpen = this.trees[id][root]; 
	if (root && ancestors.length) {
		var t = store.getTiddler(root);
		if (childNodes.length && depth>0) {
			var wrapper = createTiddlyElement(place , this.styles[Math.min(Math.max(ancestors.length,1),6)-1],null,"branch");
			if (showButtons) {
				b = createTiddlyButton(wrapper, isOpen ? config.macros.tagsTree.collapse : config.macros.tagsTree.expand, null, config.macros.tagsTree.onClick);
				b.setAttribute("treeId",id);
				b.setAttribute("tiddler",root);					
			}
			createTiddlyText(createTiddlyLink(wrapper, root),t&&labelField ? t.fields[labelField] ? t.fields[labelField] : root : root);
		}
		else 
			createTiddlyText(createTiddlyLink(place, root,false,"leaf"),t&&labelField ? t.fields[labelField] ? t.fields[labelField] : root : root);
	}
	if (childNodes.length && depth) {
		var d = createTiddlyElement(place,"div",null,"subtree");
		d.style.display= isOpen ? "block" : "none";
		if (sortField)
			childNodes.sort(function(a, b){
				var fa=a.fields[sortField];
				var fb=b.fields[sortField];
				return (fa==undefined && fb==undefined) ? a.title < b.title ? -1 : a.title > b.title ? 1 : 0 : (fa==undefined && fb!=undefined) ? 1 :(fa!=undefined && fb==undefined) ? -1 : fa < fb ? -1 : fa > fb ? 1 : 0;
			})
		for (var cpt=0; cpt<childNodes.length; cpt++)
			this.createSubTree(d, id, childNodes[cpt].title, excludeTag, ancestors.concat(root), level-1, depth-1, sortField, labelField, showButtons);	
	}	
}

config.macros.tagsTree.onClick = function(e){
	var id = this.getAttribute("treeId");
	var tiddler = this.getAttribute("tiddler");	
	var n = this.parentNode.nextSibling;
	var isOpen = n.style.display != "none";
	if(config.options.chkAnimate && anim && typeof Slider == "function")
		anim.startAnimating(new Slider(n,!isOpen,null,"none"));
	else
		n.style.display = isOpen ? "none" : "block";
	this.firstChild.nodeValue = isOpen ? config.macros.tagsTree.expand : config.macros.tagsTree.collapse;
	config.macros.tagsTree.trees[id][tiddler]=!isOpen;
	return false;
}

config.macros.tagsTree.getChildNodes = function(root ,ancestors){
	var childs = store.getTaggedTiddlers(root);
	var result = new Array();
	for (var cpt=0; cpt<childs.length; cpt++)
		if (childs[cpt].title!=root && ancestors.indexOf(childs[cpt].title)==-1) result.push(childs[cpt]);
	return result;
}

config.macros.tagsTree.getRootTags = function(excludeTag){
	var tags = store.getTags(excludeTag);
	tags.sort(function(a,b) {return a[0].toLowerCase() < b[0].toLowerCase() ? -1 : (a[0].toLowerCase() == b[0].toLowerCase() ? 0 : +1);});
	var result = new Array();
	for (var cpt=0; cpt<tags.length; cpt++) {
		var t = store.getTiddler(tags[cpt][0]);
		if (!t || t.tags.length==0) result.push(t ? t : {title:tags[cpt][0],fields:{}});
	}
	return result;
}

config.macros.tagsTree.getId = function(element){
	while (!element.id && element.parentNode) element=element.parentNode;
	return element.id ? element.id : "<html>";
}

config.shadowTiddlers.TagsTreeStyleSheet = "/*{{{*/\n";
config.shadowTiddlers.TagsTreeStyleSheet +=".leaf, .subtree {display:block; margin-left : 0.5em}\n";
config.shadowTiddlers.TagsTreeStyleSheet +=".subtree {margin-bottom:0.5em}\n";
config.shadowTiddlers.TagsTreeStyleSheet +="#mainMenu {text-align:left}\n";
config.shadowTiddlers.TagsTreeStyleSheet +=".branch .button {border:1px solid #DDD; color:#AAA;font-size:9px;padding:0 2px;margin-right:0.3em;vertical-align:middle;text-align:center;}\n";
config.shadowTiddlers.TagsTreeStyleSheet +="/*}}}*/";

store.addNotification("TagsTreeStyleSheet", refreshStyles); 

config.shadowTiddlers.MainMenu="<<tagsTree>>"

config.shadowTiddlers.PageTemplate = config.shadowTiddlers.PageTemplate.replace(/id='mainMenu' refresh='content' /,"id='mainMenu' refresh='content' force='true' ")

//}}}
/*{{{*/
.leaf, .subtree {display:block}

/* 設定 Tree 第一層的 left margin */ 
#mainMenu>.subtree {margin-left:0em}

.leaf {margin-left:0.2em; margin-bottom:0.2em; color:navy;}
.subtree {margin-left:0.8em;}

.branch .button {
   border:1px solid #DDD; color:#999;
   font-size:10px;padding:0 4px;
   margin-right:0.5em;
   vertical-align:middle;text-align:center;
}

/*}}}*/
/***
|''Name:''|TiddlersBarPlugin|
|''Description:''|A bar to switch between tiddlers through tabs (like browser tabs bar).|
|''Version:''|1.2.5|
|''Date:''|Jan 18,2008|
|''Source:''|http://visualtw.ouvaton.org/VisualTW.html|
|''Author:''|Pascal Collin|
|''License:''|[[BSD open source license|License]]|
|''~CoreVersion:''|2.1.0|
|''Browser:''|Firefox 2.0; InternetExplorer 6.0, others|
!Tips
*Doubleclick on the tiddlers bar (where there is no tab) create a new tiddler.
*Tabs include a button to close {{{x}}} or save {{{!}}} their tiddler.
*By default, click on the current tab close all others tiddlers.
!Configuration options 
<<option chkDisableTabsBar>> Disable the tabs bar (to print, by example).
<<option chkHideTabsBarWhenSingleTab >> Automatically hide the tabs bar when only one tiddler is displayed. 
<<option txtSelectedTiddlerTabButton>> ''selected'' tab command button.
<<option txtPreviousTabKey>> previous tab access key.
<<option txtNextTabKey>> next tab access key.
!Code
***/
//{{{
config.options.chkDisableTabsBar = config.options.chkDisableTabsBar ? config.options.chkDisableTabsBar : false;
config.options.chkHideTabsBarWhenSingleTab  = config.options.chkHideTabsBarWhenSingleTab  ? config.options.chkHideTabsBarWhenSingleTab  : false;
config.options.txtSelectedTiddlerTabButton = config.options.txtSelectedTiddlerTabButton ? config.options.txtSelectedTiddlerTabButton : "closeOthers";
config.options.txtPreviousTabKey = config.options.txtPreviousTabKey ? config.options.txtPreviousTabKey : "";
config.options.txtNextTabKey = config.options.txtNextTabKey ? config.options.txtNextTabKey : "";
config.macros.tiddlersBar = {
	tooltip : "see ",
	tooltipClose : "click here to close this tab",
	tooltipSave : "click here to save this tab",
	promptRename : "Enter tiddler new name",
	currentTiddler : "",
	previousState : false,
	previousKey : config.options.txtPreviousTabKey,
	nextKey : config.options.txtNextTabKey,	
	tabsAnimationSource : null, //use document.getElementById("tiddlerDisplay") if you need animation on tab switching.
	handler: function(place,macroName,params) {
		var previous = null;
		if (config.macros.tiddlersBar.isShown())
			story.forEachTiddler(function(title,e){
				if (title==config.macros.tiddlersBar.currentTiddler){
					var d = createTiddlyElement(null,"span",null,"tab tabSelected");
					config.macros.tiddlersBar.createActiveTabButton(d,title);
					if (previous && config.macros.tiddlersBar.previousKey) previous.setAttribute("accessKey",config.macros.tiddlersBar.nextKey);
					previous = "active";
				}
				else {
					var d = createTiddlyElement(place,"span",null,"tab tabUnselected");
					var btn = createTiddlyButton(d,title,config.macros.tiddlersBar.tooltip + title,config.macros.tiddlersBar.onSelectTab);
					btn.setAttribute("tiddler", title);
					if (previous=="active" && config.macros.tiddlersBar.nextKey) btn.setAttribute("accessKey",config.macros.tiddlersBar.previousKey);
					previous=btn;
				}
				var isDirty =story.isDirty(title);
				var c = createTiddlyButton(d,isDirty ?"!":"x",isDirty?config.macros.tiddlersBar.tooltipSave:config.macros.tiddlersBar.tooltipClose, isDirty ? config.macros.tiddlersBar.onTabSave : config.macros.tiddlersBar.onTabClose,"tabButton");
				c.setAttribute("tiddler", title);
				if (place.childNodes) {
					place.insertBefore(document.createTextNode(" "),place.firstChild); // to allow break line here when many tiddlers are open
					place.insertBefore(d,place.firstChild); 
				}
				else place.appendChild(d);
			})
	}, 
	refresh: function(place,params){
		removeChildren(place);
		config.macros.tiddlersBar.handler(place,"tiddlersBar",params);
		if (config.macros.tiddlersBar.previousState!=config.macros.tiddlersBar.isShown()) {
			story.refreshAllTiddlers();
			if (config.macros.tiddlersBar.previousState) story.forEachTiddler(function(t,e){e.style.display="";});
			config.macros.tiddlersBar.previousState = !config.macros.tiddlersBar.previousState;
		}
	},
	isShown : function(){
		if (config.options.chkDisableTabsBar) return false;
		if (!config.options.chkHideTabsBarWhenSingleTab) return true;
		var cpt=0;
		story.forEachTiddler(function(){cpt++});
		return (cpt>1);
	},
	selectNextTab : function(){  //used when the current tab is closed (to select another tab)
		var previous="";
		story.forEachTiddler(function(title){
			if (!config.macros.tiddlersBar.currentTiddler) {
				story.displayTiddler(null,title);
				return;
			}
			if (title==config.macros.tiddlersBar.currentTiddler) {
				if (previous) {
					story.displayTiddler(null,previous);
					return;
				}
				else config.macros.tiddlersBar.currentTiddler=""; 	// so next tab will be selected
			}
			else previous=title;
			});		
	},
	onSelectTab : function(e){
		var t = this.getAttribute("tiddler");
		if (t) story.displayTiddler(null,t);
		return false;
	},
	onTabClose : function(e){
		var t = this.getAttribute("tiddler");
		if (t) {
			if(story.hasChanges(t) && !readOnly) {
				if(!confirm(config.commands.cancelTiddler.warning.format([t])))
				return false;
			}
			story.closeTiddler(t);
		}
		return false;
	},
	onTabSave : function(e) {
		var t = this.getAttribute("tiddler");
		if (!e) e=window.event;
		if (t) config.commands.saveTiddler.handler(e,null,t);
		return false;
	},
	onSelectedTabButtonClick : function(event,src,title) {
		var t = this.getAttribute("tiddler");
		if (!event) event=window.event;
		if (t && config.options.txtSelectedTiddlerTabButton && config.commands[config.options.txtSelectedTiddlerTabButton])
			config.commands[config.options.txtSelectedTiddlerTabButton].handler(event, src, t);
		return false;
	},
	onTiddlersBarAction: function(event) {
		var source = event.target ? event.target.id : event.srcElement.id; // FF uses target and IE uses srcElement;
		if (source=="tiddlersBar") story.displayTiddler(null,'New Tiddler',DEFAULT_EDIT_TEMPLATE,false,null,null);
	},
	createActiveTabButton : function(place,title) {
		if (config.options.txtSelectedTiddlerTabButton && config.commands[config.options.txtSelectedTiddlerTabButton]) {
			var btn = createTiddlyButton(place, title, config.commands[config.options.txtSelectedTiddlerTabButton].tooltip ,config.macros.tiddlersBar.onSelectedTabButtonClick);
			btn.setAttribute("tiddler", title);
		}
		else
			createTiddlyText(place,title);
	}
}

story.coreCloseTiddler = story.coreCloseTiddler? story.coreCloseTiddler : story.closeTiddler;
story.coreDisplayTiddler = story.coreDisplayTiddler ? story.coreDisplayTiddler : story.displayTiddler;

story.closeTiddler = function(title,animate,unused) {
	if (title==config.macros.tiddlersBar.currentTiddler)
		config.macros.tiddlersBar.selectNextTab();
	story.coreCloseTiddler(title,false,unused); //disable animation to get it closed before calling tiddlersBar.refresh
	var e=document.getElementById("tiddlersBar");
	if (e) config.macros.tiddlersBar.refresh(e,null);
}

story.displayTiddler = function(srcElement,tiddler,template,animate,unused,customFields,toggle){
	story.coreDisplayTiddler(config.macros.tiddlersBar.tabsAnimationSource,tiddler,template,animate,unused,customFields,toggle);
	var title = (tiddler instanceof Tiddler)? tiddler.title : tiddler;  
	if (config.macros.tiddlersBar.isShown()) {
		story.forEachTiddler(function(t,e){
			if (t!=title) e.style.display="none";
			else e.style.display="";
		})
		config.macros.tiddlersBar.currentTiddler=title;
	}
	var e=document.getElementById("tiddlersBar");
	if (e) config.macros.tiddlersBar.refresh(e,null);
}

var coreRefreshPageTemplate = coreRefreshPageTemplate ? coreRefreshPageTemplate : refreshPageTemplate;
refreshPageTemplate = function(title) {
	coreRefreshPageTemplate(title);
	if (config.macros.tiddlersBar) config.macros.tiddlersBar.refresh(document.getElementById("tiddlersBar"));
}

//ensureVisible=function (e) {return 0} //disable bottom scrolling (not useful now)

config.shadowTiddlers.StyleSheetTiddlersBar = "/*{{{*/\n";
config.shadowTiddlers.StyleSheetTiddlersBar += "#tiddlersBar .button {border:0}\n";
config.shadowTiddlers.StyleSheetTiddlersBar += "#tiddlersBar .tab {white-space:nowrap}\n";
config.shadowTiddlers.StyleSheetTiddlersBar += "#tiddlersBar {padding : 1em 0.5em 2px 0.5em}\n";
config.shadowTiddlers.StyleSheetTiddlersBar += ".tabUnselected .tabButton, .tabSelected .tabButton {padding : 0 2px 0 2px; margin: 0 0 0 4px;}\n";
config.shadowTiddlers.StyleSheetTiddlersBar += ".tiddler, .tabContents {border:1px [[ColorPalette::TertiaryPale]] solid;}\n";
config.shadowTiddlers.StyleSheetTiddlersBar +="/*}}}*/";
store.addNotification("StyleSheetTiddlersBar", refreshStyles);

config.refreshers.none = function(){return true;}
config.shadowTiddlers.PageTemplate=config.shadowTiddlers.PageTemplate.replace(/<div id='tiddlerDisplay'><\/div>/m,"<div id='tiddlersBar' refresh='none' ondblclick='config.macros.tiddlersBar.onTiddlersBarAction(event)'></div>\n<div id='tiddlerDisplay'></div>");

//}}}
<!--{{{-->
<div class='toolbar' macro='toolbar closeTiddler closeOthers +editTiddler > fields syncing permalink references jump'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>

<!--
<div class='tagging' macro='tagging'></div>
-->
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
{{item1{設定 IPv6 位址}}}
{{{
# configure
[edit]
root@GWVT100V6# set interfaces ethernet eth
eth0  eth1  
[edit]
root@GWVT100V6# set interfaces ethernet eth0 address 2012::155/64
[edit]
root@GWVT100V6# set interfaces ethernet eth1 address fd00:155::254/64
[edit]
root@GWVT100V6# commit
[edit]
root@GWVT100V6# save
save     savelog  
[edit]
root@GWVT100V6# save
Saving configuration to '/config/config.boot'...
Done
[edit]
root@GWVT100V6# exit
exit
root@GWVT100V6:~# ifconfig -a
eth0      Link encap:Ethernet  HWaddr 52:54:00:3e:a0:60  
          inet addr:192.168.122.98  Bcast:192.168.122.255  Mask:255.255.255.0
          inet6 addr: 2012::155/64 Scope:Global
          inet6 addr: fe80::5054:ff:fe3e:a060/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:359 errors:0 dropped:0 overruns:0 frame:0
          TX packets:316 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:25738 (25.1 KiB)  TX bytes:25408 (24.8 KiB)
          Interrupt:10 Base address:0x2000 

eth1      Link encap:Ethernet  HWaddr 52:54:00:a0:6e:63  
          inet addr:192.168.100.252  Bcast:192.168.100.255  Mask:255.255.255.0
          inet6 addr: fe80::5054:ff:fea0:6e63/64 Scope:Link
          inet6 addr: fd00:155::254/64 Scope:Global
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:442 errors:0 dropped:0 overruns:0 frame:0
          TX packets:10 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:136899 (133.6 KiB)  TX bytes:1044 (1.0 KiB)
          Interrupt:11 Base address:0x6000 

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:5114 errors:0 dropped:0 overruns:0 frame:0
          TX packets:5114 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:307936 (300.7 KiB)  TX bytes:307936 (300.7 KiB)
}}}

{{item1{顯示 IPv6 路由表}}}
{{{
# show ipv6 route
Codes: K - kernel route, C - connected, S - static, R - RIPng, O - OSPFv3,
       I - ISIS, B - BGP, * - FIB route.

C>* ::1/128 is directly connected, lo
C>* 2012::/64 is directly connected, eth0
C>* fd00:166::/64 is directly connected, eth1
C * fe80::/64 is directly connected, eth0
C>* fe80::/64 is directly connected, eth1
}}}

{{item1{顯示 Neighbor Discovery (ND) cache}}}
{{{
# show ipv6 neighbors 
fe80::5054:ff:fe66:6787 dev eth1 lladdr 52:54:00:66:67:87 DELAY
fd00:166::100 dev eth1 lladdr 52:54:00:66:67:87 REACHABLE
}}}

{{item1{增加 IPv6 路由表}}}
{{{
# configure 
[edit]
root@GWVT100V6# set protocols static route6 fd00:188::/64 next-hop 2012::188
[edit]
root@GWVT100V6# commit
[edit]
root@GWVT100V6# save
Saving configuration to '/config/config.boot'...
Done
[edit]

}}}


{{item1{最終設定檔內容}}}
{{{
# cat /config/config.boot 
interfaces {
    ethernet eth0 {
        address dhcp
        address 2012::155/64
        duplex auto
        hw-id 52:54:00:3e:a0:60
        smp_affinity auto
        speed auto
    }
    ethernet eth1 {
        address fd00:155::254/64
        duplex auto
        hw-id 52:54:00:a0:6e:63
        smp_affinity auto
        speed auto
    }
    loopback lo {
    }
}
protocols {
    static {
        route6 fd00:188::/64 {
            next-hop 2012::188 {
            }
        }
    }
}
system {
    config-management {
        commit-revisions 20
    }
    console {
        device ttyS0 {
            speed 9600
        }
    }
    host-name GW155
    login {
        user vyatta {
            authentication {
                encrypted-password $1$HZ71C4bm$Gg42Wxzdg8uineJSenNWc.
            }
            level admin
        }
    }
    ntp {
        server 0.vyatta.pool.ntp.org {
        }
        server 1.vyatta.pool.ntp.org {
        }
        server 2.vyatta.pool.ntp.org {
        }
    }
    package {
        auto-sync 1
        repository community {
            components main
            distribution stable
            password ""
            url http://packages.vyatta.com/vyatta
            username ""
        }
    }
    syslog {
        global {
            facility all {
                level notice
            }
            facility protocols {
                level debug
            }
        }
    }
    time-zone GMT
}
}}}
It’s amazing but it’s possible to write little web server on bash shell script. Here is it’s source code:
{{{
while [ $? -eq 0 ];do 
nc -vlp 8080 -c'(r=read;e=echo;$r a b c;z=$r;while [ ${#z} -gt 2 ];do $r z;done;f=`$e $b|sed 's/[^a-z0-9_.-]//gi'`;h="HTTP/1.0";o="$h 200 OK\r\n";c="Content";if [ -z $f ];then($e $o;ls|(while $r n;do if [ -f "$n" ]; then $e "`ls -gh $n`";fi;done););elif [ -f $f ];then $e "$o$c-Type: `file -ib $f`\n$c-Length: `stat -c%s $f`";$e;cat $f;else $e -e "$h 404 Not Found\n\n404\n";fi)';
done
}}}
網址 : http://joliclic.free.fr/html/object-tag/en/ 

A lot of people insert medias in their web page with the non-standard <embed> tag. But there is a standard tag for this insertion kind, <object> . Effectively this is not immediate to use it manner cross-browsers, but we'll see that there are some techniques for that practically all the browsers be able to understand the code.

The HTML 4.01 specification introduce the <object> element :

    ...HTML 4 introduces the OBJECT element, which offers an all-purpose solution to generic object inclusion. The OBJECT element allows HTML authors to specify everything required by an object for its presentation by a user agent: source code, initial values, and run-time data. In this specification, the term "object" is used to describe the things that people want to place in HTML documents; other commonly used terms for these things are: applets, plug-ins, media handlers, etc.

This element is designed to include any sort of document. We specify which sort with the type attribute indicating the mime type, and the source of the document with the data attribute indicating his URI.

If the browser, or one of his plugin, can interpret this document, it does it, otherwise the nested content of the object is displayed.
Any HTML code can be inserted as a alternative content, for example a link to the document or an image instead an animation. It can be also another alternative object, we talk about "nested object".

For a lot of type of document, that's all !

''examples :''

embed a HTML document
{{{
<object data="data/test.html" type="text/html" width="300" height="200">
  alt : <a href="data/test.html">test.html</a>
</object>
}}}

embed a pdf document
{{{
<object data="data/test.pdf" type="application/pdf" width="300" height="200">
  alt : <a href="data/test.pdf">test.pdf</a>
</object>
}}}

You can specify some parameters related to the document with the param tag. IE sometimes needs a src parameter to understand the location.

embed a wav document
{{{
<object type="audio/x-wav" data="data/test.wav" width="200" height="20">
  <param name="src" value="data/test.wav">
  <param name="autoplay" value="false">
  <param name="autoStart" value="0">
  alt : <a href="data/test.wav">test.wav</a>
</object>
}}}
The parameters autoplay is understandable by ~QuickTime, autoStart by Windows media Player and Real Audio.

!More complicated cases

For some types, like ~QuickTime document, IE needs a non-standard value to the valid classid attribute, an identifier to load an associated activeX.

an only IE insertion of a ~QuickTime document
{{{
<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"
        width="320" height="240">
  <param name="src" value="data/test.mov" >
  alt : <a href="data/test.mov">test.mov</a>
</object>
}}}

We 're going to nest another object as an alternative content, for the other browsers that use the standard formulation :

nested objects
{{{
<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"
        width="320" height="240">
  <param name="src" value="data/test.mov" >
  <param name="controller" value="true" >
  <param name="autoplay" value="false">

  <object type="video/quicktime" data="data/test.mov" width="320" height="240">
    <param name="controller" value="true" >
    <param name="autoplay" value="false">
   alt : <a href="data/test.mov">test.mov</a>
  </object>
</object>
}}}

It works, but unfortunately IE has a bug, it displays a blank zone for the second object.
This bug is resolved in ~IE7, but for older versions, we must hide this second object. We have two techniques to do it, the IE specific conditional comments, or by CSS.

Hide the nested object with IE conditional comments

~IE5 introduce the conditional comments, that is very helpful to compensate IE bugs. This method isn't understandable by earlier versions of IE, but fortunately they are almost not used.

We can write two objects, one specially for IE, and another for the standards respectful browsers :
{{{
<!--[if IE]>
<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"
        width="320" height="240">
  <param name="src" value="data/test.mov" >
  <param name="controller" value="true" >
  <param name="autoplay" value="false">
</object>
<![endif]-->

<!--[if !IE]> <!-->
<object type="video/quicktime" data="data/test.mov" width="320" height="240">
  <param name="controller" value="true" >
  <param name="autoplay" value="false">
  alt : <a href="data/test.mov">test.mov</a>
</object>
<!--<![endif]-->
}}}

But as ~IE7 corrects this bug, I prefer to use them with nested objects :
{{{
<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"
        width="320" height="240">
  <param name="src" value="data/test.mov" >
  <param name="controller" value="true" >
  <param name="autoplay" value="false">

  <!--[if gte IE 7]> <!-->
  <object type="video/quicktime" data="data/test.mov" width="320" height="240">
    <param name="controller" value="true" >
    <param name="autoplay" value="false">
   alt : <a href="data/test.mov">test.mov</a>
  </object>
  <!--<![endif]-->
  <!--[if lt IE 7]>
   alt : <a href="data/test.mov">test.mov</a>
  <![endif]-->
</object>
}}}

Hide the nested object with CSS

The other solution is to use some CSS hacks to hide the nested object. We must use a hack to create rules applied only by IE to hide the object, then another to render visible it again by IE Mac.

special class for IE (place it in a style tag on the head of the HTML document, or in a separate stylesheet)
{{{
/* hides the second object from all versions of IE */

* html object.hiddenObjectForIE { display: none; }

/* display the second object only for IE5 Mac */

/* IE Mac \*//*/
* html object.hiddenObjectForIE { display: inline; }
/**/
}}}

and apply this style to the nested object
{{{
<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"
        width="320" height="240">
  <param name="src" value="data/test.mov" >
  <param name="controller" value="true" >
  <param name="autoplay" value="false">

  <object type="video/quicktime" data="data/test.mov"
         width="320" height="240"
         class="hiddenObjectForIE">
    <param name="controller" value="true" >
    <param name="autoplay" value="false">
   alt : <a href="data/test.mov">test.mov</a>
  </object>
</object>
}}}

This technic have some annoyances with java (and perhaps some other), a security alert is displayed on loading, and the alternative content of the nested object is also displayed.

/***
|''Name:''|abego.IncludePlugin|
|''Version:''|1.0.0 (2007-02-08)|
|''Type:''|plugin|
|''Source:''|http://tiddlywiki.abego-software.de/#IncludePlugin|
|''Author:''|Udo Borkowski (ub [at] abego-software [dot] de)|
|''Documentation:''|[[IncludePlugin Documentation|http://tiddlywiki.abego-software.de/#%5B%5BIncludePlugin%20Documentation%5D%5D]]|
|''Community:''|([[del.icio.us|http://del.icio.us/post?url=http://tiddlywiki.abego-software.de/index.html%23IncludePlugin]]) ([[Support|http://groups.google.com/group/TiddlyWiki]])|
|''Copyright:''|&copy; 2007 [[abego Software|http://www.abego-software.de]]|
|''Licence:''|[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]|
|''~CoreVersion:''|2.1.3|
|''Browser:''|Firefox 1.5.0.9 or better; Internet Explorer 6.0|
***/
//{{{

// Ensure the global abego namespace is set up.
if (!window.abego) window.abego = {};

var invokeLater = function(func, delay, priority) {
	return abego.invokeLater ? abego.invokeLater(func, delay, priority) : setTimeout(func,delay);
};

// Asynchronously load the given (local or remote) file.
// 
// @param url 		either an URL or a local file path to a file
//					Examples:
//						* http://www.abego-software.de/index.html
//						* file:///C:/abegoWebSite-Copy/index.html
//						* C:\abegoWebSite-Copy\index.html    (for Windows machines)
//							(Notice: backslashes in JavaScript string constants must be escaped, 
//							 i.e. the last example must be written as: "C:\\abegoWebSite-Copy\\index.html"
//							 when "hardcoded" in JavaScript source code)
// 
// @param callback 
//					function(content,url,params,errorMessage) 
//					called at the end of the operation. 
//					On success content holds the content of the loaded file. 
//					On error content is undefined and errorMessage holds an error message. 
//					params is the params passed into abego.loadFile.
//
// @param params 	passed through to the callback function
// 
abego.loadFile = function(url,callback,params) {

	var onLoad = function(status,params,responseText,url,xhr) {
		return status 
				? callback(responseText, url, params)
				: callback(undefined, url, params, "Error loading %0".format([url]));
	};
	
	// Make sure the URL is a real URL, with protocol prefix etc.
	if (url.search(/^((http(s)?)|(file)):/) != 0) {
		
		// no protocol specified. 
		if (url.search(/^((.\:\\)|(\\\\)|(\/))/) == 0) {
			// "url" is an "absolute" path to a local file. Prefix it with file://
			url = "file://"+url;
			
		} else {
			// "url" is a "relative" URL. Make it absolute
			
			// prefix the url with the directory containing the current document
			// (This also includes the protocol prefix)
			var documentPath = document.location.toString();
			var i = documentPath.lastIndexOf("/");
			url = documentPath.substr(0,i+1)+url;
		}
		// replace every \ by a /, to cover Windows style pathes
		url = url.replace(/\\/mg,"/");
	}
	
	loadRemoteFile(url,onLoad,params);

};

// Asynchronously load the given (local or remote) TiddlyWiki store.
// 
// @param url 		either an URL or a local file path to a TiddlyWiki file (absolute or relative)
//					Examples:
//						* http://www.abego-software.de/index.html
//						* file:///C:/abegoWebSite-Copy/index.html
//						* include/beta.html
//						* C:\abegoWebSite-Copy\index.html    (for Windows machines)
//							(Notice: backslashes in JavaScript string constants must be escaped, 
//							 i.e. the last example must be written as: "C:\\abegoWebSite-Copy\\index.html"
//							 when "hardcoded" in JavaScript source code)
// 
// @param callbackWithStore 
//					function(theStore,url,params,errorMessage) 
//					called at the end of the operation. 
//					On success theStore holds the loaded store (a TiddlyWiki object). 
//					On error theStore is undefined and errorMessage holds an error message. 
//					params is the params passed into abego.loadTiddlyWikiStore
//
// @param params 	passed through to the callbackWithStore
//
// @progress		[optional] function(message, sender, state, url, params) called in various situations during the operation,
//								typically used to show "the progress" of the operation.
//								sender: the constant "abego.loadTiddlyWikiStore"
//								state: one of these: "Started", "Processing", "Done", "Failed"
//									"Processing" means the data has been received and in now processed.
// 
abego.loadTiddlyWikiStore = function(url,callbackWithStore,params,progress) {
	
	var sendProgress = function(message, state) {
		if (progress)
			progress(message,"abego.loadTiddlyWikiStore",state,url,params);
	};
	
	// Load contents of a TiddlyWiki from a string
	//# Returns null on success, an error message otherwise.
	//# based on code from TiddlyWiki 2.2 alpha
	var importTiddlyWiki = function(store,text)
	{
		// Crack out the content - will be refactored to share code with saveChanges()
		var posOpeningDiv = text.indexOf(startSaveArea);
		var limitClosingDiv = text.indexOf("<!--POST-BODY-END--"+">");
		var posClosingDiv = text.lastIndexOf(endSaveArea,limitClosingDiv == -1 ? text.length : limitClosingDiv);
		if((posOpeningDiv == -1) || (posClosingDiv == -1))
			return config.messages.invalidFileError.format([url]);
		var content = "<html><body>" + text.substring(posOpeningDiv,posClosingDiv + endSaveArea.length) + "</body></html>";
		// Create the iframe
		var iframe = document.createElement("iframe");
		iframe.style.display = "none";
		document.body.appendChild(iframe);
		var doc = iframe.document;
		if(iframe.contentDocument)
			doc = iframe.contentDocument; // For NS6
		else if(iframe.contentWindow)
			doc = iframe.contentWindow.document; // For IE5.5 and IE6
		// Put the content in the iframe
		doc.open();
		doc.writeln(content);
		doc.close();
		// Load the content into a TiddlyWiki() object
		var storeArea = doc.getElementById("storeArea");
		store.loadFromDiv(storeArea,"store");
		// Get rid of the iframe
		iframe.parentNode.removeChild(iframe);
		return null;
	};
	
	var sendError = function(message) {
		sendProgress("Error when loading %0".format([url]),"Failed");
		callbackWithStore(undefined, url,params, message);
		return message;
	};
	
	var sendStore = function(store) {
		sendProgress("Loaded %0".format([url]),"Done");
		callbackWithStore(store, url, params);
		return null;
	};
	
	
	var callback = function(content,theURL,params,errorMessage) {
		if (content === undefined) {
			sendError(errorMessage);
			return;
		}
		
		sendProgress("Processing %0".format([url]),"Processing");
		var orig_invalidFileError = config.messages.invalidFileError;
		config.messages.invalidFileError = "The file '%0' does not appear to be a valid TiddlyWiki file";
		try {
			// Load the content into a TiddlyWiki() object
			var importStore = new TiddlyWiki();
			var errorText = importTiddlyWiki(importStore,content);
			if (errorText)
				sendError(errorText);
			else
				sendStore(importStore);

		} catch (ex) {
			sendError(exceptionText(ex));
		} finally {
			config.messages.invalidFileError = orig_invalidFileError;
		}
	};
	
	sendProgress("Start loading %0".format([url]),"Started");
	abego.loadFile(url,callback,params);
};


//==============================================================================
// Include Plugin 

(function(){

// only install once
if (abego.TiddlyWikiIncluder) return;


// --------------------------------------------------
// Constants

var WAITING = "waiting";
var LOADING = "loading";

var ANI_DURATION_HIDE_STATE = 1000;

var REFRESH_PRIORITY = -200;
var ANIMATION_PRIORITY = -100;
var UPDATE_STATE_PRIORITY = -300;

// --------------------------------------------------
// Variables

var useInclude;
var includes = []; // [] of Strings. the urls of the stores to include, in the sequence of the calls.
var includedStores = {}; // url(String) -> TiddlyWiki or String; when not (yet) loaded a status or error string.
var pendingOnLoadURLs = []; // [] of String. a list of urls that should be passed with the next "notifyListeners".
var refreshTiddlyWikiTimerID; // for delayed refresh
var listeners = [];
var progress;

// --------------------------------------------------
// Helper functions

var isIncludeEnabled = function() {
	if (useInclude === undefined)
		useInclude = config.options.chkUseInclude === undefined || config.options.chkUseInclude;
	return useInclude;
};

var getMissingIncludeMsg = function(url) {
	return "No include specified for %0".format([url])
};

// Called after one or more included TiddlyWikis are loaded
//
var notifyListeners = function() {
	var urls = pendingOnLoadURLs;
	pendingOnLoadURLs = [];
	if (urls.length) {
		for (var i= 0; i < listeners.length; i++)
			listeners[i](urls);
	}
};

var idleCount; // Reset to 0 when the system is "not idle", incremented inside refreshTiddlyWiki

var refreshTiddlyWiki = function() {
	// To avoid to much refreshing/flickering don't refresh immediately 
	// but wait until the system was idle for a certain time.
	
	if (refreshTiddlyWikiTimerID !== undefined) clearInterval(refreshTiddlyWikiTimerID);
	
	idleCount = 0;
	
	var sendDone = function() {
		abego.TiddlyWikiIncluder.sendProgress("","","Done");
	};
	
	refreshTiddlyWikiTimerID = setInterval(function() {
		idleCount++;
		if (idleCount <= 10)
			return;
			
		clearInterval(refreshTiddlyWikiTimerID);
		refreshTiddlyWikiTimerID = undefined;
			
		abego.TiddlyWikiIncluder.sendProgress("Refreshing...","","");
		refreshDisplay();
		invokeLater(sendDone,0,REFRESH_PRIORITY);
	},0);
};

// Calls callback for every loaded store and returns the first non-false/null.. value returned by callback.
//
// @param callback  function(store, url)
//
var forEachLoadedStore = function(callback) {
	var result;
	for (var i = 0; i < includes.length; i++) {
		var theStore = abego.TiddlyWikiIncluder.getStore(includes[i]);
		if (theStore && (result = callback(theStore, includes[i])))
			return result;
	}
};

var attachToStore = function() {
	if (!window.store)
		return invokeLater(attachToStore,100);
		
	var orig_fetchTiddler = store.fetchTiddler;
	
	store.fetchTiddler = function(title) {
		var t = orig_fetchTiddler.apply(this,arguments);
		if (t) return t;
		
		// When there is a shadowtiddler with that name done look for
		// any included tiddler since these would hide the shadow
		if (config.shadowTiddlers[title] !== undefined) return undefined;
		
		// Don't look for the "New Tiddler" tiddler in the included TiddlyWikis,
		// since returning such a tiddler (that is readonly) will make it impossible
		// in the Main TiddlyWiki to create new tiddlers.
		if (title == config.macros.newTiddler.title) return undefined;

		return forEachLoadedStore(
				function(theStore, url) {
					var t = theStore.fetchTiddler(title);
					if (t) 
						t.includeURL = url;
					return t;
				});
	};

	// We also refresh TiddlyWiki to reflect the new included Tiddlers (if we have any).
	if (includes.length)
		refreshTiddlyWiki();
};

var includeFromIncludeList = function() {
	if (!window.store)
		return invokeLater(includeFromIncludeList,100);
		
	var includeListText = store.getTiddlerText("IncludeList");
	if (includeListText) 
		wikify(includeListText,document.createElement("div"));
};

var getFunctionUsingForReallyEachTiddler = function(func) {
	var wrapper = function() {
		var orig_forEachTiddler = store.forEachTiddler;

		var forEachTiddlerWithIncludes = function(callback) {
			var done = {};
			var includeURL;

			var callbackWrapper = function(title, tiddler) {
				// ensure every title is only processed once
				if (done[title]) 
					return;
				done[title] = 1;
				
				// for "included tiddlers" set the includeURL;
				if (includeURL)
					tiddler.includeURL = includeURL;
				
				callback.apply(this,arguments);
			};
			
			// forEachTiddler over the original tiddlers
			orig_forEachTiddler.call(store, callbackWrapper);
			
			// add all shadowTiddler titles to done 
			// (to avoid an included store hides a shadow tiddler)
			for (var n in config.shadowTiddlers)
				done[n] = 1;

			// add all the "New Tiddler" tiddlerto done 
			// (to avoid an included store (with "New Tiddler") makes it impossible to create new tiddlers)
			done[config.macros.newTiddler.title] = 1;

			// forEachTiddler over every included store
			forEachLoadedStore(
					function(theStore, url) {
						includeURL = url;
						theStore.forEachTiddler(callbackWrapper);
					});
		};
		
		store.forEachTiddler = forEachTiddlerWithIncludes;
		try {
			return func.apply(this,arguments);
		} finally {
			store.forEachTiddler = orig_forEachTiddler;
		}
	};
	
	return wrapper;
};

var useForReallyEachTiddler = function(object,property) {
	return object[property] = getFunctionUsingForReallyEachTiddler(object[property]);
};


//================================================================================
// abego.TiddlyWikiIncluder

abego.TiddlyWikiIncluder = {};

abego.TiddlyWikiIncluder.setProgressFunction = function(func) {
	progress = func;
};

abego.TiddlyWikiIncluder.getProgressFunction = function(func) {
	return progress;
};

abego.TiddlyWikiIncluder.sendProgress = function(message, sender, state) {
	if (progress)
		progress.apply(this,arguments);
};


// Called when an included TiddlyWiki could not be loaded.
//
// By default an error message is displayed.
//
abego.TiddlyWikiIncluder.onError = function(url, errorMessage) {
	displayMessage("Error when including '%0':\n%1".format([url, errorMessage]));
};


// Returns true when there are "pending" includes, i.e. TiddlyWiki that are not yet loaded.
//
// A TiddlyWiki that failed loading is not pending.
//
abego.TiddlyWikiIncluder.hasPendingIncludes = function() {
	for (var i = 0; i < includes.length; i++) {
		var state = abego.TiddlyWikiIncluder.getState(includes[i]);
		if (state == WAITING || state == LOADING)
			return true;
	}
	return false;
};


// @return [] of Strings, the URLs of the includes
//
abego.TiddlyWikiIncluder.getIncludes = function() {
	return includes.slice();
};


// @return [may be null] a state/error text of the store with the given URL, or null when the store is already loaded
//
abego.TiddlyWikiIncluder.getState = function(url) {
	var s = includedStores[url];
	if (!s)
		return getMissingIncludeMsg(url);
	return typeof s == "string" ? s : null;
};


// @return [may be null] the (TiddlyWiki) store  with the given URL, null if not (yet) loaded.
//
abego.TiddlyWikiIncluder.getStore = function(url) {
	var s = includedStores[url];
	if (!s)
		return getMissingIncludeMsg(url);
	return s instanceof TiddlyWiki ? s : null;
};


// Includes the (local or remote) TiddlyWiki store with the given url.
// 
// stores with urls already already included are ignored.
//
// @param url	see url@abego.loadTiddlyWikiStore
// @param delayMilliSeconds [optional] if defined loading starts delayMilliSeconds later, otherwise "immediately"
//
abego.TiddlyWikiIncluder.include = function(url, delayMilliSeconds) {
	if (!isIncludeEnabled() || includedStores[url])
		return;
	var self = this;
	
	includes.push(url);
	includedStores[url] = WAITING;

	var loadStoreCallback = function(theStore,urlInCallback,params,errorMessage) {
		if (theStore === undefined) {
			includedStores[url] = errorMessage;
			self.onError(url, errorMessage);
			return;
		}
		includedStores[url] = theStore;
		pendingOnLoadURLs.push(url);
		invokeLater(notifyListeners);
	};
	
	var loadStore = function() {
		includedStores[url] = LOADING;
		abego.loadTiddlyWikiStore(url,loadStoreCallback,null,progress);
	};
	
	if (delayMilliSeconds)
		invokeLater(loadStore, delayMilliSeconds);
	else
		loadStore();
};


// iterates over all tiddlers of "the store" and all tiddlers of included (and loaded) stores
//
abego.TiddlyWikiIncluder.forReallyEachTiddler = function(callback) {
	var caller = function() {
		store.forEachTiddler(callback);
	};
	
	getFunctionUsingForReallyEachTiddler(caller).call(store);
};


// function abego.TiddlyWikiIncluder.getFunctionUsingForReallyEachTiddler(func)
//
// Returns a function that behaves as func, but every call to store.forEachTiddler will actually 
// be a call to forReallyEachTiddler, i.e. iterate over the tiddlers the main store and of the 
// included TiddlyWikis
//
// @return the patched function
//
abego.TiddlyWikiIncluder.getFunctionUsingForReallyEachTiddler = getFunctionUsingForReallyEachTiddler;


// function abego.TiddlyWikiIncluder.useForReallyEachTiddler(object,property)
//
// Patches the function hold in the given property of the object in such a way that every call
// to store.forEachTiddler will actually be a call to forReallyEachTiddler, i.e. iterate over the
// tiddlers the main staire and of the included TiddlyWikis
//
// @param object
// @param property the name of the property of the object containing the function to be patched.
// @return the patched function
//
abego.TiddlyWikiIncluder.useForReallyEachTiddler = useForReallyEachTiddler;


// Add a listener function to the TiddlyWikiIncluder.
//
// @param listener function(urls)
//							url: [] of Strings, containing the urls of the TiddlyWiki just included
//									(see url@abego.TiddlyWikiIncluder.include)
//						called whenever one or more TiddlyWiki store are successfully included.
//
abego.TiddlyWikiIncluder.addListener = function(listener) {
	listeners.push(listener);
};

// -------------------------------------------------------------------------------
// TiddlyWikiIncluder initialization code

abego.TiddlyWikiIncluder.addListener(refreshTiddlyWiki);

//----------------------------------------------------------------------------
// Options Support

if (config.options.chkUseInclude === undefined) config.options.chkUseInclude = true;

config.shadowTiddlers.AdvancedOptions += "\n<<option chkUseInclude>> Include ~TiddlyWikis (IncludeList | IncludeState | [[help|http://tiddlywiki.abego-software.de/#%5B%5BIncludePlugin%20Documentation%5D%5D]])\n^^(Reload this ~TiddlyWiki to make changes become effective)^^";
config.shadowTiddlers.IncludeState = "<<includeState>>";

//================================================================================
// Default Progress Handling for abego.TiddlyWikiIncluder

var showAnimated = function(e, showing, duration) {
	if (!anim || !abego.ShowAnimation) {
		e.style.display = showing ? "block" : "none";
		return;
	}
	
	anim.startAnimating(new abego.ShowAnimation(e,showing,duration));
};

abego.TiddlyWikiIncluder.getDefaultProgressFunction = function() {

	setStylesheet(
		".includeProgressState{\n"+
		"background-color:#FFCC00;\n"+
		"position:absolute;\n"+
		"right:0.2em;\n"+
		"top:0.2em;\n"+
		"width:7em;\n"+
		"padding-left:0.2em;\n"+
		"padding-right:0.2em\n"+
		"}\n",
		"abegoInclude");

	var createStateElem = function() {
		var e = document.createElement("div");
		e.className = "includeProgressState";
		e.style.display = "none";
		document.body.appendChild(e);
		return e;
	};
	
	var stateElem = createStateElem();


	var showState = function(message) {
		removeChildren(stateElem);
		createTiddlyText(stateElem,message);
		showAnimated(stateElem,true,0);
	};

	var hideState = function() {
		// hide the state the next idle time 
		invokeLater(function() {
			showAnimated(stateElem,false,ANI_DURATION_HIDE_STATE);
		},100,ANIMATION_PRIORITY);
	};
	
	var myProgressFunction = function(message, sender, state, url, params) {
		
		if (state == "Done" || state == "Failed") {
			hideState();
			return;
		}
		
		if (sender == "abego.loadTiddlyWikiStore") {
			idleCount = 0;
			if (state == "Processing")
				showState("Including...");
		} else {
			showState(message);
		}
	};
	return myProgressFunction;
};

abego.TiddlyWikiIncluder.setProgressFunction(abego.TiddlyWikiIncluder.getDefaultProgressFunction());


//================================================================================
// The "include" macro
//
// Syntax: <<include {url}* [delay: {milliSeconds}] [hide: true] >>
//

config.macros.include = {};
config.macros.include.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
    params = paramString.parseParams("url",null,true,false,true); // allowEval, cascadeDefaults, names allowed
	var delay = parseInt(getParam(params,"delay","0"));
	var urls = params[0]["url"];
	var hide = getFlag(params, "hide", false);
	if (!hide)
		createTiddlyText(createTiddlyElement(place,"code"),wikifier.source.substring(wikifier.matchStart, wikifier.nextMatch));
	for (var i = 0; urls && i < urls.length; i++)
		abego.TiddlyWikiIncluder.include(urls[i],delay);
};


//================================================================================
// The "includeState" macro
//
// Syntax: <<includeState>>

config.macros.includeState = {};
config.macros.includeState.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
	var getFullState = function () {
		var s = "";
		var includes = abego.TiddlyWikiIncluder.getIncludes();
		if (!includes.length)
			return "{{noIncludes{\nNo includes or 'include' is disabled (see AdvancedOptions)\n}}}\n";
			
		s += "|!Address|!State|\n";
		for (var i = 0; i < includes.length; i++) {
			var inc = includes[i];
			s += "|{{{"+inc+"}}}|";
			var t = abego.TiddlyWikiIncluder.getState(inc);
			s += t ? "{{{"+t+"}}}" : "included";
			s += "|\n"
		}
		s += "|includeState|k\n";
		return s;
	};
	
	var updateState = function(){
		removeChildren(div);
		wikify(getFullState(),div);
		if (abego.TiddlyWikiIncluder.hasPendingIncludes())
			invokeLater(updateState,500,UPDATE_STATE_PRIORITY);
	};

	var div = createTiddlyElement(place,"div");
	
	invokeLater(updateState,0,UPDATE_STATE_PRIORITY);
};

//================================================================================
// Tiddler extension/modification

var orig_Tiddler_isReadOnly = Tiddler.prototype.isReadOnly;

// Includes tiddlers are readonly.
Tiddler.prototype.isReadOnly = function() {
	return orig_Tiddler_isReadOnly.apply(this,arguments) || this.isIncluded();
}

Tiddler.prototype.isIncluded = function() {
	return this.includeURL != undefined;
};

Tiddler.prototype.getIncludeURL = function() {
	return this.includeURL;
};


//================================================================================
// TiddlyWiki modifications

// In some TiddlyWiki functions the "forEachTiddler" should work on all tiddlers, also those from 
// included store. (E.g. TiddlyWiki.prototype.getTags)
//
// But not for all (e.g. TiddlyWiki.prototype.getTiddlers is used for saving, but only the "own" tiddlers should be saved)
//
// Therefore explicitly list the functions that should be "wrapped" to use the "forReallyEachTiddler".
//
var tiddlyWikiFunctionsUsingForReallyEachTiddler = {
	getMissingLinks: 1, getOrphans: 1,getTags:1, reverseLookup: 1, updateTiddlers: 1};
	
for (var n in tiddlyWikiFunctionsUsingForReallyEachTiddler)
	useForReallyEachTiddler(TiddlyWiki.prototype,n);


//================================================================================
// Make IntelliTagger "Include-aware"

var patchIntelliTagger = function() {
	if (abego.IntelliTagger)
		useForReallyEachTiddler(abego.IntelliTagger,"assistTagging");
};

//================================================================================
// Perform plugin startup tasks

attachToStore();
invokeLater(includeFromIncludeList,100);
invokeLater(patchIntelliTagger,100);

})();

//}}}
/***
|''Name:''|easyEditPlugin|
|''Description:''|Lite and extensible Wysiwyg editor for TiddlyWiki.|
|''Version:''|1.3.3|
|''Date:''|Dec 21,2007|
|''Source:''|http://visualtw.ouvaton.org/VisualTW.html|
|''Author:''|Pascal Collin|
|''License:''|[[BSD open source license|License]]|
|''~CoreVersion:''|2.1.0|
|''Browser:''|Firefox 2.0; InternetExplorer 6.0|
!Installation
#import the plugin,
#save and reload,
#use the <<toolbar easyEdit>> button in the tiddler's toolbar (in default ViewTemplate) or add {{{easyEdit}}} command in your own toolbar.
! Useful Addons
*[[HTMLFormattingPlugin|http://www.tiddlytools.com/#HTMLFormattingPlugin]] to embed wiki syntax in html tiddlers.<<br>>//__Tips__ : When this plugin is installed, you can use anchor syntax to link tiddlers in wysiwyg mode (example : #example). Anchors are converted back and from wiki syntax when editing.//
*[[TaggedTemplateTweak|http://www.TiddlyTools.com/#TaggedTemplateTweak]] to use alternative ViewTemplate/EditTemplate for tiddler's tagged with specific tag values.
!Configuration
|Buttons in the toolbar (empty = all).<<br>>//Example : bold,underline,separator,forecolor//<<br>>The buttons will appear in this order.| <<option txtEasyEditorButtons>>|
|EasyEditor default height | <<option txtEasyEditorHeight>>|
|Stylesheet applied to the edited richtext |[[EasyEditDocStyleSheet]]|
|Template called by the {{{write}}} button |[[EasyEditTemplate]]|
!How to extend EasyEditor
*To add your own buttons, add some code like the following in a systemConfig tagged tiddler (//use the prompt attribute only if there is a parameter//) :
**{{{EditorToolbar.buttons.heading = {label:"H", toolTip : "Set heading level", prompt: "Enter heading level"};}}} 
**{{{EditorToolbar.buttonsList +=",heading";}}}
*To get the list of all possible commands, see the documentation of the [[Gecko built-in rich text editor|http://developer.mozilla.org/en/docs/Midas]] or the [[IE command identifiers|http://msdn2.microsoft.com/en-us/library/ms533049.aspx]].
*To go further in customization, see [[Link button|EasyEditPlugin-LinkButton]] as an example.
!Code
***/

//{{{

var geckoEditor={};
var IEeditor={};

config.options.txtEasyEditorHeight = config.options.txtEasyEditorHeight ? config.options.txtEasyEditorHeight : "500px";
config.options.txtEasyEditorButtons = config.options.txtEasyEditorButtons ? config.options.txtEasyEditorButtons : "";

// TW2.1.x compatibility
config.browser.isGecko = config.browser.isGecko ? config.browser.isGecko : (config.userAgent.indexOf("gecko") != -1); 
config.macros.annotations = config.macros.annotations ? config.macros.annotations : {handler : function() {}}


// EASYEDITOR MACRO

config.macros.easyEdit = {
	handler : function(place,macroName,params,wikifier,paramString,tiddler) {
		var field = params[0];
		var height = params[1] ? params[1] : config.options.txtEasyEditorHeight;
		var editor = field ? new easyEditor(tiddler,field,place,height) : null;
	},
	gather: function(element){
		var iframes = element.getElementsByTagName("iframe");
		if (iframes.length!=1) return null
		var text = "<html>"+iframes[0].contentWindow.document.body.innerHTML+"</html>";
		text = config.browser.isGecko ? geckoEditor.postProcessor(text) : (config.browser.isIE ? IEeditor.postProcessor(text) : text);
		return text;
	}
}

// EASYEDITOR CLASS

function easyEditor(tiddler,field,place,height) {
	this.tiddler = tiddler;
	this.field = field;
	this.browser = config.browser.isGecko ? geckoEditor : (config.browser.isIE ? IEeditor : null);
	this.wrapper = createTiddlyElement(place,"div",null,"easyEditor");
	this.wrapper.setAttribute("easyEdit",this.field);
	this.iframe = createTiddlyElement(null,"iframe");
	this.browser.setupFrame(this.iframe,height,contextualCallback(this,this.onload));
	this.wrapper.appendChild(this.iframe);
}

easyEditor.prototype.onload = function(){
	this.editor = this.iframe.contentWindow;
	this.doc = this.editor.document;
	if (!this.browser.isDocReady(this.doc)) return null;
	
	if (!this.tiddler.isReadOnly() && this.doc.designMode.toLowerCase()!="on") {
		this.doc.designMode = "on";
		if (this.browser.reloadOnDesignMode) return false;	// IE fire readystatechange after designMode change
	}
	
	var internalCSS = store.getTiddlerText("EasyEditDocStyleSheet");
	setStylesheet(internalCSS,"EasyEditDocStyleSheet",this.doc);
	this.browser.initContent(this.doc,store.getValue(this.tiddler,this.field));

	var barElement=createTiddlyElement(null,"div",null,"easyEditorToolBar");
	this.wrapper.insertBefore(barElement,this.wrapper.firstChild);
	this.toolbar = new EditorToolbar(this.doc,barElement,this.editor);

	this.browser.plugEvents(this.doc,contextualCallback(this,this.scheduleButtonsRefresh));
	this.editor.focus();
}

easyEditor.SimplePreProcessoror = function(text) {
	var re = /^<html>(.*)<\/html>$/m;
	var htmlValue = re.exec(text);
	var value = (htmlValue && (htmlValue.length>0)) ? htmlValue[1] : text;
	return value;
}

easyEditor.prototype.scheduleButtonsRefresh=function() { //doesn't refresh buttons state when rough typing
	if (this.nextUpdate) window.clearTimeout(this.nextUpdate);
	this.nextUpdate = window.setTimeout(contextualCallback(this.toolbar,EditorToolbar.onUpdateButton),easyEditor.buttonDelay);
}

easyEditor.buttonDelay = 200;

// TOOLBAR CLASS

function EditorToolbar(target,parent,window){
	this.target = target;
	this.window=window;
	this.elements={};
	var row = createTiddlyElement(createTiddlyElement(createTiddlyElement(parent,"table"),"tbody"),"tr");
	var buttons = (config.options.txtEasyEditorButtons ? config.options.txtEasyEditorButtons : EditorToolbar.buttonsList).split(",");
	for(var cpt = 0; cpt < buttons.length; cpt++){
		var b = buttons[cpt];
		var button = EditorToolbar.buttons[b];
		if (button) {
			if (button.separator)
				createTiddlyElement(row,"td",null,"separator").innerHTML+="&nbsp;";
			else {
				var cell=createTiddlyElement(row,"td",null,b+"Button");
				if (button.onCreate) button.onCreate.call(this, cell, b);
				else EditorToolbar.createButton.call(this, cell, b);
			}
		}
	}
}

EditorToolbar.createButton = function(place,name){
	this.elements[name] = createTiddlyButton(place,EditorToolbar.buttons[name].label,EditorToolbar.buttons[name].toolTip,contextualCallback(this,EditorToolbar.onCommand(name)),"button");
}

EditorToolbar.onCommand = function(name){
	var button = EditorToolbar.buttons[name];
	return function(){
		var parameter = false;
		if (button.prompt) {
			var parameter = this.target.queryCommandValue(name);
			parameter = prompt(button.prompt,parameter);
		}
		if (parameter != null) {
			this.target.execCommand(name, false, parameter);
			EditorToolbar.onUpdateButton.call(this);
		}
		return false;
	}
}

EditorToolbar.getCommandState = function(target,name){
	try {return target.queryCommandState(name)}
	catch(e){return false}
}

EditorToolbar.onRefreshButton = function (name){
	if (EditorToolbar.getCommandState(this.target,name)) addClass(this.elements[name].parentNode,"buttonON");
	else removeClass(this.elements[name].parentNode,"buttonON");
	this.window.focus();
}

EditorToolbar.onUpdateButton = function(){
	for (b in this.elements) 
		if (EditorToolbar.buttons[b].onRefresh) EditorToolbar.buttons[b].onRefresh.call(this,b);
		else EditorToolbar.onRefreshButton.call(this,b);
}

EditorToolbar.buttons = {
	separator : {separator : true},
	bold : {label:"B", toolTip : "Bold"},
	italic : {label:"I", toolTip : "Italic"},
	underline : {label:"U", toolTip : "Underline"},
	strikethrough : {label:"S", toolTip : "Strikethrough"},
	insertunorderedlist : {label:"\u25CF", toolTip : "Unordered list"},
	insertorderedlist : {label:"1.", toolTip : "Ordered list"},
	justifyleft : {label:"[\u2261", toolTip : "Align left"},
	justifyright : {label:"\u2261]", toolTip : "Align right"},
	justifycenter : {label:"\u2261", toolTip : "Align center"},
	justifyfull : {label:"[\u2261]", toolTip : "Justify"},
	removeformat : {label:"\u00F8", toolTip : "Remove format"},
	fontsize : {label:"\u00B1", toolTip : "Set font size", prompt: "Enter font size"},
	forecolor : {label:"C", toolTip : "Set font color", prompt: "Enter font color"},
	fontname : {label:"F", toolTip : "Set font name", prompt: "Enter font name"},
	heading : {label:"H", toolTip : "Set heading level", prompt: "Enter heading level (example : h1, h2, ...)"},
	indent : {label:"\u2192[", toolTip : "Indent paragraph"},
	outdent : {label:"[\u2190", toolTip : "Outdent paragraph"},
	inserthorizontalrule : {label:"\u2014", toolTip : "Insert an horizontal rule"},
	insertimage : {label:"\u263C", toolTip : "Insert image", prompt: "Enter image url"}
}

EditorToolbar.buttonsList = "bold,italic,underline,strikethrough,separator,increasefontsize,decreasefontsize,fontsize,forecolor,fontname,separator,removeformat,separator,insertparagraph,insertunorderedlist,insertorderedlist,separator,justifyleft,justifyright,justifycenter,justifyfull,indent,outdent,separator,heading,separator,inserthorizontalrule,insertimage";

if (config.browser.isGecko) {
	EditorToolbar.buttons.increasefontsize = {onCreate : EditorToolbar.createButton, label:"A", toolTip : "Increase font size"};
	EditorToolbar.buttons.decreasefontsize = {onCreate : EditorToolbar.createButton, label:"A", toolTip : "Decrease font size"};
	EditorToolbar.buttons.insertparagraph = {label:"P", toolTip : "Format as paragraph"};
}

// GECKO (FIREFOX, ...) BROWSER SPECIFIC METHODS

geckoEditor.setupFrame = function(iframe,height,callback) {
	iframe.setAttribute("style","width: 100%; height:" + height);
	iframe.addEventListener("load",callback,true);
}

geckoEditor.plugEvents = function(doc,onchange){
	doc.addEventListener("keyup", onchange, true);
	doc.addEventListener("keydown", onchange, true);
	doc.addEventListener("click", onchange, true);
}

geckoEditor.postProcessor = function(text){return text};

geckoEditor.preProcessor = function(text){return easyEditor.SimplePreProcessoror(text)}

geckoEditor.isDocReady = function() {return true;}

geckoEditor.reloadOnDesignMode=false;

geckoEditor.initContent = function(doc,content){
	if (content) doc.execCommand("insertHTML",false,geckoEditor.preProcessor(content));
}

// INTERNET EXPLORER BROWSER SPECIFIC METHODS
	
IEeditor.setupFrame = function(iframe,height,callback) {
	iframe.width="99%";  //IE displays the iframe at the bottom if 100%. CSS layout problem ? I don't know. To be studied...
	iframe.height=height.toString();
	iframe.attachEvent("onreadystatechange",callback);
}

IEeditor.plugEvents = function(doc,onchange){
	doc.attachEvent("onkeyup", onchange);
	doc.attachEvent("onkeydown", onchange);
	doc.attachEvent("onclick", onchange);
}

IEeditor.isDocReady = function(doc){
	if (doc.readyState!="complete") return false;
	if (!doc.body) return false;
	return (doc && doc.getElementsByTagName && doc.getElementsByTagName("head") && doc.getElementsByTagName("head").length>0);
}

IEeditor.postProcessor = function(text){return text};

IEeditor.preProcessor = function(text){return easyEditor.SimplePreProcessoror(text)}

IEeditor.reloadOnDesignMode=true;

IEeditor.initContent = function(doc,content){
	if (content) doc.body.innerHTML=IEeditor.preProcessor(content);
}
	
function contextualCallback(obj,func){
    return function(){return func.call(obj)}
}
	
Story.prototype.previousGatherSaveEasyEdit = Story.prototype.previousGatherSaveEasyEdit ? Story.prototype.previousGatherSaveEasyEdit : Story.prototype.gatherSaveFields; // to avoid looping if this line is called several times
Story.prototype.gatherSaveFields = function(e,fields){
	if(e && e.getAttribute) {
		var f = e.getAttribute("easyEdit");
		if(f){
			var newVal = config.macros.easyEdit.gather(e);
			if (newVal) fields[f] = newVal;
		}
		this.previousGatherSaveEasyEdit(e, fields);
	}
}

config.commands.easyEdit={
	text: "編輯網頁",
	tooltip: "Edit this tiddler in wysiwyg mode",
	readOnlyText: "檢視",
	readOnlyTooltip: "View the source of this tiddler",
	handler : function(event,src,title) {
		clearMessage();
		var tiddlerElem = document.getElementById(story.idPrefix + title);
		var fields = tiddlerElem.getAttribute("tiddlyFields");
		story.displayTiddler(null,title,"EasyEditTemplate",false,null,fields);
		return false;
	}
}

config.shadowTiddlers.ViewTemplate = config.shadowTiddlers.ViewTemplate.replace(/\+editTiddler/,"+editTiddler easyEdit");

config.shadowTiddlers.EasyEditTemplate = config.shadowTiddlers.EditTemplate.replace(/macro='edit text'/,"macro='easyEdit text'");

config.shadowTiddlers.EasyEditToolBarStyleSheet = "/*{{{*/\n";
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar {font-size:0.8em}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".editor iframe {border:1px solid #DDD}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar td{border:1px solid #888; padding:2px 1px 2px 1px; vertical-align:middle}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar td.separator{border:0}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .button{border:0;color:#444}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .buttonON{background-color:#EEE}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar {margin:0.25em 0}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .boldButton {font-weight:bold}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .italicButton .button {font-style:italic;padding-right:0.65em}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .underlineButton .button {text-decoration:underline}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .strikeButton .button {text-decoration:line-through}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .unorderedListButton {margin-left:0.7em}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .justifyleftButton .button {padding-left:0.1em}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .justifyrightButton .button {padding-right:0.1em}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .justifyfullButton .button, .easyEditorToolBar .indentButton .button, .easyEditorToolBar .outdentButton .button {padding-left:0.1em;padding-right:0.1em}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .increasefontsizeButton .button {padding-left:0.15em;padding-right:0.15em; font-size:1.3em; line-height:0.75em}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .decreasefontsizeButton .button {padding-left:0.4em;padding-right:0.4em; font-size:0.8em;}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .forecolorButton .button {color:red;}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .fontnameButton .button {font-family:serif}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet +="/*}}}*/";

store.addNotification("EasyEditToolBarStyleSheet", refreshStyles); 

config.shadowTiddlers.EasyEditDocStyleSheet = "/*{{{*/\n \n/*}}}*/";
if (config.annotations) config.annotations.EasyEditDocStyleSheet = "This stylesheet is applied when editing a text with the wysiwyg easyEditor";

//}}}
/***
!Link button add-on
***/
//{{{
EditorToolbar.createLinkButton = function(place,name) {
	this.elements[name] = createTiddlyButton(place,EditorToolbar.buttons[name].label,EditorToolbar.buttons[name].toolTip,contextualCallback(this,EditorToolbar.onInputLink()),"button");
}

EditorToolbar.onInputLink = function() {
	return function(){
		var browser = config.browser.isGecko ? geckoEditor : (config.browser.isIE ? IEeditor : null);
		var value = browser ? browser.getLink(this.target) : "";
		value = prompt(EditorToolbar.buttons["createlink"].prompt,value);
		if (value) browser.doLink(this.target,value);
		else if (value=="") this.target.execCommand("unlink", false, value);
		EditorToolbar.onUpdateButton.call(this);
		return false;
	}
}

EditorToolbar.buttonsList += ",separator,createlink";

EditorToolbar.buttons.createlink = {onCreate : EditorToolbar.createLinkButton, label:"L", toolTip : "Set link", prompt: "Enter link url"};


geckoEditor.getLink=function(doc){
	var range=doc.defaultView.getSelection().getRangeAt(0);
	var container = range.commonAncestorContainer;
	var node = (container.nodeType==3) ? container.parentNode : range.startContainer.childNodes[range.startOffset];
	if (node && node.tagName=="A") {
		var r=doc.createRange();
		r.selectNode(node);
		doc.defaultView.getSelection().addRange(r);
		return (node.getAttribute("tiddler") ? "#"+node.getAttribute("tiddler") : node.href);
	}
	else return (container.nodeType==3 ? "#"+container.textContent.substr(range.startOffset, range.endOffset-range.startOffset).replace(/ $/,"") : "");
}

geckoEditor.doLink=function(doc,link){ // store tiddler in a temporary attribute to avoid url encoding of tiddler's name
	var pin = "href"+Math.random().toString().substr(3);
	doc.execCommand("createlink", false, pin);
	var isTiddler=(link.charAt(0)=="#");
	var node = doc.defaultView.getSelection().getRangeAt(0).commonAncestorContainer;
	var links= (node.nodeType!=3) ? node.getElementsByTagName("a") : [node.parentNode];
	for (var cpt=0;cpt<links.length;cpt++) 
			if (links[cpt].href==pin){
				links[cpt].href=isTiddler ? "javascript:;" : link; 
				links[cpt].setAttribute("tiddler",isTiddler ? link.substr(1) : "");
			}
}

geckoEditor.beforeLinkPostProcessor = geckoEditor.beforelinkPostProcessor ? geckoEditor.beforelinkPostProcessor : geckoEditor.postProcessor;
geckoEditor.postProcessor = function(text){
	return geckoEditor.beforeLinkPostProcessor(text).replace(/<a tiddler="([^"]*)" href="javascript:;">(.*?)(?:<\/a>)/gi,"[[$2|$1]]").replace(/<a tiddler="" href="/gi,'<a href="');
}

geckoEditor.beforeLinkPreProcessor = geckoEditor.beforeLinkPreProcessor ? geckoEditor.beforeLinkPreProcessor : geckoEditor.preProcessor
geckoEditor.preProcessor = function(text){
	return geckoEditor.beforeLinkPreProcessor(text).replace(/\[\[([^|\]]*)\|([^\]]*)]]/g,'<a tiddler="$2" href="javascript:;">$1</a>');
}


IEeditor.getLink=function(doc){
	var node=doc.selection.createRange().parentElement();
	if (node.tagName=="A") return node.href;
	else return (doc.selection.type=="Text"? "#"+doc.selection.createRange().text.replace(/ $/,"") :"");
}

IEeditor.doLink=function(doc,link){
	doc.execCommand("createlink", false, link);
}

IEeditor.beforeLinkPreProcessor = IEeditor.beforeLinkPreProcessor ? IEeditor.beforeLinkPreProcessor : IEeditor.preProcessor
IEeditor.preProcessor = function(text){
	return IEeditor.beforeLinkPreProcessor(text).replace(/\[\[([^|\]]*)\|([^\]]*)]]/g,'<a ref="#$2">$1</a>');
}

IEeditor.beforeLinkPostProcessor = IEeditor.beforelinkPostProcessor ? IEeditor.beforelinkPostProcessor : IEeditor.postProcessor;
IEeditor.postProcessor = function(text){
	return IEeditor.beforeLinkPostProcessor(text).replace(/<a href="#([^>]*)">([^<]*)<\/a>/gi,"[[$2|$1]]");
}

IEeditor.beforeLinkInitContent = IEeditor.beforeLinkInitContent ? IEeditor.beforeLinkInitContent : IEeditor.initContent;
IEeditor.initContent = function(doc,content){
	IEeditor.beforeLinkInitContent(doc,content);
	var links=doc.body.getElementsByTagName("A");
	for (var cpt=0; cpt<links.length; cpt++) {
		links[cpt].href=links[cpt].ref; //to avoid IE conversion of relative URLs to absolute
		links[cpt].removeAttribute("ref");	
	}
}

config.shadowTiddlers.EasyEditToolBarStyleSheet += "\n/*{{{*/\n.easyEditorToolBar .createlinkButton .button {color:blue;text-decoration:underline;}\n/*}}}*/";

config.shadowTiddlers.EasyEditDocStyleSheet += "\n/*{{{*/\na {color:#0044BB;font-weight:bold}\n/*}}}*/";

//}}}
//{{{
//============================================================================
// getCreateDate Function
//============================================================================
//
// Returns the "create date" as generated by the AutoTaggerPlugin
// (http://www.TiddlyTools.com/#AutoTaggerPlugin).
// The create date must be stored in the default format "YYYY.0MM.0DD".
//
// @return [may be null] the create date (as a String) or null if no create 
// date is found.
//
version.extensions.getCreateDate = {major: 1, minor: 0, revision: 0, 
 date: new Date(2005,11,21), 
 provider: "http://tiddlywiki.abego-software.de"};
//
function getCreateDate(tiddler) {
 if (!tiddler || !tiddler.tags) {
 return null;
 }

 for(var i = 0; i < tiddler.tags.length; i++) {
 var matches = tiddler.tags[i].match(/^[0-9]{4}\.[0-9]{2}\.[0-9]{2}$/);
 if (matches && matches.length > 0) {
 return matches[0];
 }
 }
 return null;
}

//}}}
/***
|''Name:''|zh-HantTranslationPlugin|
|''Description:''|Translation of TiddlyWiki into Traditional Chinese|
|''Source:''|http://tiddlywiki-zh.googlecode.com/svn/trunk/|
|''Subversion:''|http://svn.tiddlywiki.org/Trunk/association/locales/core/zh-Hant/locale.zh-Hant.js|
|''Author:''|BramChen (bram.chen (at) gmail (dot) com)|
|''Version:''|2.2.6|
|''Date:''|Dec 01, 2007|
|''Comments:''|Please make comments at http://groups-beta.google.com/group/TiddlyWiki-zh/|
|''License:''|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|''~CoreVersion:''|2.2.0|
***/

//{{{
// --
// -- Translateable strings
// --

// Strings in "double quotes" should be translated; strings in 'single quotes' should be left alone

config.locale = 'zh-Hant'; // W3C language tag

if (config.options.txtUserName == 'YourName' || !config.options.txtUserName) // do not translate this line, but do translate the next line
	merge(config.options,{txtUserName: "YourName"});

merge(config.tasks,{
	save: {text: "儲存", tooltip: "儲存變更至此 TiddlyWiki", action: saveChanges},
	sync: {text: "同步", tooltip: "將你的資料內容與外部伺服器與檔案同步", content: '<<sync>>'},
	importTask: {text: "導入", tooltip: "自其他檔案或伺服器導入文章或套件", content: '<<importTiddlers>>'},
	tweak: {text: "選項", tooltip: "改變此 TiddlyWiki 的顯示與行為的設定", content: '<<options>>'},
	plugins: {text: "套件管理", tooltip: "管理已安裝的套件", content: '<<plugins>>'}
});

merge(config.optionsDesc,{
	txtUserName: "編輯文章所使用之作者署名",
	chkRegExpSearch: "啟用正規式搜尋",
	chkCaseSensitiveSearch: "搜尋時,區分大小寫",
	chkAnimate: "使用動畫顯示",
	chkSaveBackups: "儲存變更前,保留備份檔案",
	chkAutoSave: "自動儲存變更",
	chkGenerateAnRssFeed: "儲存變更時,也儲存 RSS feed",
	chkSaveEmptyTemplate: "儲存變更時,也儲存空白範本",
	chkOpenInNewWindow: "於新視窗開啟連結",
	chkToggleLinks: "點擊已開啟文章將其關閉",
	chkHttpReadOnly: "非本機瀏覽文件時,隱藏編輯功能",
	chkForceMinorUpdate: "修改文章時,不變更作者名稱與日期時間",
	chkConfirmDelete: "刪除文章前須確認",
	chkInsertTabs: "使用 tab 鍵插入定位字元,而非跳至下一個欄位",
	txtBackupFolder: "存放備份檔案的資料夾",
	txtMaxEditRows: "編輯模式中顯示列數",
	txtFileSystemCharSet: "指定儲存文件所在之檔案系統之字集 (僅適用於 Firefox/Mozilla only)"});

// Messages
merge(config.messages,{
	customConfigError: "套件載入發生錯誤,詳細請參考 PluginManager",
	pluginError: "發生錯誤: %0",
	pluginDisabled: "未執行,因標籤設為 'systemConfigDisable'",
	pluginForced: "已執行,因標籤設為 'systemConfigForce'",
	pluginVersionError: "未執行,套件需較新版本的 TiddlyWiki",
	nothingSelected: "尚未作任何選擇,至少需選擇一項",
	savedSnapshotError: "此 TiddlyWiki 未正確存檔,詳見 http://www.tiddlywiki.com/#DownloadSoftware",
	subtitleUnknown: "(未知)",
	undefinedTiddlerToolTip: "'%0' 尚無內容",
	shadowedTiddlerToolTip: "'%0' 尚無內容, 但已定義隱藏的預設值",
	tiddlerLinkTooltip: "%0 - %1, %2",
	externalLinkTooltip: "外部連結至 %0",
	noTags: "未設定標籤的文章",
	notFileUrlError: "須先將此 TiddlyWiki 存至檔案,才可儲存變更",
	cantSaveError: "無法儲存變更。可能的原因有:\n- 你的瀏覽器不支援此儲存功能(Firefox, Internet Explorer, Safari and Opera 經適當設定後可儲存變更)\n- 也可能是你的 TiddlyWiki 檔名包含不合法的字元所致。\n- 或是 TiddlyWiki 文件被改名或搬移。",
	invalidFileError: " '%0' 非有效之 TiddlyWiki 文件",
	backupSaved: "已儲存備份",
	backupFailed: "無法儲存備份",
	rssSaved: "RSS feed 已儲存",
	rssFailed: "無法儲存 RSS feed ",
	emptySaved: "已儲存範本",
	emptyFailed: "無法儲存範本",
	mainSaved: "主要的TiddlyWiki已儲存",
	mainFailed: "無法儲存主要 TiddlyWiki,所作的改變未儲存",
	macroError: "巨集 <<\%0>> 執行錯誤",
	macroErrorDetails: "執行巨集 <<\%0>> 時,發生錯誤 :\n%1",
	missingMacro: "無此巨集",
	overwriteWarning: "'%0' 已存在,[確定]覆寫之",
	unsavedChangesWarning: "注意! 尚未儲存變更\n\n[確定]存檔,或[取消]放棄存檔?",
	confirmExit: "--------------------------------\n\nTiddlyWiki 以更改內容尚未儲存,繼續的話將遺失這些更動\n\n--------------------------------",
	saveInstructions: "SaveChanges",
	unsupportedTWFormat: "未支援此 TiddlyWiki 格式:'%0'",
	tiddlerSaveError: "儲存文章 '%0' 時,發生錯誤。",
	tiddlerLoadError: "載入文章 '%0' 時,發生錯誤。",
	wrongSaveFormat: "無法使用格式 '%0' 儲存,請使用標准格式存放",
	invalidFieldName: "無效的欄位名稱:%0",
	fieldCannotBeChanged: "無法變更欄位:'%0'",
	loadingMissingTiddler: "正從伺服器 '%1' 的:\n\n工作區 '%3' 中的 '%2' 擷取文章 '%0'"});

merge(config.messages.messageClose,{
	text: "關閉",
	tooltip: "關閉此訊息"});

config.messages.backstage = {
	open: {text: "控制台", tooltip: "開啟控制台執行編寫工作"},
	close: {text: "關閉", tooltip: "關閉控制台"},
	prompt: "控制台:",
	decal: {
		edit: {text: "編輯", tooltip: "編輯 '%0'"}
	}
};

config.messages.listView = {
	tiddlerTooltip: "檢視全文",
	previewUnavailable: "(無法預覽)"
};

config.messages.dates.months = ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"];
config.messages.dates.days = ["星期日", "星期一","星期二", "星期三", "星期四", "星期五", "星期六"];
// config.messages.dates.shortMonths = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
config.messages.dates.shortMonths = ["一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二"];
// config.messages.dates.shortDays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
config.messages.dates.shortDays = ["日", "一","二", "三", "四", "五", "六"];
// suffixes for dates, eg "1st","2nd","3rd"..."30th","31st"
config.messages.dates.daySuffixes = ["st","nd","rd","th","th","th","th","th","th","th",
		"th","th","th","th","th","th","th","th","th","th",
		"st","nd","rd","th","th","th","th","th","th","th",
		"st"];
config.messages.dates.am = "上午";
config.messages.dates.pm = "下午";

merge(config.messages.tiddlerPopup,{ 
	});

merge(config.views.wikified.tag,{
	labelNoTags: "未設標籤",
	labelTags: "標籤: ",
	openTag: "開啟標籤 '%0'",
	tooltip: "顯示標籤為 '%0' 的文章",
	openAllText: "開啟以下所有文章",
	openAllTooltip: "開啟以下所有文章",
	popupNone: "僅此文標籤為 '%0'"});

merge(config.views.wikified,{
	defaultText: "",
	defaultModifier: "(未完成)",
	shadowModifier: "(預設)",
	dateFormat: "YYYY年0MM月0DD日",
	createdPrompt: "建立於"});

merge(config.views.editor,{
	tagPrompt: "設定標籤之間以空白區隔,[[標籤含空白時請使用雙中括弧]],或點選現有之標籤加入",
	defaultText: ""});

merge(config.views.editor.tagChooser,{
	text: "標籤",
	tooltip: "點選現有之標籤加至本文章",
	popupNone: "未設定標籤",
	tagTooltip: "加入標籤 '%0'"});

merge(config.messages,{
	sizeTemplates:
		[
		{unit: 1024*1024*1024, template: "%0\u00a0GB"},
		{unit: 1024*1024, template: "%0\u00a0MB"},
		{unit: 1024, template: "%0\u00a0KB"},
		{unit: 1, template: "%0\u00a0B"}
		]});

merge(config.macros.search,{
	label: " 尋找",
	prompt: "搜尋本 Wiki",
	accessKey: "F",
	successMsg: " %0 篇符合條件: %1",
	failureMsg: " 無符合條件: %0"});

merge(config.macros.tagging,{
	label: "引用標籤:",
	labelNotTag: "無引用標籤",
	tooltip: "列出標籤為 '%0' 的文章"});

merge(config.macros.timeline,{
	dateFormat: "YYYY年0MM月0DD日"});

merge(config.macros.allTags,{
	tooltip: "顯示文章- 標籤為'%0'",
	noTags: "沒有標籤"});

config.macros.list.all.prompt = "依字母排序";
config.macros.list.missing.prompt = "被引用且內容空白的文章";
config.macros.list.orphans.prompt = "未被引用的文章";
config.macros.list.shadowed.prompt = "這些隱藏的文章已預設內容";
config.macros.list.touched.prompt = "自下載或新增後被修改過的文章"; 

merge(config.macros.closeAll,{
	label: "全部關閉",
	prompt: "關閉所有開啟中的 tiddler (編輯中除外)"});

merge(config.macros.permaview,{
	label: "引用連結",
	prompt: "可存取現有開啟之文章的連結位址"});

merge(config.macros.saveChanges,{
	label: "儲存變更",
	prompt: "儲存所有文章,產生新的版本",
	accessKey: "S"});

merge(config.macros.newTiddler,{
	label: "新增文章",
	prompt: "新增 tiddler",
	title: "新增文章",
	accessKey: "N"});

merge(config.macros.newJournal,{
	label: "新增日誌",
	prompt: "新增 jounal",
	accessKey: "J"});

merge(config.macros.options,{
	wizardTitle: "增訂的進階選項",
	step1Title: "增訂的選項儲存於瀏覽器的 cookies",
	step1Html: "<input type='hidden' name='markList'></input><br><input type='checkbox' checked='false' name='chkUnknown'>顯示未知選項</input>",
	unknownDescription: "//(未知)//",
	listViewTemplate: {
		columns: [
			{name: 'Option', field: 'option', title: "選項", type: 'String'},
			{name: 'Description', field: 'description', title: "說明", type: 'WikiText'},
			{name: 'Name', field: 'name', title: "名稱", type: 'String'}
			],
		rowClasses: [
			{className: 'lowlight', field: 'lowlight'}
			]}
	});

merge(config.macros.plugins,{
	wizardTitle: "擴充套件管理",
	step1Title: "- 已載入之套件",
	step1Html: "<input type='hidden' name='markList'></input>", // DO NOT TRANSLATE
	skippedText: "(此套件因剛加入,故尚未執行)",
	noPluginText: "未安裝套件",
	confirmDeleteText: "確認是否刪除此文章:\n\n%0",
	removeLabel: "移除 systemConfig 標籤",
	removePrompt: "移除 systemConfig 標籤",
	deleteLabel: "刪除",
	deletePrompt: "永遠刪除所選",

	listViewTemplate : {
		columns: [
			{name: 'Selected', field: 'Selected', rowName: 'title', type: 'Selector'},
			{name: 'Tiddler', field: 'tiddler', title: "套件", type: 'Tiddler'},
			{name: 'Size', field: 'size', tiddlerLink: 'size', title: "大小", type: 'Size'},
			{name: 'Forced', field: 'forced', title: "強制執行", tag: 'systemConfigForce', type: 'TagCheckbox'},
			{name: 'Disabled', field: 'disabled', title: "停用", tag: 'systemConfigDisable', type: 'TagCheckbox'},
			{name: 'Executed', field: 'executed', title: "已載入", type: "Boolean", trueText: "是", falseText: "否"},
			{name: 'Startup Time', field: 'startupTime', title: "載入時間", type: 'String'},
			{name: 'Error', field: 'error', title: "載入狀態", type: 'Boolean', trueText: "錯誤", falseText: "正常"},
			{name: 'Log', field: 'log', title: "紀錄", type: 'StringList'}
			],
		rowClasses: [
			{className: 'error', field: 'error'},
			{className: 'warning', field: 'warning'}
			]}
	});

merge(config.macros.toolbar,{
	moreLabel: "其他",
	morePrompt: "顯示更多工具命令"});
	
merge(config.macros.refreshDisplay,{
	label: "刷新",
	prompt: "刷新此 TiddlyWiki 顯示"
	});
	
merge(config.macros.importTiddlers,{
	readOnlyWarning: "TiddlyWiki 於唯讀模式下,不支援導入文章。請由本機(file://)開啟 TiddlyWiki 文件",
	wizardTitle: "自其他檔案或伺服器導入文章",
	step1Title: "步驟一:指定伺服器或來源文件",
	step1Html: "指定伺服器類型:<select name='selTypes'><option value=''>選取...</option></select><br>請輸入網址或路徑:<input type='text' size=50 name='txtPath'><br>...或選擇來源文件:<input type='file' size=50 name='txtBrowse'><br><hr>...或選擇指定的饋入來源:<select name='selFeeds'><option value=''>選取...</option></select>",
	openLabel: "開啟",
	openPrompt: "開啟檔案或",
	openError: "讀取來源文件時發生錯誤",
	statusOpenHost: "正與伺服器建立連線",
	statusGetWorkspaceList: "正在取得可用之文章清單",
	step2Title: "步驟二:選擇工作區",
	step2Html: "輸入工作區名稱:<input type='text' size=50 name='txtWorkspace'><br>...或選擇工作區:<select name='selWorkspace'><option value=''>選取...</option></select>",
	cancelLabel: "取消",
	cancelPrompt: "取消本次導入動作",
	statusOpenWorkspace: "正在開啟工作區",
	statusGetTiddlerList: "正在取得可用之文章清單",
	step3Title: "步驟三:選擇欲導入之文章",
	step3Html: "<input type='hidden' name='markList'></input><br><input type='checkbox' checked='true' name='chkSync'>保持這些文章與伺服器的連結,便於同步後續的變更。</input><br><input type='checkbox' name='chkSave'>儲存此伺服器的詳細資訊於標籤為 'systemServer' 的文章名為:</input> <input type='text' size=25 name='txtSaveTiddler'>", 
	importLabel: "導入",
	importPrompt: "導入所選文章",
	confirmOverwriteText: "確定要覆寫這些文章:\n\n%0",
	step4Title: "步驟四:正在導入%0 篇文章",
	step4Html: "<input type='hidden' name='markReport'></input>", // DO NOT TRANSLATE
	doneLabel: "完成",
	donePrompt: "關閉",
	statusDoingImport: "正在導入文章 ...",
	statusDoneImport: "所選文章已導入",
	systemServerNamePattern: "%2 位於 %1",
	systemServerNamePatternNoWorkspace: "%1",
	confirmOverwriteSaveTiddler: "此 tiddler '%0' 已經存在。點擊「確定」以伺服器上料覆寫之,或「取消」不變更後離開",
	serverSaveTemplate: "|''Type:''|%0|\n|''網址:''|%1|\n|''工作區:''|%2|\n\n此文為自動產生紀錄伺服器之相關資訊。",
	serverSaveModifier: "(系統)",

	listViewTemplate: {
		columns: [
			{name: 'Selected', field: 'Selected', rowName: 'title', type: 'Selector'},
			{name: 'Tiddler', field: 'tiddler', title: "文章", type: 'Tiddler'},
			{name: 'Size', field: 'size', tiddlerLink: 'size', title: "大小", type: 'Size'},
			{name: 'Tags', field: 'tags', title: "標籤", type: 'Tags'}
			],
		rowClasses: [
			]}
	});

merge(config.macros.sync,{
	listViewTemplate: {
		columns: [
			{name: 'Selected', field: 'selected', rowName: 'title', type: 'Selector'},
			{name: 'Tiddler', field: 'tiddler', title: "文章", type: 'Tiddler'},
			{name: 'Server Type', field: 'serverType', title: "伺服器類型", type: 'String'},
			{name: 'Server Host', field: 'serverHost', title: "伺服器主機", type: 'String'},
			{name: 'Server Workspace', field: 'serverWorkspace', title: "伺服器工作區", type: 'String'},
			{name: 'Status', field: 'status', title: "同步情形", type: 'String'},
			{name: 'Server URL', field: 'serverUrl', title: "伺服器網址", text: "View", type: 'Link'}
			],
		rowClasses: [
			],
		buttons: [
			{caption: "同步更新這些文章", name: 'sync'}
			]},
	wizardTitle: "將你的資料內容與外部伺服器與檔案同步",
	step1Title: "選擇欲同步的文章",
	step1Html: '<input type="hidden" name="markList"></input>', // DO NOT TRANSLATE
	syncLabel: "同步",
	syncPrompt: "同步更新這些文章",
	hasChanged: "已更動",
	hasNotChanged: "未更動",
	syncStatusList: {
		none: {text: "...", color: 'transparent'},
		changedServer: {text: "伺服器資料已更動", color: '#80ff80'},
		changedLocally: {text: "本機資料已更動", color: '#80ff80'},
		changedBoth: {text: "已同時更新本機與伺服器上的資料", color: '#ff8080'},
		notFound: {text: "伺服器無此資料", color: '#ffff80'},
		putToServer: {text: "已儲存更新資料至伺服器", color: '#ff80ff'},
		gotFromServer: {text: "已從伺服器擷取更新資料", color: '#80ffff'}
		}
	});

merge(config.macros.annotations,{
	});

merge(config.commands.closeTiddler,{
	text: "關閉",
	tooltip: "關閉本文"});

merge(config.commands.closeOthers,{
	text: "關閉其他",
	tooltip: "關閉其他文章"});

merge(config.commands.editTiddler,{
	text: "編輯",
	tooltip: "編輯本文",
	readOnlyText: "檢視",
	readOnlyTooltip: "檢視本文之原始內容"});

merge(config.commands.saveTiddler,{
	text: "完成",
	tooltip: "確定修改"});

merge(config.commands.cancelTiddler,{
	text: "取消",
	tooltip: "取消修改",
	warning: "確定取消對 '%0' 的修改嗎?",
	readOnlyText: "完成",
	readOnlyTooltip: "返回正常顯示模式"});

merge(config.commands.deleteTiddler,{
	text: "刪除",
	tooltip: "刪除文章",
	warning: "確定刪除 '%0'?"});

merge(config.commands.permalink,{
	text: "引用連結",
	tooltip: "本文引用連結"});

merge(config.commands.references,{
	text: "引用",
	tooltip: "引用本文的文章",
	popupNone: "本文未被引用"});

merge(config.commands.jump,{
	text: "捲頁",
	tooltip: "捲頁至其他已開啟的文章"});

merge(config.commands.syncing,{
	text: "同步",
	tooltip: "本文章與伺服器或其他外部檔案的同步資訊",
	currentlySyncing: "<div>同步類型:<span class='popupHighlight'>'%0'</span></"+"div><div>與伺服器:<span class='popupHighlight'>%1 同步</span></"+"div><div>工作區:<span class='popupHighlight'>%2</span></"+"div>", // Note escaping of closing <div> tag
	notCurrentlySyncing: "無進行中的同步動作",
	captionUnSync: "停止同步此文章",
	chooseServer: "與其他伺服器同步此文章:",
	currServerMarker: "\u25cf ",
	notCurrServerMarker: "  "});

merge(config.commands.fields,{
	text: "欄位",
	tooltip: "顯示此文章的擴充資訊",
	emptyText: "此文章沒有擴充欄位",
	listViewTemplate: {
		columns: [
			{name: 'Field', field: 'field', title: "擴充欄位", type: 'String'},
			{name: 'Value', field: 'value', title: "內容", type: 'String'}
			],
		rowClasses: [
			],
		buttons: [
			]}});

merge(config.shadowTiddlers,{
	DefaultTiddlers: "GettingStarted",
	GettingStarted: "使用此 TiddlyWiki 的空白範本之前,請先修改以下預設文章:\n* SiteTitle 及 SiteSubtitle:網站的標題和副標題,顯示於頁面上方<br />(在儲存變更後,將顯示於瀏覽器視窗的標題列)。\n* MainMenu:主選單(通常在頁面左側)。\n* DefaultTiddlers:內含一些文章的標題,可於載入TiddlyWiki 後的預設開啟。\n請輸入您的大名,作為所建立/ 編輯的文章署名:<<option txtUserName>>",
	MainMenu: "[[使用說明|GettingStarted]]\n\n\n^^~TiddlyWiki 版本:<<version>>\n© 2007 [[UnaMesa|http://www.unamesa.org/]]^^",
	OptionsPanel: "這些設定將暫存於瀏覽器\n請簽名<<option txtUserName>>\n (範例:WikiWord)\n\n <<option chkSaveBackups>> 儲存備份\n <<option chkAutoSave>> 自動儲存\n <<option chkRegExpSearch>> 正規式搜尋\n <<option chkCaseSensitiveSearch>> 區分大小寫搜尋\n <<option chkAnimate>> 使用動畫顯示\n----\n [[進階選項|AdvancedOptions]]",
	SiteTitle: "我的 TiddlyWiki",
	SiteSubtitle: "一個可重複使用的個人網頁式筆記本",
	SiteUrl: 'http://www.tiddlywiki.com/',
	SideBarOptions: '<<search>><<closeAll>><<permaview>><<newTiddler>><<newJournal " YYYY年0MM月0DD日" "日誌">><<saveChanges>><<slider chkSliderOptionsPanel OptionsPanel  "偏好設定 »" "變更 TiddlyWiki 選項">>',
	SideBarTabs: '<<tabs txtMainTab "最近更新" "依更新日期排序" TabTimeline "全部" "所有文章" TabAll "分類" "所有標籤" TabTags "更多" "其他" TabMore>>',
	StyleSheet: '[[StyleSheetLocale]]',
	TabMore: '<<tabs txtMoreTab "未完成" "內容空白的文章" TabMoreMissing "未引用" "未被引用的文章" TabMoreOrphans "預設文章" "已預設內容的隱藏文章" TabMoreShadowed>>'});

merge(config.annotations,{
	AdvancedOptions: "此預設文章可以存取一些進階選項。",
	ColorPalette: "此預設文章裡的設定值,將決定 ~TiddlyWiki 使用者介面的配色。",
	DefaultTiddlers: "當 ~TiddlyWiki 在瀏覽器中開啟時,此預設文章裡列出的文章,將被自動顯示。",
	EditTemplate: "此預設文章裡的 HTML template 將決定文章進入編輯模式時的顯示版面。",
	GettingStarted: "此預設文章提供基本的使用說明。",
	ImportTiddlers: "此預設文章提供存取導入中的文章。",
	MainMenu: "此預設文章的內容,為於螢幕左側主選單的內容",
	MarkupPreHead: "此文章的內容將加至 TiddlyWiki 文件的 <head> 段落的起始",
	MarkupPostHead: "此文章的內容將加至 TiddlyWiki 文件的 <head> 段落的最後",
	MarkupPreBody: "此文章的內容將加至 TiddlyWiki 文件的 <body> 段落的起始",
	MarkupPostBody: "此文章的內容將加至 TiddlyWiki 文件的 <body> 段落的最後,於 script 區塊之前",
	OptionsPanel: "此預設文章的內容,為於螢幕右側副選單中的選項面板裡的內容",
	PageTemplate: "此預設文章裡的 HTML template 決定的 ~TiddlyWiki 主要的版面配置",
	PluginManager: "此預設文章提供存取套件管理員",
	SideBarOptions: "此預設文章的內容,為於螢幕右側副選單中選項面板裡的內容",
	SideBarTabs: "此預設文章的內容,為於螢幕右側副選單中的頁籤面板裡的內容",
	SiteSubtitle: "此預設文章的內容為頁面的副標題",
	SiteTitle: "此預設文章的內容為頁面的主標題",
	SiteUrl: "此預設文章的內容須設定為文件發佈時的完整網址",
	StyleSheetColors: "此預設文章內含的 CSS 規則,為相關的頁面元素的配色。''勿修改此文'',請於 StyleSheet 中作增修。",
	StyleSheet: "此預設文章內容可包含 CSS 規則",
	StyleSheetLayout: "此預設文章內含的 CSS 規則,為相關的頁面元素的版面配置。''勿修改此文'',請於 StyleSheet 中作增修。",
	StyleSheetLocale: "此預設文章內含的 CSS 規則,可依翻譯語系做適當調整",
	StyleSheetPrint: "此預設文章內含的 CSS 規則,用於列印時的樣式",
	TabAll: "此預設文章的內容,為於螢幕右側副選單中的「全部」頁籤的內容",
	TabMore: "此預設文章的內容,為於螢幕右側副選單中的「更多」頁籤的內容",
	TabMoreMissing: "此預設文章的內容,為於螢幕右側副選單中的「未完成」頁籤的內容",
	TabMoreOrphans: "此預設文章的內容,為於螢幕右側副選單中的「未引用」頁籤的內容",
	TabMoreShadowed: "此預設文章的內容,為於螢幕右側副選單中的「預設文章」頁籤的內容",
	TabTags: "此預設文章的內容,為於螢幕右側副選單中的「分類」頁籤的內容",
	TabTimeline: "此預設文章的內容,為於螢幕右側副選單中的「最近更新」頁籤的內容",
	ViewTemplate: "此預設文章裡的 HTML template 決定文章顯示的樣子"
	});
//}}}
/***
|Name|ShowUpdatesPlugin|
|Created by|SaqImtiaz|
|Version|0.2 |
|Requires|~TW2.x|
!!!Description:
Allows you to list tiddlers that have changed since the users last visit. You can list only all changed tiddlers, or filter them to only show tiddlers that have or do not have a specific tag. By default a simple list of the titles of changed tiddlers is created. However, using an extremely versatile syntax you can provide a custom template for the generated text.

!!!Installation:
Copy the contents of this tiddler to your TW, tag with systemConfig, save and reload your TW.

!!!Syntax:
{{{<<showUpdates>>}}}
additional optional params:
{{{<showUpdates excludeTag:TagToExclude onlyTag:TagToList maxEntries:10 write:CustomWriteParameter >>}}}
excludeTag: ~TagToExclude
onlyTag: ~TagToList
maxEntries: max number of entries displayed when there are no updates. (default is 10, which can be changed in the config.macros.showUpdates.settings part of the code)
write: if a write parameter is not provided, an un-numbered list of the updates is generated. Alternatively, you can specify a custom 'template' for the text generated. The syntax for the write parameter is identical to that of the forEachTiddler macro. Additonal documentation on this syntax will be provided soon.
Some of the variables available in the write parameter are 'index', 'count' and 'lastVisit' where lastVisit is the date of the last visit in the format YYYYMMDDHHMM. Also areUpdates is a boolean that is true if there are new updates since the users last visit.

!!!To Do:
*refactor code to facilitate translations
*a streamlined version without the custom write parameter


!!!Code
***/
//{{{
window.lewcidLastVisit = '';
window.old_lewcid_whatsnew_restart = window.restart;
window.restart = function()
{
        if(config.options.txtLastVisit)
                 lewcidLastVisit= config.options.txtLastVisit;
        config.options.txtLastVisit = (new Date()).convertToYYYYMMDDHHMM();
        saveOptionCookie('txtLastVisit');
        window.old_lewcid_whatsnew_restart();
}

TiddlyWiki.prototype.lewcidGetTiddlers = function(field,excludeTag,includeTag,updatesOnly)
{
              var results = [];
              this.forEachTiddler(function(title,tiddler)
                      {
                      if(excludeTag == undefined || !tiddler.isTagged(excludeTag))
                                    if(includeTag == undefined ||  tiddler.isTagged(includeTag))
                                            if ( updatesOnly == false || tiddler.modified.convertToYYYYMMDDHHMM()>lewcidLastVisit)
                                                  results.push(tiddler);
                      });
              if(field)
                  results.sort(function (a,b) {if(a[field] == b[field]) return(0); else return (a[field] < b[field]) ? -1 : +1; });
              return results;
}

config.macros.showUpdates={};
config.macros.showUpdates.settings =
{
         maxEntries: 10  //max items to show, if there are no updates since last visit
}

config.macros.showUpdates.handler = function(place,macroName,params,wikifier,paramString,tiddler)
{
          var args = paramString.parseParams("list",null,true);
          var write = getParam(args, "write", undefined);
          var onlyTag = getParam(args, "onlyTag", undefined);
          var excludeTag = getParam(args, "excludeTag", undefined);
          var sortBy = "modified";
          var maxEntries = getParam(args,"maxEntries",this.settings.maxEntries);

          if (lewcidLastVisit) 
                {var tiddlers = store.lewcidGetTiddlers(sortBy,excludeTag,onlyTag,true);
                 var areUpdates = tiddlers.length>0? true:false;}

          //if (!lewcidLastVisit)
          //     {var countLine = "!!最近的更新:";
                  var tiddlers = store.lewcidGetTiddlers(sortBy,excludeTag,onlyTag,false);
                  var areUpdates = false;
          //     }
          //else if (tiddlers.length == 0)
          //     {var countLine = "!!@@color:red;上次拜訪後, 沒有任何更新 " + (Date.convertFromYYYYMMDDHHMM(lewcidLastVisit)).formatString(" (DD/MM/YY)") + "@@\n!!最近的更新:";
         //      var tiddlers = store.lewcidGetTiddlers(sortBy,excludeTag,onlyTag,false);}
         // else
         //      {var countLine ="!!@@ 自從上次拜訪後, 共有 "+ tiddlers.length +" 更新 " + (Date.convertFromYYYYMMDDHHMM(lewcidLastVisit)).formatString(" (DD/MM/YY)") + "@@";}

          tiddlers = tiddlers.reverse();
          var lastVisit = lewcidLastVisit? lewcidLastVisit:undefined;
          var count = areUpdates == true? tiddlers.length : maxEntries;
          var sp = createTiddlyElement(place,"span","showUpdates");
          if (write==undefined)
                 {
                  //wikify(countLine,sp);
                  var list = createTiddlyElement(sp,"ul");
                  for (var i = 0; i < count; i++)
                          {
                           var tiddler = tiddlers[i];
                           createTiddlyLink(createTiddlyElement(list,"li"), tiddler.title, true);
                          }
                 }
          else
                {
                 var list = '';
                 for (var index = 0; index < count; index++) {
                 var tiddler = tiddlers[index];
                 list += eval(write); }
                 wikify(list, sp);
                }
}
//}}}
/***
|''巨集名稱:''|toBalaAjax|
|''版本:''|2.1 (2008-06-28)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''| |
***/

//{{{
config.macros.toBalaAjax={
	
	editLabel: "編輯網頁",
	editTip: "編輯網頁",
        saveLabel: "儲存網頁",
	saveTip: "儲存網頁",
        openLabel: "檢視網頁",
	openTip: "檢視網頁",
        cancelLabel: "取消編輯",
	cancelTip: "取消編輯",
    
	GUIEditButtonOnclick: function(e,xtiddler,xbox,xfname,xx,yy) {

            if (config.browser.isIE) {
               window.event.cancelBubble=true;
            } else {  
               e.cancelBubble = true;   
               if (e.stopPropagation)  
                  e.stopPropagation();
            }

            removeChildren(xbox);

            var boxtool = createTiddlyElement(xbox,"div",null,"toBalaFileToolBar",null,null);
            var boxtext = createTiddlyElement(xbox,"textarea",null,null,null,null);
            wikify("@@color:#841;border:2px dotted #841;padding:2px;檔案 : <nowiki>"+xfname+"</nowiki>@@ ",boxtool);

            createTiddlyButton(boxtool,this.saveLabel,this.saveTip,
                            function(e) { config.macros.toBalaAjax.GUISaveButtonOnclick(e,xtiddler,xbox,xfname,boxtext,xx,yy); },
                            "toBalaFileSave",null,null);
	    createTiddlyButton(boxtool,this.cancelLabel,this.cancelTip,
                            function(e) { config.macros.toBalaAjax.GUICancelButtonOnclick(e,xtiddler,xbox,xfname,xx,yy); },
                            "toBalaFileCancel",null,null);

            // alert(xtitle+":"+xx+":"+yy);
            boxtext.setAttribute("rows",20);
            boxtext.setAttribute("cols",88);
            boxtext.value = xtiddler.text.substring(xx,yy);
        },

	GUISaveButtonOnclick: function(e,xtiddler1,xbox1,xfname1,boxtext1,xx1,yy1) {

            if (config.browser.isIE) {
               window.event.cancelBubble=true;
            } else {  
               e.cancelBubble = true;   
               if (e.stopPropagation)  
                  e.stopPropagation();
            }
 
            removeChildren(xbox1);
            var xtext=boxtext1.value;
            if (config.browser.isIE) {              
               xtext=xtext.replace(/\r/g,"");   // 請看最後的註解
            }
            var toptext=xtiddler1.text.substring(0,xx1);
            var bottomtext=xtiddler1.text.substring(yy1);
            xtext = (xtext.charAt(xtext.length-1) == "\n" ? xtext : xtext+"\n");
            xtiddler1.text=toptext+xtext+bottomtext;

            story.refreshTiddler(xtiddler1.title,null,true);
            saveChanges(false);              // 參數 false, 代表不管 Dirty 與否, 均要執行存檔動作

            var baseDIR = getLocalPath(document.URL);
  
            if (config.browser.isWindows) {
                var baseDIR = baseDIR.replace(/\//g,"");
                var x = baseDIR.lastIndexOf("\\");
             } else {
                var x = baseDIR.lastIndexOf("/");
             }

            baseDIR = baseDIR.substr(0,x+1);

            var s = saveFile(baseDIR+ (config.browser.isWindows ? xfname1 : xfname1.replace(/\\/g,"\/")), 
                                          convertUnicodeToUTF8(boxtext1.value));
            if (!s) {
               alert("存檔失敗");
            }
        },

	GUICancelButtonOnclick: function(e,xtiddler1,xbox1,xfname1,xx1,yy1) {

            if (config.browser.isIE) {
               window.event.cancelBubble=true;
            } else {  
               e.cancelBubble = true;   
               if (e.stopPropagation)  
                  e.stopPropagation();
            }

            removeChildren(xbox1);

            var boxtool = createTiddlyElement(xbox1,"div",null,"toBalaFileToolBar",null,null);
            wikify("@@color:#841;border:2px dotted #841;padding:2px;檔案 : <nowiki>"+xfname1+"</nowiki>@@ ",boxtool);

	    createTiddlyButton(boxtool,this.editLabel,this.editTip,
                            function(e) { config.macros.toBalaAjax.GUIEditButtonOnclick(e,xtiddler1,xbox1,xfname1,xx1,yy1);},
                            "toBalaFileEdit",null,null);

	    createTiddlyButton(boxtool,this.openLabel,this.openTip,
                            function(e) { config.macros.toBalaAjax.openHTML(e,params[0],xwidth,xheight);},
                            "toBalaFileEdit",null,null);

             var boxarea = createTiddlyElement(xbox1,"div",null,null,null,null);
	     wikify("{{{\n"+xtiddler1.text.substring(xx1,yy1-1)+"\n}}}",boxarea);
        },

        openHTML: function(ev,xf,xw,xh) {

               if (config.browser.isIE) {
                  window.event.cancelBubble=true;
               } else {  
                  ev.cancelBubble=true;   
               if (ev.stopPropagation)  
                  ev.stopPropagation();
               }

               // 將視窗置中
               var winl = (screen.width-xw)/2;
               var wint = (screen.height-xh)/2;
               if (winl < 0) winl = 0;
               if (wint < 0) wint = 0;
               var settings = 'scrollbars=yes, resizable=yes, height='  + xh +  ', width=' + xw  + ',top='  + wint  + ',left='  + winl;

               xf=xf.replace(/\\/mg,"/");

               // alert(xf+":"+settings);
               var xwin=window.open(xf,"HTMLWIN",settings);
               xwin.window.focus();
        },

	handler : function(place,macroName,params,wikifier,paramString,tiddler){

                if (!params[0]) {
                  alert("請給檔名");
                  return;
                } 

                var xwidth = params[1] || 550;
                var xheight = params[2] || 400;

		var xtext=store.getTiddlerText(tiddler.title);
                var x1=xtext.indexOf("/"+"/"+"/"+"%" + params[0]);

                // 自動產生 TiddlyWiki 備註
                if (x1 == -1) { 
                   xtext=xtext+"\n\n/"+"/"+"/"+"%" + params[0] + "\n" + "/"+"/"+"%"+"/";
                   tiddler.text=xtext; 
                   story.refreshTiddler(tiddler.title,null,true); // 這個 Tiddler 會重新顯示, 也就是 handler 會再被執行一次
                   //saveChanges(false);
                 }
                var x2=xtext.indexOf("/"+"/"+"%"+"/",x1);
                x1=x1+params[0].length+5;

		var box = createTiddlyElement(place,"div",tiddler.title+"-"+x1,"toBalaFile",null,null);
                var boxtool = createTiddlyElement(box,"div",null,"toBalaFileToolBar",null,null);
                wikify("@@color:#841;border:2px dotted #841;padding:2px;檔案 : <nowiki>"+params[0]+"</nowiki>@@ ",boxtool);

                var boxtext = createTiddlyElement(box,"div",null,null,null,null);
		wikify("{{{\n"+xtext.substring(x1,x2-1)+"\n}}}",boxtext);

                if (readOnly) {
                   return;
                }
		createTiddlyButton(boxtool,this.editLabel,this.editTip,
                            function(e) { config.macros.toBalaAjax.GUIEditButtonOnclick(e,tiddler,box,params[0],x1,x2);},
                            "toBalaFileEdit",null,null);

		createTiddlyButton(boxtool,this.openLabel,this.openTip,
                            function(e) { config.macros.toBalaAjax.openHTML(e,params[0],xwidth,xheight);},
                            "toBalaFileEdit",null,null);
	}		
};

/*
HTML 的 textarea 標籤, 對於換行在不同的瀏覽器有不同的處理方式

As you may know, the humble line break actually has three forms depending on which operating system is doing the breaking. On Unix machines, a single newline character ‘\n’ does the job. On Macs, a carriage return ‘\r’ is used. DOS and Windows use both: ‘\r\n’. It’s one of those relatively subtle issues that can bite you hard if you don’t know what to look out for.
*/

//}}}
{{item1{使用格式}}}
{{{
<<toBalaAjax  "ajax\html\testAjax.htm">>
}}}

{{item1{實作範例}}}
<<toBalaAjax "ajax\html\testAjax.htm">>

///%ajax\html\testAjax.htm
<html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf8">
</head>

<body>
<h2 align=center>顯示網頁載入時間的警告視窗</h2>
<hr>

<script>
today = new Date();			// 產生日期物件
hour = today.getHours();		// 取得時數
minute = today.getMinutes();		// 取得分數
second = today.getSeconds();		// 取得秒數
string = "網頁載入時間是"+hour+"點"+minute+"分"+second+"秒";	// 連接字串
</script>
<a href="javascript:alert(string)">網頁載入時間</a>

<hr>
</body>
</html>
//%/
<<toBalaAjax "ajax\AjaxCall.htm" "700" "450">>

///%ajax\AjaxCall.htm
<!-- 
程式名稱 : AjaxCall.html
程式描述 : Call XMLHTTP Object
適用瀏覽器 : Firefox 2.0,IE 5.5
參考文件 : 
-->
<html>
	
<head>
	
<meta http-equiv="Expires" content="0">
<meta http-equiv="Content-Type" content="text/html; charset=utf8">

<script>
var xmlhttp
function show(){
 
 if (window.XMLHttpRequest) {
    netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
    xmlhttp = new XMLHttpRequest();    
 }
 else if (window.ActiveXObject){ 
    try {
          xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
         }
    catch (e){
      try{
         xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
        }
      catch (e){}
    }
 }

 xmlhttp.open(document.getElementById("c").value,document.getElementById("u").value,false);
 xmlhttp.send("");
 if (parseInt(xmlhttp.status)>300){
     alert(xmlhttp.status);
 }
 else {
  document.getElementById("h").innerHTML=xmlhttp.getAllResponseHeaders();
  
  if (xmlhttp.getResponseHeader("Content-Type") == "text/xml"){
  	 xmlobj=xmlhttp.responseXML;
     document.getElementById("x").innerHTML=xmlobj.getElementsByTagName('app')[0].firstChild.nodeValue;
  }
  else{
  	 document.getElementById("x").innerHTML="";
     var testFrame = document.getElementById("myFrame");
     var doc = testFrame.contentDocument;
     if (doc == undefined || doc == null)
        doc = testFrame.contentWindow.document;
     doc.open();
     doc.write(xmlhttp.responseText);
	 doc.close(); 
  }  
 }
}
</script>
</head>

<style type="text/css">
body {
 background-color:white;
}
</style>

<body>
<h2>Ajax 測試程式 (使用本機的瀏覽器以 "開啟檔案" 方式執行)</h2>
<hr>
Method: <input id="c" value="GET" style="width: 100px;" type="text"><span> (要大寫) </span><br> 
URL: <input style="width: 250px;" id="u" value="http://" type="text"><br>

<button onclick="show();">傳送命令</button>
<hr>

<b>Response Header</b>
<pre id="h"></pre>

<b>Response XML</b>
<pre id="x"></pre>

<b>Response HTML</b><br>
<iframe id="myFrame" height="30%" width="100%"></iframe>

</body>
</html>

<!--
HTTP Methods
-------------
HTTP defines eight methods (sometimes referred to as "verbs") indicating the desired 
action to be performed on the identified resource.

HEAD
    Asks for the response identical to the one that would correspond to a GET request, 
    but without the response body. This is useful for retrieving meta-information 
	written in response headers, without having to transport the entire content.
GET
    Requests a representation of the specified resource. By far the most common method
	used on the Web today. Should not be used for operations that cause side-effects 
	(using it for actions in web applications is a common mis-use). See 'safe methods' 
	below.
POST
    Submits data to be processed (e.g. from an HTML form) to the identified resource. 
	The data is included in the body of the request. This may result in the creation 
	of a new resource or the updates of existing resources or both.
PUT
    Uploads a representation of the specified resource.
DELETE
    Deletes the specified resource.
TRACE
    Echoes back the received request, so that a client can see what intermediate 
	servers are adding or changing in the request.
OPTIONS
    Returns the HTTP methods that the server supports. This can be used to check the 
	functionality of a web server.
CONNECT
    For use with a proxy that can change to being an SSL tunnel.


WebDAV added the following methods to HTTP:

    * PROPFIND — Used to retrieve properties, persisted as XML, from a resource. 
	             It is also overloaded to allow one to retrieve the collection 
				 structure (a.k.a. directory hierarchy) of a remote system.
    * PROPPATCH — Used to change and delete multiple properties on a resource 
	              in a single atomic act.
    * MKCOL — Used to create collections (a.k.a. directory).
    * COPY — Used to copy a resource from one URI to another.
    * MOVE — Used to move a resource from one URI to another.
    * LOCK — Used to put a lock on a resource. WebDAV supports both shared and 
	         exclusive locks.
    * UNLOCK — To remove a lock from a resource.

-->
//%/
/***
|''巨集名稱:''|toBalaApp|
|''版本:''|2.1 (2008-10-2)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''| |
***/
//{{{
config.macros.toBalaApp={
       mode:"open",

       handler : function(place,macroName,params,wikifier,paramString,tiddler){
                if (!params[0]) {
                  alert("請給檔名");
                  return;
                } 
		createTiddlyButton(place,"應用模式","應用模式", function(e) { config.macros.toBalaApp.onClick(params[0]); } );

                /* 下式的寫法, 在執行 handler 的同時也會執行 onClick, 這樣的執行方式不對, 所以請使用上式
                     createTiddlyButton(place,"應用模式","應用模式",this.onClick(params[0]));
                */ 
	},
       onClick : function(xapp) {
            // alert(this.mode+":"+xapp);
            if (this.mode=="open"){
               this.mode="close";
               document.getElementById("displayArea").style.display="none";
               document.getElementById("mainMenu").style.display="none";
               document.getElementById("ApplicationArea").style.display="block";
               document.getElementById("ApplicationArea").style.width="99.6%";
               document.getElementById("ApplicationArea").style.height=(window.screen.availHeight-200)+"px";
               document.getElementById("ApplicationArea").src=xapp;               
               return false;
            } else {
               this.mode="open";
               document.getElementById("displayArea").style.display="block";
               document.getElementById("mainMenu").style.display="block";
               document.getElementById("ApplicationArea").style.display="none";
               document.getElementById("ApplicationArea").src="";   
               return  false;
            }
        }	
};

//}}}
/***
|''巨集名稱:''|toBalaBackup|
|''版本:''|1.0 (2008-09-12)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0|
|''使用文件''| &lt;&lt;toBalaBackup '備份檔名'  '樹幹名'  '文章,文章,文章'&gt;&gt;|
***/

//{{{
// 自定的巨集變數, 開頭前三個字如為 txt, 結合 option 巨集會以文字欄處理, 前三個字如為 chk, 結合 option 巨集會以 checkbox 欄處理
config.options.txtBalaBackupFileName = config.options.txtBalaBackupFileName ? config.options.txtBalaBackupFileName : "toBalaBackup.html";
config.options.txtBalaTreeBody = config.options.txtBalaTreeBody ? config.options.txtBalaTreeBody : "";
config.options.txtBalaBackupOthers = config.options.txtBalaBackupOthers ? config.options.txtBalaBackupOthers : "首頁,MainMenu,SiteTitle,SiteSubtitle,00-控制台,StyleSheet";

config.macros.toBalaBackup = {};
config.macros.toBalaBackup.handler = function(place,macroName,params,wikifier,paramString,tiddler){

  if (readOnly) {
     return;
  }

  if (!params[0] && config.options.txtBalaBackupFileName == "") {
     alert("請給檔名");
     return;
  }
  var tbName = config.options.txtBalaBackupFileName != "" ? config.options.txtBalaBackupFileName : params[0];   // 備份檔名
  var tbTag = config.options.txtBalaTreeBody != "" ? config.options.txtBalaTreeBody : params[1] ;            // 備份主標籤
  var tbTD = config.options.txtBalaBackupOthers != "" ? config.options.txtBalaBackupOthers : params[2];      // 其它備份文章
  var label = params[3] || "備份資訊樹文章";
  var tooltip = params[4] || "備份資訊樹文章 : " + tbName;

  createTiddlyButton(place, label, tooltip,
       function(e) { config.macros.toBalaBackup.save(e, tbName, tbTag, tbTD); },
       null, null, null);
}

config.macros.toBalaBackup.save = function(ev,xfname,xtag, xtd) {

  if (config.browser.isIE) {
     window.event.cancelBubble=true;
  } else {  
     ev.cancelBubble = true;   
     if (ev.stopPropagation)  
        ev.stopPropagation();
  }

  var baseDIR = getLocalPath(document.URL);
  //alert(baseDIR);
  
   if (config.browser.isWindows) {
      var baseDIR = baseDIR.replace(/\//g,"");
      var x = baseDIR.lastIndexOf("\\");
   } else {
      var x = baseDIR.lastIndexOf("/");
   }

   baseDIR = baseDIR.substr(0,x+1);
   //alert(baseDIR);

   toBala.AllTiddlers = "";
   // 呼叫 toBalaLIB 的 getMainTree() 方法, 取出資訊樹的樹幹及所有文章抬頭
   if (xtag!="") {
      var tbTempArr = toBala.getMainTree(xtag);

      for(var i=0; i<tbTempArr.length; ++i)
           toBala.TagDigg(tbTempArr[i]);
   }

   // 取出資訊樹所有文章的 DIV 內容
   var tbText='<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /><body>\n<div id="storeArea">';
   if (toBala.AllTiddlers!="") {
      var tbArr = toBala.AllTiddlers.split(",");
      for(i=0;i<tbArr.length;++i){
         if (tbArr[i])
            tbText = tbText+ "\n" + toBala.getTiddlerDIV(tbArr[i]);
      }
   }
   // 取出指定文章的 DIV 內容
   if (xtd!=""){
      tbArr = xtd.split(",");
      for(i=0;i<tbArr.length;++i)
          tbText = tbText+ "\n" + toBala.getTiddlerDIV(tbArr[i]);
   }
   tbText = tbText + "</div></body></html>";

   var s = saveFile(baseDIR+ (config.browser.isWindows?xfname:xfname.replace(/\\/g,"\/")), convertUnicodeToUTF8(tbText));
   if (s) {
      saveChanges(true);
      alert("備份完成");
   } else {
      alert("備份失敗");
   }
}
//}}}
config.options.chkAutoSave=false;
config.options.chkSaveBackups=false;
config.options.txtUserName="toBala";
config.options.txtMaxEditRows=50;
config.options.chkHttpReadOnly=true;

config.options.chkHideTabsBarWhenSingleTab=true;

config.options.chkDisableWikiLinks=true;
config.options.chkAllowLinksFromShadowTiddlers=true;
config.options.chkDisableNonExistingWikiLinks=true;
/***
|''巨集名稱:''|toBalaCoreBackup|
|''版本:''|1.0 (2008-09-12)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0|
|''使用文件''| &lt;&lt;toBalaCoreBackup '備份檔名' '文章,文章,文章'&gt;&gt;|
***/

//{{{
// 自定的巨集變數, 開頭前三個字如為 txt, 結合 option 巨集會以文字欄處理, 前三個字如為 chk, 結合 option 巨集會以 checkbox 欄處理
config.options.txtBalaCoreBackupFileName = config.options.txtBalaCoreBackupFileName ? config.options.txtBalaCoreBackupFileName : "toBalaMacro.html";
config.options.txtBalaCoreBackupOthers = config.options.txtBalaCoreBackupOthers ? config.options.txtBalaCoreBackupOthers : "";

config.macros.toBalaCoreBackup = {};
config.macros.toBalaCoreBackup.handler = function(place,macroName,params,wikifier,paramString,tiddler){

  if (readOnly) {
     return;
  }

  if (!params[0] && config.options.txtBalaCoreBackupFileName == "") {
     alert("請給檔名");
     return;
  }
  var tbName = params[0] || config.options.txtBalaCoreBackupFileName;          // toBala 巨集備份檔名
  var tbTD = params[1] || config.options.txtBalaCoreBackupOthers;            // 其它備份文章
  var label = params[2] || "備份 toBala 巨集";
  var tooltip = params[3] || "備份 toBala 巨集 : " + tbName;

  createTiddlyButton(place, label, tooltip,
       function(e) { config.macros.toBalaCoreBackup.save(e, tbName, tbTD); },
       null, null, null);
}

config.macros.toBalaCoreBackup.save = function(ev,xfname, xtd) {

  if (config.browser.isIE) {
     window.event.cancelBubble=true;
  } else {  
     ev.cancelBubble = true;   
     if (ev.stopPropagation)  
        ev.stopPropagation();
  }

  var baseDIR = getLocalPath(document.URL);
  //alert(baseDIR);
  
   if (config.browser.isWindows) {
      var baseDIR = baseDIR.replace(/\//g,"");
      var x = baseDIR.lastIndexOf("\\");
   } else {
      var x = baseDIR.lastIndexOf("/");
   }

   baseDIR = baseDIR.substr(0,x+1);
   // alert(baseDIR);

   // 取出所有 toBala 巨集的 DIV 內容
   var tbT2 = store.getTaggedTiddlers("toBala");
   var tbText='<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /></head>';
   tbText = tbText + '<body>\n<div id="storeArea">';
   for (var i=0; i<tbT2.length; ++i) {
        tbText = tbText+ "\n" + toBala.getTiddlerDIV(tbT2[i].title);
   }

   // 取出指定文章的 DIV 內容
   if (xtd!=""){
      tbArr = xtd.split(",");
      for(i=0;i<tbArr.length;++i)
          tbText = tbText+ "\n" + toBala.getTiddlerDIV(tbArr[i]);
   }
   tbText = tbText + "</div></body></html>";

   var s = saveFile(baseDIR+ (config.browser.isWindows?xfname:xfname.replace(/\\/g,"\/")), convertUnicodeToUTF8(tbText));
   if (s) {
      saveChanges(true);
      alert("備份完成");
   } else {
      alert("備份失敗");
   }
}
//}}}
/***
|''巨集名稱:''|toBalaFile|
|''版本:''|1.0 (2008-05-09)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''||
***/

//{{{
config.macros.toBalaFile={
	
	editLabel: "編輯",
	editTip: "編輯",
        saveLabel: "儲存",
	saveTip: "儲存",
        cancelLabel: "取消",
	cancelTip: "取消",
    
	GUIEditButtonOnclick: function(e,xtiddler,xbox,xfname,xx,yy) {

            if (config.browser.isIE) {
               window.event.cancelBubble=true;
            } else {  
               e.cancelBubble = true;   
               if (e.stopPropagation)  
                  e.stopPropagation();
            }

            removeChildren(xbox);

            var boxtool = createTiddlyElement(xbox,"div",null,"toBalaFileToolBar",null,null);
            var boxtext = createTiddlyElement(xbox,"textarea",null,null,null,null);
            wikify("@@color:#841;border:2px dotted #841;padding:2px;檔案 : <nowiki>"+xfname+"</nowiki>@@ ",boxtool);

            createTiddlyButton(boxtool,this.saveLabel,this.saveTip,
                            function(e) { config.macros.toBalaFile.GUISaveButtonOnclick(e,xtiddler,xbox,xfname,boxtext,xx,yy); },
                            "toBalaFileSave",null,null);
	    createTiddlyButton(boxtool,this.cancelLabel,this.cancelTip,
                            function(e) { config.macros.toBalaFile.GUICancelButtonOnclick(e,xtiddler,xbox,xfname,xx,yy); },
                            "toBalaFileCancel",null,null);

            // alert(xtitle+":"+xx+":"+yy);
            boxtext.setAttribute("rows",20);
            boxtext.setAttribute("cols",88);
            boxtext.value = xtiddler.text.substring(xx,yy);
        },

	GUISaveButtonOnclick: function(e,xtiddler1,xbox1,xfname1,boxtext1,xx1,yy1) {

            if (config.browser.isIE) {
               window.event.cancelBubble=true;
            } else {  
               e.cancelBubble = true;   
               if (e.stopPropagation)  
                  e.stopPropagation();
            }
 
            removeChildren(xbox1);
            var xtext=boxtext1.value;
            if (config.browser.isIE) {              
               xtext=xtext.replace(/\r/g,"");   // 請看最後的註解
            }
            var toptext=xtiddler1.text.substring(0,xx1);
            var bottomtext=xtiddler1.text.substring(yy1);
            xtext = (xtext.charAt(xtext.length-1) == "\n" ? xtext : xtext+"\n");
            xtiddler1.text=toptext+xtext+bottomtext;

            story.refreshTiddler(xtiddler1.title,null,true);
            saveChanges(false);              // 參數 false, 代表不管 Dirty 與否, 均要執行存檔動作

            var baseDIR = getLocalPath(document.URL);
  
            if (config.browser.isWindows) {
                var baseDIR = baseDIR.replace(/\//g,"");
                var x = baseDIR.lastIndexOf("\\");
             } else {
                var x = baseDIR.lastIndexOf("/");
             }

            baseDIR = baseDIR.substr(0,x+1);

            var s = saveFile(baseDIR+ (config.browser.isWindows ? xfname1 : xfname1.replace(/\\/g,"\/")), 
                                          convertUnicodeToUTF8(boxtext1.value));
            if (!s) {
               alert("存檔失敗");
            }
        },

	GUICancelButtonOnclick: function(e,xtiddler1,xbox1,xfname1,xx1,yy1) {

            if (config.browser.isIE) {
               window.event.cancelBubble=true;
            } else {  
               e.cancelBubble = true;   
               if (e.stopPropagation)  
                  e.stopPropagation();
            }

            removeChildren(xbox1);

            var boxtool = createTiddlyElement(xbox1,"div",null,"toBalaFileToolBar",null,null);
            wikify("@@color:#841;border:2px dotted #841;padding:2px;檔案 : <nowiki>"+xfname1+"</nowiki>@@ ",boxtool);

	    createTiddlyButton(boxtool,this.editLabel,this.editTip,
                            function(e) { config.macros.toBalaFile.GUIEditButtonOnclick(e,xtiddler1,xbox1,xfname1,xx1,yy1);},
                            "toBalaFileEdit",null,null);

             var boxarea = createTiddlyElement(xbox1,"div",null,null,null,null);
	     wikify("{{{\n"+xtiddler1.text.substring(xx1,yy1-1)+"\n}}}",boxarea);
        },

	handler : function(place,macroName,params,wikifier,paramString,tiddler){

                if (!params[0]) {
                  alert("請給檔名");
                  return;
                } 

		var xtext=store.getTiddlerText(tiddler.title);
                var x1=xtext.indexOf("/"+"/"+"/"+"%" + params[0]);

                // 自動產生 TiddlyWiki 備註
                if (x1 == -1) { 
                   xtext=xtext+"\n\n/"+"/"+"/"+"%" + params[0] + "\n" + "/"+"/"+"%"+"/";
                   tiddler.text=xtext; 
                   story.refreshTiddler(tiddler.title,null,true); // 這個 Tiddler 會重新顯示, 也就是 handler 會再被執行一次
                   //saveChanges(false);
                 }
                var x2=xtext.indexOf("/"+"/"+"%"+"/",x1);
                x1=x1+params[0].length+5;

		var box = createTiddlyElement(place,"div",tiddler.title+"-"+x1,"toBalaFile",null,null);
                var boxtool = createTiddlyElement(box,"div",null,"toBalaFileToolBar",null,null);
                wikify("@@color:#841;border:2px dotted #841;padding:2px;檔案 : <nowiki>"+params[0]+"</nowiki>@@ ",boxtool);

                var boxtext = createTiddlyElement(box,"div",null,null,null,null);
		wikify("{{{\n"+xtext.substring(x1,x2-1)+"\n}}}",boxtext);

                if (readOnly) {
                   return;
                }
		createTiddlyButton(boxtool,this.editLabel,this.editTip,
                            function(e) { config.macros.toBalaFile.GUIEditButtonOnclick(e,tiddler,box,params[0],x1,x2);},
                            "toBalaFileEdit",null,null);
	}		
};

/*
HTML 的 textarea 標籤, 對於換行在不同的瀏覽器有不同的處理方式

As you may know, the humble line break actually has three forms depending on which operating system is doing the breaking. On Unix machines, a single newline character ‘\n’ does the job. On Macs, a carriage return ‘\r’ is used. DOS and Windows use both: ‘\r\n’. It’s one of those relatively subtle issues that can bite you hard if you don’t know what to look out for.
*/

//}}}
在文章中使用 toBalaFile 巨集, 可將巨集中所編輯的文字, 存入指定的檔案, 請看以下使用格式
{{{
<<toBalaFile "ajax\html\hello.htm">>

此巨集以 UTF-8 編碼, 儲存檔文字到檔案
}}}

__{{op1{實作範例}}}__
<<toBalaFile "ajax\html\hello.htm">>

///%ajax\html\hello.htm
<html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf8">
</head>

<body>
<h2 align=center>利用 JavaScript 來印出 "Hello World!"</h2>
<hr>
<script language="javascript">
	str = "Hello World!";
	document.write(str);
</script>
<hr>
</body>
</html>
//%/
{{item1{說明}}}
{{{

<<toBalaFile "檔名">>

}}}
{{item1{範例}}}
<<toBalaFile "xml\abc.xml">>


///%xml\abc.xml
<?xml version='1.0'?>
<root>
  <marble color="red"/>
  <marble color='red'/>
</root> 
//%/
/***
|''巨集名稱:''|toBalaFlashPlayer|
|''版本:''|1.0 (2008-03-06)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''| |
***/
//{{{
config.macros.toBalaFlashPlayer = {};

config.macros.toBalaFlashPlayer.handler = function(place,macroName,params,wikifier,paramString,tiddler){

  var xname = params[0] || tiddler.title;
  var label = params[1] || "撥放 " + xname;
  var xwidth = params[2] || 600;
  var xheight = params[3] || 450;

  createTiddlyButton(place, label, label,
       function(e) { config.macros.toBalaFlashPlayer.show(e, xname, xwidth, xheight); },
       null, null, null);
}

config.macros.toBalaFlashPlayer.show = function(ev,fname,xw,xh) {

  if (config.browser.isIE) {
     window.event.cancelBubble=true;
  } else {  
     ev.cancelBubble = true;   
     if (ev.stopPropagation)  
        ev.stopPropagation();
  }

  if (config.browser.isIE)
     var URLtext = document.URL.replace(/\\/g,"\/");
  else 
     var URLtext = document.URL;
  //alert(URLtext);

  var x = URLtext.lastIndexOf("/");
  var baseDIR = URLtext.substr(0,x);
  var jsDIR = '<script type="text/javascript" src="' + baseDIR + '/jslib/swfobject/swfobject.js"></script>'
  //alert(jsDIR);

  var generator=window.open('','name','height=' + xh +',width=' + xw);
  generator.document.open();
  generator.document.write('<html><head><title>toBala Flash Player</title>');
  generator.document.write(jsDIR);
  generator.document.write('</head><body>');
  generator.document.write('<div id="flashTag" style="width:'+(xw-5)+'px;height:'+(xh-5)+'px;overflow:auto"></div>');
  generator.document.write('<script type="text/javascript">');
  generator.document.write('var xo = new SWFObject("' + baseDIR + '/' + fname + '","mymovie","'+(xw-5)+'","'+(xh-5)+'","8", "#336699");');
  //generator.document.write('xo.addParam("wmode", "transparent");');
  generator.document.write('xo.write("flashTag");');
  generator.document.write('</script>');
  generator.document.write('</body></html>');
  generator.document.close();

}
//}}}
使用 toBalaFlashPlayer 巨集, 來撥放指定的 Flash 檔, 命令格式如下 :
{{{
<<toBalaFlashPlayer "movie/infotree.swf" "" "820" "610">>
}}}

{{item1{實作範例 : winzip 的安裝}}}

<<toBalaFlashPlayer "movie/winzip.swf" "" "800" "580">>
/***
|''巨集名稱:''|toBalaHTML|
|''版本:''|1.0 (2008-03-18)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''|&lt;&lt;toBalaHTML  title  filename  label  tooltip  width  height&gt;&gt; |
***/

//{{{
config.macros.toBalaHTML = {};

config.macros.toBalaHTML.handler = function(place,macroName,params,wikifier,paramString,tiddler){

  var title = params[0] || tiddler.title;
  var xfname = params[1] || "";          // 外部檔名
  var label = params[2] || "測試網頁";
  var tooltip = params[3] || "開啟另一個視窗, 檢視網頁";
  var xwidth = params[4] || 550;
  var xheight = params[5] || 400;

  createTiddlyButton(place, label, tooltip,
       function(e) { config.macros.toBalaHTML.show(e,title,xfname,xwidth,xheight); },
       null, null, null);
}

config.macros.toBalaHTML.show = function(ev,xtitle,xf,xw,xh) {

  if (config.browser.isIE) {
     window.event.cancelBubble=true;
  } else {  
     ev.cancelBubble=true;   
     if (ev.stopPropagation)  
        ev.stopPropagation();
  }

  // 將視窗置中
  var winl = (screen.width-xw)/2;
  var wint = (screen.height-xh)/2;
  if (winl < 0) winl = 0;
  if (wint < 0) wint = 0;
  var settings = 'height='  + xh +  ', width=' + xw  + ',top='  + wint  + ',left='  + winl;

  if (xf != "") {

     xf=xf.replace(/\\/mg,"/");

     // alert(xf+":"+settings);
     var xwin=window.open(xf,"HTMLWIN",settings);
     xwin.window.focus();

  } else {
    // alert(store.getTiddlerText(xtitle));
    xtext=store.getTiddlerText(xtitle);

    x1=xtext.indexOf("/*{{{*/");
    x2=xtext.indexOf("/*}}}*/");
    // alert(xtext.substring(x1+8,x2));
    xtext = xtext.substring(x1+8,x2);

    var xwin=window.open('','',settings);
    xwin.document.open();
    xwin.document.write(xtext);
    xwin.document.close();
  }
}
/*
window.open() 參數
----------------------------------------------
* width:定義新視窗的寬度。
* height:定義新視窗的高度。
* resizable:能否讓用戶調整視窗大小,可能的設定值為:yes或no(或者1與0)。
* menubar:是否要顯示主功能表,可能的設定值為:yes或no。
* toolbar:是否要顯示「標準按鈕」工具列,可能的設定值為:yes或no。
* location:是否要顯示網址欄位,可能的設定值為:yes或no。
* scrollbars:能否顯示捲軸,可能的設定值為:yes或no。
* status:是否要呈現狀態列,可能的設定值為:yes或no。
* directories:是否要呈現額外的按鈕(例如:「連結」列,以及「標準按鈕」以外的其他按鈕),可能的設定值為:yes或no。
* copyhistory:是否要複製原有瀏覽器視窗的瀏覽歷程(history),可能的設定值為:yes或no。
* fullscreen:是否要以全螢幕方式開啟新視窗(適用於IE瀏覽器),可能的設定值為:yes或no。
*/
//}}}
{{item1{你可以直接載入已存在的網頁檔, 巨集如下 :}}}
{{{
<<toBalaHTML "" "ajax\html\iframe.htm" "顯示外部檔案: ajax\html\iframe.htm">>
}}}

<<toBalaHTML "" "ajax\html\iframe.htm">>

{{item1{你可以直接載入存在 tiddler 的網頁文字, 巨集如下 :}}}
{{{
<<toBalaHTML "" "" "網頁顯示 : 直接載入以下網頁文字">>
}}}

<<toBalaHTML "" "" "網頁顯示 : 直接載入以下網頁文字">>
/*{{{*/
<html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
</head>

<style>
body {color:red;background-color: yellow}
</style>

<body>
<h2 align=center>印出 "Hello World!"</h2>
</body>
</html>
/*}}}*/
<<toBalaHTML "" "ajax/html/e4x.htm" "網頁測試 : ajax/html/e4x.htm">><<toBalaFile "ajax\html\e4x.htm">>

///%ajax\html\e4x.htm
<html>
<script type="text/javascript;e4x=1">
      myquestion = <question>          
      <display>Is it animal, vegetable, or mineral?</display>              
      <answerOption>Animal</answerOption>
      <answerOption>Vegetable</answerOption>
      <answerOption>Mineral</answerOption>
      </question>;
      alert("The question is '" + myquestion.display + "'");             
</script>
</html>
//%/
這範例程式可在 IE, Firefox, Opera  等瀏覽器中執行

<<toBalaHTML "" "ajax\html\contentEditableFF.htm">><<toBalaFile "ajax\html\contentEditableFF.htm">>

///%ajax\html\contentEditableFF.htm
<body>
<iFrame id="jia" src="about:blank"></iFrame>  
<script>  
  // window.onload   =   function(){  
  var jia = document.getElementById("jia");  
  jia.contentWindow.document.designMode="on";  
  jia.contentWindow.document.contentEditable=true;  
  jia.contentWindow.document.open();  
  jia.contentWindow.document.write("<html><head></head><body></body></html>");  
  jia.contentWindow.document.close();  
  // }  
</script>
</body>
//%/
必須關閉瀏覽器 [阻檔 POPUP 視窗] 功能, 以下程式才能執行

<<toBalaHTML "" "ajax\html\popup.htm">><<toBalaFile "ajax\html\popup.htm">>


///%ajax\html\popup.htm
<html>
<head>
<script type="text/javascript">
function show_popup()
{
   var p=window.createPopup();
   var pbody=p.document.body;
   pbody.style.backgroundColor="lime";
   pbody.style.border="solid black 1px";
   pbody.innerHTML="This is a pop-up! Click outside to close.";
   p.show(150,150,200,50,document.body);
}
</script>
</head>

<body>
<button onclick="show_popup()">Create pop-up!</button>
</body>

</html>
//%/
/***
|''巨集名稱:''|toBalaJava|
|''版本:''|1.0 (2008-04-01)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''|toBalaRun|
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''|&lt;&lt;toBalaJava  "程式檔名"  "前置編譯參數"  "前置執行參數"  "後置執行參數" "按鈕提示資訊" "按鈕提示資訊"&gt;&gt; |
***/

//{{{
config.macros.toBalaJava = {};

config.macros.toBalaJava.handler = function(place,macroName,params,wikifier,paramString,tiddler){

  if (readOnly) {
     return;
  }

  if (!params[0].match(".java")) {
     alert("請給檔名或副檔名錯誤");
     return;
  }

  // 程式檔名
  var xfname = params[0]; 

  // 前置編譯參數 
  var cprearg = params[1] || "";

  // 前置執行參數 
  var eprearg = params[2] || "";

  // 後置執行參數 
  var postarg = params[3] || "";

  var cargs = (cprearg=="" ? "":cprearg+" ") + xfname;
  //alert(cargs);

  var p = xfname.indexOf(".java");
  yfname=xfname.substring(0,p);
  p=yfname.lastIndexOf("\\");
  yfname=yfname.substring(p+1,yfname.length);

  var rargs = (eprearg==""?"":eprearg+" ") + yfname + (postarg==""?"":" "+postarg);
  //alert(rargs);

  // 按鈕提示資訊
  var clabel = params[4] || "翻譯程式 :" + xfname;
  var rlabel = params[5] || "執行程式 :" + yfname;

  // 翻譯程式
  createTiddlyButton(place, clabel, clabel,
       function(e) { config.macros.toBalaRun.cmd(e,"tbjavac.exe",cargs,"yes"); },
       null, null, null);

  // 執行程式
  createTiddlyButton(place, rlabel, rlabel,
       function(e) { config.macros.toBalaRun.cmd(e,"tbjava.exe",rargs,"yes"); },
       null, null, null);
}
//}}}
/***
|''巨集名稱:''|toBalaJava2|
|''版本:''|1.1 (2008-07-02)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''|toBalaRun|
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''|&lt;&lt;toBalaJava2 "程式檔名" "前置編譯參數" "前置執行參數" "後置執行參數"&gt;&gt;|
***/

//{{{
config.macros.toBalaJava2={
	
	editLabel: "程式編輯",
	editTip: "程式編輯",
	compileLabel: "編譯程式",
	compileTip: "編譯程式",
	runLabel: "執行程式",
	runTip: "執行程式",
        saveLabel: "儲存程式",
	saveTip: "儲存程式",
        cancelLabel: "取消編輯",
	cancelTip: "取消編輯",

	GUIEditButtonOnclick: function(e,xtiddler,xbox,xfname1,xx,yy) {

            if (config.browser.isIE) {
               window.event.cancelBubble=true;
            } else {  
               e.cancelBubble = true;   
               if (e.stopPropagation)  
                  e.stopPropagation();
            }

            removeChildren(xbox);

            var boxtool = createTiddlyElement(xbox,"div",null,"toBalaFileToolBar",null,null);
            var boxtext = createTiddlyElement(xbox,"textarea",null,null,null,null);
            wikify("@@color:#841;border:2px dotted #841;padding:2px;檔案 : <nowiki>"+xfname1+"</nowiki>@@ ",boxtool);

            createTiddlyButton(boxtool,this.saveLabel,this.saveTip,
                            function(e) { config.macros.toBalaJava2.GUISaveButtonOnclick(e,xtiddler,xbox,xfname1,boxtext,xx,yy); },
                            "toBalaFileSave",null,null);
	    createTiddlyButton(boxtool,this.cancelLabel,this.cancelTip,
                            function(e) { config.macros.toBalaJava2.GUICancelButtonOnclick(e,xtiddler,xbox,xx,yy); },
                            "toBalaFileCancel",null,null);

            // alert(xtitle+":"+xx+":"+yy);
            boxtext.setAttribute("rows",20);
            boxtext.setAttribute("cols",88);
            boxtext.value = xtiddler.text.substring(xx,yy);
        },

	GUISaveButtonOnclick: function(e,xtiddler1,xbox1,xfname2,boxtext1,xx1,yy1) {

            if (config.browser.isIE) {
               window.event.cancelBubble=true;
            } else {  
               e.cancelBubble = true;   
               if (e.stopPropagation)  
                  e.stopPropagation();
            }
 
            removeChildren(xbox1);
            var xtext=boxtext1.value;
            if (config.browser.isIE) {              
               xtext=xtext.replace(/\r/g,"");   // 請看最後的註解
            }
            var toptext=xtiddler1.text.substring(0,xx1);
            var bottomtext=xtiddler1.text.substring(yy1);
            xtext = (xtext.charAt(xtext.length-1) == "\n" ? xtext : xtext+"\n");
            xtiddler1.text=toptext+xtext+bottomtext;

            story.refreshTiddler(xtiddler1.title,null,true);
            saveChanges(false);              // 參數 false, 代表不管 Dirty 與否, 均要執行存檔動作

            var baseDIR = getLocalPath(document.URL);
  
            if (config.browser.isWindows) {
                var baseDIR = baseDIR.replace(/\//g,"");
                var x = baseDIR.lastIndexOf("\\");
             } else {
                var x = baseDIR.lastIndexOf("/");
             }

            baseDIR = baseDIR.substr(0,x+1);

            var s = saveFile(baseDIR+ (config.browser.isWindows ? xfname2 : xfname2.replace(/\\/g,"\/")), 
                                          convertUnicodeToUTF8(boxtext1.value));
            if (!s) {
               alert("存檔失敗");
            }
        },

	GUICancelButtonOnclick: function(e,xtiddler1,xbox1,xx1,yy1) {

            if (config.browser.isIE) {
               window.event.cancelBubble=true;
            } else {  
               e.cancelBubble = true;   
               if (e.stopPropagation)  
                  e.stopPropagation();
            }

            removeChildren(xbox1);
            story.refreshTiddler(xtiddler1.title,null,true);
        },

	handler : function(place,macroName,params,wikifier,paramString,tiddler){

              if (!params[0].match(".java")) {
                 alert("請給檔名或副檔名錯誤");
                 return;
              }

              // 程式檔名
              var xfname = params[0]; 

              // javac 編譯參數 
              var cprearg = params[1] || "";

              // java 執行參數 
              var eprearg = params[2] || "";

              // 你的程式執行參數 
              var postarg = params[3] || "";

              var cargs = (cprearg=="" ? "":cprearg+" ") + xfname;
              //alert(cargs);

              var p = xfname.indexOf(".java");
              yfname=xfname.substring(0,p);
              p=yfname.lastIndexOf("\\");
              yfname=yfname.substring(p+1,yfname.length);

              var rargs = (eprearg==""?"":eprearg+" ") + yfname + (postarg==""?"":" "+postarg);
              //alert(rargs);

	      var xtext=store.getTiddlerText(tiddler.title);

              // 取得程式段的起始位址
              var x1=xtext.indexOf("/"+"/"+"/"+"%" + xfname);

                // 自動產生程式段 (TiddlyWiki 備註)
                if (x1 == -1) { 
                   xtext=xtext+"\n\n/"+"/"+"/"+"%" + xfname + "\n" + "/"+"/"+"%"+"/";
                   tiddler.text=xtext; 
                   story.refreshTiddler(tiddler.title,null,true); // 這個 Tiddler 會重新顯示, 也就是 handler 會再被執行一次
                   //saveChanges(false);
                 }
                var x2=xtext.indexOf("/"+"/"+"%"+"/",x1);
                x1=x1+params[0].length+5;

		var box = createTiddlyElement(place,"div",tiddler.title+"-"+x1,"toBalaFile",null,null);
                var boxtool = createTiddlyElement(box,"div",null,"toBalaFileToolBar",null,null);
                wikify("@@color:#841;border:2px dotted #841;padding:2px;檔案 : <nowiki>"+xfname+"</nowiki>@@ ",boxtool);

                var boxtext = createTiddlyElement(box,"div",null,null,null,null);
		wikify("{{{\n"+xtext.substring(x1,x2-1)+"\n}}}",boxtext);

                if (readOnly) {
                   return;
                }

                // 編輯程式
		createTiddlyButton(boxtool,this.editLabel,this.editTip,
                            function(e) { config.macros.toBalaJava2.GUIEditButtonOnclick(e,tiddler,box,xfname,x1,x2);},
                            "toBalaFileEdit",null,null);

                // 翻譯程式
		createTiddlyButton(boxtool,this.compileLabel,this.compileTip,
                            function(e) { config.macros.toBalaRun.cmd(e,"tbjavac.exe",cargs,"yes"); },
                            "toBalaFileEdit",null,null);

                // 執行程式
                if (xtext.substring(x1,x2-1).indexOf("main") != -1) {
		       createTiddlyButton(boxtool,this.runLabel,this.runTip,
                            function(e) { config.macros.toBalaRun.cmd(e,"tbjava.exe",rargs,"yes");},
                            "toBalaFileEdit",null,null);
                }
	}		
};

/*
HTML 的 textarea 標籤, 對於換行在不同的瀏覽器有不同的處理方式

As you may know, the humble line break actually has three forms depending on which operating system is doing the breaking. On Unix machines, a single newline character ‘\n’ does the job. On Macs, a carriage return ‘\r’ is used. DOS and Windows use both: ‘\r\n’. It’s one of those relatively subtle issues that can bite you hard if you don’t know what to look out for.
*/

//}}}
{{item1{程式範例}}} 
{{{
使用 toBalaJava2 巨集, 撰寫, 編譯及執行 Java 程式, 命令格式如下 :

<<toBalaJava2 "java\hello.java" "" "">>
}}}
<<toBalaJava2 "java\hello.java" "" "">>

{{item1{程式範例 : 輸入 [編譯] 及 [執行] 參數}}}
{{{
使用 toBalaJava2 巨集, 編譯及執行 Java 程式, 命令格式如下 :
<<toBalaJava2 "java\assertion.java" "-source 1.4" "-ea">>

"-source 1.4" 是編譯參數
"-ea" 是執行參數
}}}
<<toBalaJava2 "java\assertion.java" "-source 1.4" "-ea">>

{{item1{程式範例 : 輸入程式參數}}}
{{{
使用 toBalaJava2 巨集, 編譯及執行 Java 程式, 命令格式如下 :

<<toBalaJava2 "java\args.java" "" "" "aa bb cc">>
}}}
<<toBalaJava2 "java\args.java" "" "" "aa bb cc">>


///%java\hello.java
public class hello {
  public static void main(String[] args){
     System.out.println("大家好好");
  }
}
//%/

///%java\assertion.java
class assertion {
  public static void main(String[] args){
    int i=-11;
    if (i%3==0) 
      { System.out.println("0"); }
    else if (i%3==1) 
      { System.out.println("1"); }
    else {
      assert((i%3)==2):i;
    }
  }
}
//%/

///%java\args.java
public class args {
  public static void main(String[] args) {
    for(int i=0; i < args.length ; ++i) 
      System.out.println(args[i]);
  }
} 
//%/
//{{{
if (!window.toBala) window.toBala = {};

toBala.AllTiddlers = "";
toBala.CoreTiddlers = "";

// 讀取資訊樹的架構
toBala.getMainTree = function(xstr) {
    var tbATree = new Array();
    var tbMMenu = new Array();
    var tbTemp = new Array();

    var xtext=store.getTiddlerText("MainMenu");
    tbMMenu = xtext.split("\n");

    for (var i=0,j=0; i<tbMMenu.length; ++i) {
       tbTemp = tbMMenu[i].split(" ");
       if (tbTemp[1] && tbTemp[1].indexOf(xstr) != -1) {
          tbATree[j] = tbTemp[1];
          ++j;
       }
    }
    return tbATree;
};

// 讀取資訊樹幹的所有文章
toBala.TagDigg = function(tbTag) {

   toBala.AllTiddlers = (toBala.AllTiddlers == "" ? tbTag : toBala.AllTiddlers + "," + tbTag);    

   var tbT2 = store.getTaggedTiddlers(tbTag);
   if (tbT2) {
      for (var i=0; i<tbT2.length; ++i) 
         toBala.TagDigg(tbT2[i].title);
   }
   return;
};

// 讀出 Tiddler 所有內容, 也就是 DIV 標籤內容
toBala.getTiddlerDIV = function(tbT) {
    var tiddler = store.getTiddler(tbT)
    if (!tiddler)
       return "";
   
    var usePre = config.options.chkUsePreForStorage;
    var created = tiddler.created.convertToYYYYMMDDHHMM();
    var modified = tiddler.modified.convertToYYYYMMDDHHMM();
    var vdate = version.date.convertToYYYYMMDDHHMM();
    var attributes = tiddler.modifier ? ' modifier="' + tiddler.modifier.htmlEncode() + '"' : "";
    attributes += (usePre && modified == created) ? "" : ' modified="' + modified +'"';
    attributes += (usePre && created == vdate) ? "" :' created="' + created + '"';
    var tags = tiddler.getTags();
    if (!usePre || tags)
       attributes += ' tags="' + tags.htmlEncode() + '"';

    return ('<div %0="%1"%2>%3</'+'div>').format([
	usePre ? "title" : "tiddler",
	tiddler.title.htmlEncode(),
	attributes,
	usePre ? "\n<pre>" + tiddler.text.htmlEncode() + "</pre>\n" : tiddler.text.escapeLineBreaks().htmlEncode()
	]);
}
//}}}
/***
|''巨集名稱:''|toBalaManager|
|''版本:''|1.0 (2008-09-05)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''~TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''||
***/
//{{{
config.macros.toBalaManager={
	preText: "",
	save: function(e,ytiddler,yform) {

            //for (var i=0,str="";i<yform.elements.length;++i){
            //  str=str+yform.elements[i].type+":"+yform.elements[i].tagName+":"+yform.elements[i].value;
            //}
            //alert(str);  
      
            // 設定主標題
            var xt = store.getTiddler("SiteTitle");  
            xt.text=  yform.elements[0].value;

            // 設定次標題
            var xt = store.getTiddler("SiteSubtitle");  
            xt.text=  yform.elements[1].value;

            // 設定 MainMenu
            var xt = store.getTiddler("MainMenu");  
            xt.text=  yform.elements[2].value;

            // 設定 ToolBar
            var xt = store.getTiddler("toBalaToolBar");  
            xt.text=  yform.elements[3].value;

            // 備份 SiteTitle, SiteSubtitle, ToolBar, MainMenu  
            ytiddler.text=preText; 
            saveChanges(false);   // 參數 false, 代表不管 Dirty 與否, 均要執行存檔動作
        },

	handler : function(place,macroName,params,wikifier,paramString,tiddler){

                if (!readOnly) {
		    createTiddlyButton(place,"儲存設定","儲存設定",
                          function(e) { config.macros.toBalaManager.save(e,tiddler,xform); },
                          "toBalaManagerSave",null,null);
                }

		var xform = createTiddlyElement(place,"form",tiddler.title+"-form","toBalaManager",null,null);
                // 讀取主標題
                var xlabel1 = createTiddlyElement(xform,"label",null,"",null,null);
		wikify("''主標題 (~SiteTitle) :  ''",xlabel1);
                var xtitle1 = createTiddlyElement(xform,"input",null,"xManagerMT",null,null);
                var xt = store.getTiddler("SiteTitle");   
		xtitle1.value=xt.text;
		wikify("\n\n",xform);

                // 讀取次標題
                var xlabel2 = createTiddlyElement(xform,"label",null,"",null,null);
                wikify("''次標題 (~SiteSubtitle) :  ''",xlabel2);
                var xtitle2 = createTiddlyElement(xform,"input",null,"xManagerST",null,null);
                var xt = store.getTiddler("SiteSubtitle");   
		xtitle2.value=xt.text;
		wikify("\n\n",xform);

                // 讀取 MainMenu
                var xlabel4 = createTiddlyElement(xform,"label",null,"",null,null);
                wikify("''資訊樹 (TagsTree)''",xlabel4);
		wikify("\n",xform);
                var xmm = createTiddlyElement(xform,"textarea",null,"xManagerMM",null,null);
                var xt = store.getTiddler("MainMenu");   
                xmm.value=xt.text;
		wikify("\n\n",xform);

                // 讀取 ToolBar
                var xlabel3 = createTiddlyElement(xform,"label",null,"",null,null);
                wikify("''工具列 (~ToolBar)''",xlabel3);
		wikify("\n",xform);
                var xtb = createTiddlyElement(xform,"textarea",null,"xManagerTB",null,null);
                var xt = store.getTiddler("toBalaToolBar");   
                xtb.value=xt.text;
		wikify("\n\n",xform);

                // 備份 SiteTitle, SiteSubtitle, ToolBar, MainMenu
	        var xtext=store.getTiddlerText(tiddler.title);
                var x1 = xtext.indexOf("/"+"/"+"/"+"%");
                xtext = ( x1 == -1 ? xtext : xtext.substring(0,x1) );

                preText=xtext+"\n\n/"+"/"+"/"+"%" ;
                preText=preText+"\n\n"+xtitle1.value;
                preText=preText+"\n\n"+xtitle2.value;
                preText=preText+"\n\n"+xmm.value;
                preText=preText+"\n\n"+xtb.value;
                preText=preText+"\n" + "/"+"/"+"%"+"/";

	}		
};

setStylesheet(".toBalaManager {background:#eee; font-size:12px;border:1px solid #ccc; padding:2px; margin:5px;}\n"+
".xManagerMT {width:550px;height:25px;}\n" +
".xManagerST {width:550px;height:25px;}\n" +
".xManagerTB {width:680px;height:100px;}\n" +
".xManagerMM {width:680px;height:240px;}\n" +
".toBalaManagerSave {border:1px solid #ccc;font-size:14px;padding:2px;margin-left:4px;margin-bottom:2px;}\n" ,
"toBalaManagerStyles");
//}}}
/***
|''巨集名稱:''|toBalaNotes|
|''版本:''|1.1 (2010-03-29)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''||
***/

//{{{
config.macros.toBalaNotes={
	
	editLabel: "編輯",
	editTip: "編輯",
        saveLabel: "儲存",
	saveTip: "儲存",
        cancelLabel: "取消",
	cancelTip: "取消",
        heading: "@@font-size:12px;color:#841;註解@@",
    
	GUIEditButtonOnclick: function(e,xtiddler,xbox,xx,yy) {
            removeChildren(xbox);

            var boxtool = createTiddlyElement(xbox,"div",null,"toBalaNotesToolBar",null,null);
            var boxtext = createTiddlyElement(xbox,"textarea",null,null,null,null);
	    wikify(this.heading+" : ",boxtool);

            // alert(xtitle+":"+xx+":"+yy);
            boxtext.setAttribute("rows",15);
            boxtext.setAttribute("cols",88);

            xstr=xtiddler.text.substring(xx,yy).replace(/&lt;/g, "<");
            xstr=xstr.replace(/&gt;/g, ">");
            xstr=xstr.replace(/&#123;/g, "{");
            xstr=xstr.replace(/&#125;/g, "}"); 
            boxtext.value = xstr;

            createTiddlyButton(boxtool,this.saveLabel,this.saveTip,
                            function(e) { config.macros.toBalaNotes.GUISaveButtonOnclick(e,xtiddler,xbox,boxtext,xx,yy); },
                            "toBalaNotesSave",null,null);
	    createTiddlyButton(boxtool,this.cancelLabel,this.cancelTip,
                            function(e) { config.macros.toBalaNotes.GUICancelButtonOnclick(e,xtiddler,xbox,xx,yy); },
                            "toBalaNotesCancel",null,null);
        },

	GUISaveButtonOnclick: function(e,xtiddler1,xbox1,boxtext1,xx1,yy1) {
            removeChildren(xbox1);
            toptext=xtiddler1.text.substring(0,xx1);
            bottomtext=xtiddler1.text.substring(yy1);

            xstr=boxtext1.value.replace(/\</g, "&lt;");
            xstr=xstr.replace(/>/g, "&gt;");
            xstr=xstr.replace(/{/g, "&#123;");
            xstr=xstr.replace(/}/g, "&#125;");
            xstr=xstr.replace(/\/\/%\//g, "");
            xstr=xstr.replace(/\/\/\/%/g, "");
            xtiddler1.text=toptext+xstr+bottomtext;

            yy1=xtiddler1.text.indexOf("/"+"/"+"%"+"/",xx1);

            var boxtool = createTiddlyElement(xbox1,"div",null,"toBalaNotesToolBar",null,null);
	    wikify(this.heading+" : ",boxtool);

	    createTiddlyButton(boxtool,this.editLabel,this.editTip,
                            function(e) { config.macros.toBalaNotes.GUIEditButtonOnclick(e,xtiddler1,xbox1,xx1,yy1);},
                            "toBalaNotesEdit",null,null);

             var boxarea = createTiddlyElement(xbox1,"div",null,null,null,null); 
             boxarea.innerHTML="<pre id='toBalaNotesText'>"+xstr+"</pre>";
	     // wikify("<nowiki>"+xtiddler1.text.substring(xx1,yy1)+"</nowiki>",boxarea);
             saveChanges(false);   // 參數 false, 代表不管 Dirty 與否, 均要執行存檔動作
             clearMessage();
        },

	GUICancelButtonOnclick: function(e,xtiddler1,xbox1,xx1,yy1) {
            removeChildren(xbox1);

            var boxtool = createTiddlyElement(xbox1,"div",null,"toBalaNotesToolBar",null,null);
	    wikify(this.heading+" : ",boxtool);

	    createTiddlyButton(boxtool,this.editLabel,this.editTip,
                            function(e) { config.macros.toBalaNotes.GUIEditButtonOnclick(e,xtiddler1,xbox1,xx1,yy1);},
                            "toBalaNotesEdit",null,null);

             var boxarea = createTiddlyElement(xbox1,"div",null,null,null,null);
             boxarea.innerHTML="<pre id='toBalaNotesText'>"+xtiddler1.text.substring(xx1,yy1)+"</pre>";
	     //wikify("<nowiki>"+xtiddler1.text.substring(xx1,yy1)+"</nowiki>",boxarea);
        },

	handler : function(place,macroName,params,wikifier,paramString,tiddler){

		var xtext=store.getTiddlerText(tiddler.title);
                var x1=xtext.indexOf("/"+"/"+"/"+"%" + params[0]);

                // 自動產生 TiddlyWiki 備註
                if (x1 == -1) { 
                   xtext=xtext+"\n\n/"+"/"+"/"+"%" + params[0] + "\n" + "/"+"/"+"%"+"/";
                   tiddler.text=xtext; 
                   story.refreshTiddler(tiddler.title,null,true);
                   saveChanges(false);     // 參數 false, 代表不管 Dirty 與否, 均要執行存檔動作
                   clearMessage();
                   return;
                 }
                var x2=xtext.indexOf("/"+"/"+"%"+"/",x1);
                x1=x1+params[0].length+5;

		var box = createTiddlyElement(place,"div",tiddler.title+"-"+x1,"toBalaNotes",null,null);
                var boxtool = createTiddlyElement(box,"div",null,"toBalaNotesToolBar",null,null);
		wikify(this.heading+" : ",boxtool);

                var boxtext = createTiddlyElement(box,"div",null,null,null,null);
                boxtext.innerHTML="<pre id='toBalaNotesText'>"+xtext.substring(x1,x2)+"</pre>";
		// wikify("<nowiki>"+xtext.substring(x1,x2)+"</nowiki>",boxtext);

                if (readOnly) {
                   return;
                }

		createTiddlyButton(boxtool,this.editLabel,this.editTip,
                            function(e) { config.macros.toBalaNotes.GUIEditButtonOnclick(e,tiddler,box,x1,x2);},
                            "toBalaNotesEdit",null,null);
	}		
};

setStylesheet(".toBalaNotes {background:#eee; border:1px solid #ccc; padding:2px; margin:5px;}\n"+
".toBalaNotesEdit {border:1px solid #ccc;padding:2px;margin-top:2px;margin-bottom:2px;}\n" +
".toBalaNotesCancel {border:1px solid #ccc;padding:2px;margin-top:2px;margin-right:2px;margin-bottom:2px;}\n" +
".toBalaNotesToolBar {border-bottom: 2px dotted #556b2f;padding:1px 0px 5px 0px;margin:1px;}\n" +
".toBalaNotesSave {border:1px solid #ccc;padding:2px;margin-top:2px;margin-right:2px;margin-bottom:2px;}\n"+
"#toBalaNotesText {background-color:#eee;border:none;margin:1px;padding:0px}\n",
"toBalaNotesStyles");
//}}}
在文章中使用 toBalaNotes 巨集, 可在文章中加入備註, 請看以下使用說明

{{item1{使用格式}}}
{{{
<<toBalaNotes "test">>

"test" 代表備註識別字串

[註] 一篇文章中可以存在多個備註
}}}

<<toBalaNotes "test">>

///%test
//%/
/***
|''巨集名稱:''|toBalaRun|
|''版本:''|1.0 (2008-04-01)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''| |
***/

//{{{
config.macros.toBalaRun = {};
config.macros.toBalaRun.handler = function(place,macroName,params,wikifier,paramString,tiddler){

  if (readOnly) {
     return;
  }

  if (!params[0]) {
     alert("請給檔名");
     return;
  }
  var fname = params[0];                //  執行檔名
  var varg = params[1] || "";             //  執行參數
  var label = params[2] || "執行 : "+fname + " " + varg;
  var tooltip = params[3] || "執行檔名 : "+fname + " " + varg;
  var result = params[4] || "yes";

  window.status="";
  createTiddlyButton(place, label, tooltip,
       function(e) { config.macros.toBalaRun.cmd(e,fname,varg,result); },
       null, null, null);
}

config.macros.toBalaRun.cmd = function(ev,xfname,xarg,xresult) {

  if (!xfname.match(".bat")) {
      //var xwin = toBala.showMsg("<h1>執行中, 請稍後</h1>",250,50);
      window.status = xfname + " " + xarg + " 執行中, 請稍後";
  }

  if (config.browser.isIE) {
     window.event.cancelBubble=true;
  } else {  
     ev.cancelBubble = true;   
     if (ev.stopPropagation)  
        ev.stopPropagation();
  }

  var baseDIR = getLocalPath(document.URL);
  //alert(baseDIR);

   if (config.browser.isWindows) {
      var baseDIR = baseDIR.replace(/\//g,"");
      var x = baseDIR.lastIndexOf("\\");
      xfname = "\\" + xfname.replace(/\//g,"\\");
      xarg = xarg.replace(/\//g,"\\");
   } else {
      var x = baseDIR.lastIndexOf("/");
      xfname = "/" + xfname.replace(/\\/g,"/");
      xarg = xarg.replace(/\\/g,"/");
   }

   baseDIR = baseDIR.substr(0,x);
   //alert(baseDIR);

   if (config.browser.isIE) {
	var theShell = new ActiveXObject("WScript.Shell");
	if (theShell) {
            var runstr = baseDIR + xfname + " " + xarg;
            // alert(runstr);
	    try {
	        theShell.run(runstr,1, (xresult == "yes" ? true:false));
	    } catch (e) {
                try {          //  執行系統命令
                    var runstr = xfname.substring(1)+ " " + xarg;
                    theShell.run(runstr,1, (xresult == "yes" ? true:false));
                } catch(e) {
                   if (!xfname.match(".bat")) 
                      window.status="";
		   displayMessage("執行失敗 :" + runstr);
		   return;
                }
	    }
	} 
   } else if (config.browser.isGecko) { 
	netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
        var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);

        try {
           var runstr = baseDIR +xfname; 
           // alert(runstr);
           file.initWithPath(runstr);
        }catch (e) {
           if (!xfname.match(".bat")) 
              window.status="";
           displayMessage("執行字串格式錯誤 : " + runstr);
           return;
        }

	try {
	   var process = Components.classes['@mozilla.org/process/util;1'].createInstance(Components.interfaces.nsIProcess);
           var Aargs = xarg.split(" ");
           // alert(Aargs);
           process.init(file);
           process.run((xresult == "yes" ? true:false), Aargs, Aargs.length);
	} catch (e) {
            try {    //  執行系統命令
                runstr=xfname.substring(1);
                file.initWithPath(runstr);
                process.init(file);
                process.run((xresult == "yes" ? true:false), Aargs, Aargs.length);
            } catch (e) {
                if (!xfname.match(".bat")) 
                    window.status="";
	        displayMessage("執行失敗 : " + runstr);
                return;
            }
	}
   }
   // 顯示執行結果
   if ( !xfname.match(".bat") && !xfname.match(".sh") && xresult == "yes") {
      window.status="";
      xf = baseDIR+xfname+".htm"
      // alert(xf);
      var xh = 400;
      var xw = 780;
      var winl = (screen.width-xw)/2;
      var wint = (screen.height-xh)/2;
      if (winl < 0) winl = 0;
      if (wint < 0) wint = 0;
      var settings = 'height='  + xh +  ', width=' + xw  + ',top='  + wint  + ',left='  + winl + ',scrollbars=yes';
      var ywin=window.open("file:///"+xf,"HTMLWIN",settings);
   }
}
//}}}
在文章中使用 toBalaRun 巨集, 可執行系統中的 ''命令'', ''批次檔'', 請看以下使用說明

{{item1{使用格式}}}

__在 Windows 系統中, 啟動 tbsys.bat  批次檔__
{{{
<<toBalaRun "tbsys.bat"  ""  "System Info (batch)">>
}}}
<<toBalaRun "tbsys.bat" "" "System Info (batch)">>


__在 Windows 系統中, 因執行 exe 檔, 執行後會自動開啟一個 [執行結果視窗]__
{{{
<<toBalaRun  "tbsys.exe"  ""  "System Info (exe)">>
}}}
<<toBalaRun "tbsys.exe" "" "System Info (exe)">>

__在 Mac OS X 系統中, 啟動 ~TextEdit 應用程式, 因最後一個參數是 "no", 所以不會開啟一個 [執行結果視窗] __
{{{
<<toBalaRun "/usr/bin/open"  "-a /Applications/TextEdit.app"  ""  ""  "no">>
}}}
<<toBalaRun "/usr/bin/open" "-a /Applications/TextEdit.app" "" "" "no">>


{{item1{tbsys.bat 批次檔內容}}}
{{{
@echo off

REM 取得這個 Batch File 的目錄
set toBalaPath=%~p0

REM 取得這個 Batch File 的磁碟代號
set toBalaDrv=%~d0

REM 轉換磁碟及目錄
call %toBalaDrv%
cd %toBalaPath%

REM 設定環境變數
REM -----------------
set JAVA_HOME=%cd%\jdk1.6.0_05
set CLASSPATH=.;%cd%\jaxp;%cd%\java;%cd%\scjp
set CLASSPATH=%cd%\apache\xalan-j_2_7_1\xalan.jar;%CLASSPATH%
set CLASSPATH=%cd%\apache\xerces-2_9_1\xercesImpl.jar;%CLASSPATH%
set PATH=.;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;%cd%\cmdtools;%PATH%


REM 執行 java 命令
REM ------------------
if "%~x0" == ".bat" goto n1
echo ^<head^> >%0.htm
echo ^<meta http-equiv="Content-Type" content="text/html; charset=big5"^> >>%0.htm
echo ^</head^> >>%0.htm
echo ^<body^> >>%0.htm
echo 執行檔案 : %1 >>%0.htm
echo ^<hr^> >>%0.htm 
echo ^<pre style='font-size:12px'^> >>%0.htm
goto n2
:n1
echo 執行中, 請稍待 (檔案 : %1) 
echo. >%0.htm
:n2

gettype >> %0.htm 2>&1
echo.
ipconfig /all >> %0.htm 2>&1

REM 處理執行訊息
REM -------------------
if "%~x0" == ".bat" goto s1
echo ^</pre^> >>%0.htm
echo ^</body^> >>%0.htm
rem convertZ\convertz /i:big5 /o:utf8 %0.msg %0.htm
exit
:s1
type %0.htm
echo.
echo 執行完成
echo.
pause
}}}

{{item1{Quick Batch File Compiler - 將 Batch 檔轉換成 exe 檔}}}
Quick Batch File Compiler convert your batch files into actual program (.EXE format) in one click. This program may be run on Windows 2000/2003/XP/Vista without any limitations. An .EXE file is much harder to casually reverse-engineer, so this could be a way to conceal a particular batch file's operations from an end user. Content of your batch file will be encrypted and protected from changes.

Quick Batch File Compiler also lets you set various resources in the .EXE file, such as its description, the company name, version information and even the application icon. In additional, you may include any files to compiled exe file and use it during execution. 

網址 : http://www.abyssmedia.com/quickbfc/index.shtml
<<toBalaFile "xml\dtd01.xml">><<toBalaRun "java\jaxp\JAXPDTD.bat" "xml\dtd01.xml" "檢核">>

----

<<toBalaFile "xml\dtd02.xml">><<toBalaRun "java\jaxp\JAXPDTD.bat" "xml\dtd02.xml" "檢核">>


///%xml\dtd01.xml
<?xml version="1.0" encoding="big5"?>
<!DOCTYPE PersonData [
  <!ELEMENT PersonData (name,spouse)>
  <!ELEMENT name (#PCDATA)>
  <!ELEMENT spouse (#PCDATA)>
]>
<PersonData>
    <spouse>Teley</spouse>
    <name>Ryan</name>
</PersonData>
//%/

///%xml\dtd02.xml
<?xml version="1.0"?>
<!DOCTYPE user [
  <!ELEMENT user (name+,e-mail*,title?)>
  <!ELEMENT name (#PCDATA)>
  <!ELEMENT e-mail (#PCDATA)>
  <!ELEMENT title (#PCDATA)>
]>
<user>
  <name>Austin Sours</name>
  <e-mail>xchen@cmt.com.tw</e-mail>
  <e-mail>aaa@x,y,z</e-mail>
</user>
//%/
<<toBalaFile "xml\well01.xml">><<toBalaRun "java\jaxp\JAXPWell.bat" "xml\well01.xml" "檢核">>

----

<<toBalaFile "xml\well02.xml">><<toBalaRun "java\jaxp\JAXPWell.bat" "xml\well02.xml" "檢核">>


///%xml\well01.xml
<root>
  <marble color="red"/>
  <marble color='red'/>
</root>
//%/

///%xml\well02.xml
<first_tag>
  <second_tag>
     <third_tag>Contents of third tag
  </second_tag>
</First_tag>
//%/
<<toBalaFile "xml\stype.xsd">>


<<toBalaFile "xml\stype.xml">><<toBalaRun "java\jaxp\JAXPSchema.bat" "xml\stype.xml xml\stype.xsd" "檢核">>


///%xml\stype.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
                  targetNamespace="http://xsdtesting">
    <xs:element name="author" type="xs:date"/>
</xs:schema>
//%/

///%xml\stype.xml
<?xml version="1.0"?>
<x:author xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
          xmlns:x="http://xsdtesting"
          xsi:schemaLocation="http://xsdtesting stype.xsd">
123.5
</x:author>
//%/
<<toBalaFile "xml\deftemp.xml">>
DOM Tree
----------------
{{{
       .
       |
       |--- <?xml-stylesheet  type="text/xsl"  .... ?>   
       |--- <root>
                |
                |--- <text>
                |
                |
                |--- <text>
                |
                |
                |--- <!-- abcd --> 

}}}


<<toBalaFile "xml\deftemp.xsl">><<toBalaRun "java\jaxp\JAXPXSLT.bat" "xml\deftemp.xml xml\deftemp.xsl" "轉換">>


///%xml\deftemp.xml
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="deftemp.xsl"?>
<root>
  <text>
    Roses are <color>red</color>, violets are <color>blue</color>.
  </text>
  <text>
    My <color>green</color> and <color id="xxx">yellow</color> 
    sweater is just the right hue.
    <?name type="bebo"?>
  </text>
  <!-- abcd -->
</root>
//%/

///%xml\deftemp.xsl
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<!-- <xsl:template match="*|/">
</xsl:template>  -->

<!-- <xsl:template match="processing-instruction()">
  PI : <xsl:value-of select="."/>
</xsl:template> -->

<!-- <xsl:template match="root"/> -->

</xsl:stylesheet>
//%/
{{item1{ZoomIt v1.8}}}
By Mark Russinovich
Published: March 10, 2008
網址 : http://technet.microsoft.com/zh-tw/sysinternals/bb897434(en-us).aspx

__''Introduction''__
~ZoomIt is screen zoom and annotation tool for technical presentations that include application demonstrations. ~ZoomIt runs unobtrusively in the tray and activates with customizable hotkeys to zoom in on an area of the screen, move around while zoomed, and draw on the zoomed image. I wrote ~ZoomIt to fit my specific needs and use it in all my presentations.

~ZoomIt works on all versions of Windows and you can use pen input for ~ZoomIt drawing on tablet ~PCs.

__''Using ~ZoomIt''__
The first time you run ~ZoomIt it presents a configuration dialog that describes ~ZoomIt's behavior, let's you specify alternate hotkeys for zooming and for entering drawing mode without zooming, and customize the drawing pen color and size. I use the draw-without-zoom option to annotate the screen at its native resolution, for example. ~ZoomIt also includes a break timer feature that remains active even when you tab away from the timer window and allows you to return to the timer window by clicking on the ~ZoomIt tray icon.

點選 <<toBalaRun "tbzoomit.bat" "" "ZoomIt v1.8" "" "no">> 啟動 Zoomit

{{item1{tbzoomit.bat 程式碼}}}
{{{
@echo off

REM 取得這個 Batch File 的目錄
set toBalaPath=%~p0

REM 取得這個 Batch File 的磁碟代號
set toBalaDrv=%~d0

REM 轉換磁碟及目錄
call %toBalaDrv%
cd %toBalaPath%

REM 設定環境變數
REM -----------------
set PATH=.;%cd%\tools;%cd%\tools\cmdtools;%PATH%
start /B zoomit.exe
exit

}}}
網址 : http://freemind.sourceforge.net/wiki/index.php/Main_Page

~FreeMind is a premier free mind-mapping (http://en.wikipedia.org/wiki/Mind_map) software written in Java. The recent development has hopefully turned it into high productivity tool. We are proud that the operation and navigation of ~FreeMind is faster than that of MindManager because of one-click "fold / unfold" and "follow link" operations.

So you want to write a completely new metaphysics? Why don't you use ~FreeMind? You have a tool at hand that remarkably resembles the tray slips of Robert Pirsig, described in his sequel to Zen and the Art of Motorcycle Maintenance called Lila. Do you want to refactor your essays in a similar way you would refactor software? Or do you want to keep personal knowledge base, which is easy to manage? Why don't you try ~FreeMind? Do you want to prioritize, know where you are, where you've been and where you are heading, as Stephen Covey would advise you? Have you tried FreeMind to keep track of all the things that are needed for that? 

Mac OS X 系統請點選以下按鈕

<<toBalaRun "java/freemind/freemind.sh"  ""  "啟動心智圖編輯器">>


Windows 系統請點選以下按鈕

<<toBalaRun "tbfreemind.bat"  ""  "啟動心智圖編輯器">>
/***
|''巨集名稱:''|toBalaSWF2|
|''版本:''|1.1 (2008-09-30)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''| |
***/
//{{{
config.macros.toBalaSWF2 = {};

config.macros.toBalaSWF2.handler = function(place,macroName,params,wikifier,paramString,tiddler){

  var xname = params[0] || tiddler.title;
  var xwidth = params[1] || 600;
  var xheight = params[2] || 450;
  var label = params[3] || "撥放 : " + xname;

  createTiddlyButton(place, label, label,
       function(e) { config.macros.toBalaSWF2.show(e, xname, xwidth, xheight); },
       null, null, null);
}

config.macros.toBalaSWF2.show = function(ev,fname,xw,xh) {

  if (config.browser.isIE) {
     window.event.cancelBubble=true;
  } else {  
     ev.cancelBubble = true;   
     if (ev.stopPropagation)  
        ev.stopPropagation();
  }

  if (config.browser.isIE)
     var URLtext = document.URL.replace(/\\/g,"\/");
  else 
     var URLtext = document.URL;
  //alert(URLtext);

  var x = URLtext.lastIndexOf("/");
  var baseDIR = URLtext.substr(0,x);
  //alert(jsDIR);

  // 將視窗置中
  var winl = (screen.width-xw)/2;
  var wint = (screen.height-xh)/2;
  if (winl < 0) winl = 0;
  if (wint < 0) wint = 0;
  var settings = 'scrollbars=yes, resizable=yes, height='  + xh +  ', width=' + xw  + ',top='  + wint  + ',left='  + winl;
  var gen=window.open('',"_blank",settings);

  gen.document.open();
  gen.document.write("<html>");
  gen.document.write("<head>");
  gen.document.write("  <title>toBalaSWF2 : " + fname + "</title>");
  gen.document.write("  <script type='text/javascript' src='" + baseDIR + "/jslib/swfobject21/swfobject.js'></script>");
  gen.document.write("  <script type='text/javascript'>");
  gen.document.write("     swfobject.embedSWF('" + baseDIR + '/' + fname + "', 'mySWF21', '" + xw + "','" + xh + "', '9.0.0');");
  gen.document.write("  </script>");
  gen.document.write("</head>");
  gen.document.write("<body style='margin:0;padding:0'>");
  gen.document.write("  <div style='margin:0;padding:0;" +"width:" + (xw+2) +";height:" + (xh+2) +"' id='mySWF21'>");
  gen.document.write("    <p>無法撥放</p>");
  gen.document.write("  </div>");
  gen.document.write("</body>");
  gen.document.write("</html>");

  gen.document.close();
}
//}}}
 [[首頁]] | [[土芭樂 3.0 - 數位新思路|http://tbala.net/]]  | [[TiddlyWiki 練功坊|http://tiddlywiki.tbala.net/]] | [[匯入文章]]  | [[匯出文章]]  |  &nbsp;&nbsp;<<toBalaRun "Java-CMD.bat" "" "命令提示視窗">>&nbsp;&nbsp;<<newTiddler label:"新增文章">>&nbsp;&nbsp;<<closeAll>>&nbsp;&nbsp;<<saveChanges>> &nbsp;&nbsp;IT 無涯,關機是岸
/***
|''巨集名稱:''|toBalaWrite|
|''版本:''|1.0 (2008-09-01)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''| |
***/

//{{{
config.macros.toBalaWrite = {};
config.macros.toBalaWrite.handler = function(place, macroName, params, wikifier, paramString, tiddler) {
	var title = params[0];
	if (title == tiddler.title) {
            title = "Error: Can't use the same tiddler from which the macro is called (infinite recursion)!";
            alert(title);
            return;
	}
	var tiddler = store.getTiddler(title);
        var contents = tiddler.text;
	wikify(contents, place);
}
//}}}
/***
|''Name:''|DropDownMenuPlugin|
|''Description:''|Create dropdown menus from unordered lists|
|''Author:''|Saq Imtiaz ( lewcid@gmail.com )|
|''Source:''|http://tw.lewcid.org/#DropDownMenuPlugin|
|''Code Repository:''|http://tw.lewcid.org/svn/plugins|
|''Version:''|2.1|
|''Date:''|11/04/2007|
|''License:''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion:''|2.2.5|

!!Usage:
* create a two-level unordered list using wiki syntax, and place {{{<<dropMenu>>}}} on the line after it.
* to create a vertical menu use {{{<<dropMenu vertical>>}}} instead.
* to assign custom classes to the list, just pass them as parameters to the macro {{{<<dropMenu className1 className2 className3>>}}}

!!Features:
*Supports just a single level of drop-downs, as anything more usually provides a poor experience for the user.
* Very light weight, about 1.5kb of JavaScript and 4kb of CSS.
* Comes with two built in css 'themes', the default horizontal and vertical. 

!!Customizing:
* to customize the appearance of the menu's, you can either add a custom class as described above or, you can edit the CSS via the StyleSheetDropDownMenu shadow tiddler.


***/
// /%
//!BEGIN-PLUGIN-CODE
config.macros.dropMenu={

	dropdownchar: "\u25bc",

	handler : function(place,macroName,params,wikifier,paramString,tiddler){
		list = findRelated(place.lastChild,"UL","tagName","previousSibling");
		if (!list)
			return;
		addClass(list,"suckerfish");
		if (params.length){
			addClass(list,paramString);
		}
		this.fixLinks(list);
	},
	
	fixLinks : function(el){
		var els = el.getElementsByTagName("li");
		for(var i = 0; i < els.length; i++) {
			if(els[i].getElementsByTagName("ul").length>0){
				var link = findRelated(els[i].firstChild,"A","tagName","nextSibling");
				if(!link){
					var ih = els[i].firstChild.data;
					els[i].removeChild(els[i].firstChild);
					var d = createTiddlyElement(null,"a",null,null,ih+this.dropdownchar,{href:"javascript:;"});
					els[i].insertBefore(d,els[i].firstChild);
				}
				else{
					link.firstChild.data = link.firstChild.data + this.dropdownchar;
					removeClass(link,"tiddlyLinkNonExisting");
				}
			}
			els[i].onmouseover = function() {
				addClass(this, "sfhover");
			};
			els[i].onmouseout = function() {
				removeClass(this, "sfhover");
			};
		}
	}	
};

config.shadowTiddlers["StyleSheetDropDownMenuPlugin"] = 
	 "/*{{{*/\n"+
	 "/***** LAYOUT STYLES -  DO NOT EDIT! *****/\n"+
	 "ul.suckerfish, ul.suckerfish ul {\n"+
	 "	margin: 0;\n"+
	 "	padding: 0;\n"+
	 "	list-style: none;\n"+
	 "	line-height:1.4em;\n"+
	 "}\n\n"+
	 "ul.suckerfish  li {\n"+
	 "	display: inline-block; \n"+
	 "	display: block;\n"+
	 "	float: left; \n"+
	 "}\n\n"+
	 "ul.suckerfish li ul {\n"+
	 "	position: absolute;\n"+
	 "	left: -999em;\n"+
	 "}\n\n"+
	 "ul.suckerfish li:hover ul, ul.suckerfish li.sfhover ul {\n"+
	 "	left: auto;\n"+
	 "}\n\n"+
	 "ul.suckerfish ul li {\n"+
	 "	float: none;\n"+
	 "	border-right: 0;\n"+
	 "	border-left:0;\n"+
	 "}\n\n"+
	 "ul.suckerfish a, ul.suckerfish a:hover {\n"+
	 "	display: block;\n"+
	 "}\n\n"+
	 "ul.suckerfish li a.tiddlyLink, ul.suckerfish li a, #mainMenu ul.suckerfish li a {font-weight:bold;}\n"+
	 "/**** END LAYOUT STYLES *****/\n"+
	 "\n\n"+
	 "/**** COLORS AND APPEARANCE - DEFAULT *****/\n"+
	 "ul.suckerfish li a {\n"+
	 "	padding: 0.5em 1.5em;\n"+
	 "	color: #FFF;\n"+
	 "	background: #0066aa;\n"+
	 "	border-bottom: 0;\n"+
	 "	font-weight:bold;\n"+
	 "}\n\n"+
	 "ul.suckerfish li:hover a, ul.suckerfish li.sfhover a{\n"+
	 "	background: #00558F;\n"+
	 "}\n\n"+
	 "ul.suckerfish li:hover ul a, ul.suckerfish li.sfhover ul a{\n"+
	 "	color: #000;\n"+
	 "	background: #eff3fa;\n"+
	 "	border-top:1px solid #FFF;\n"+
	 "}\n\n"+
	 "ul.suckerfish ul li a:hover {\n"+
	 "	background: #e0e8f5;\n"+
	 "}\n\n"+
	 "ul.suckerfish li a{\n"+
	 "	width:9em;\n"+
	 "}\n\n"+
	 "ul.suckerfish ul li a, ul.suckerfish ul li a:hover{\n"+
	 "	display:inline-block;\n"+
	 "	width:9em;\n"+
	 "}\n\n"+
	 "ul.suckerfish li {\n"+
	 "	border-left: 1px solid #00558F;\n"+
	 "}\n"+
	 "/***** END COLORS AND APPEARANCE - DEFAULT *****/\n"+
	 "\n\n"+
	 "/***** LAYOUT AND APPEARANCE: VERTICAL *****/\n"+
	 "ul.suckerfish.vertical li{\n"+
	 "	width:10em;\n"+
	 "	border-left: 0px solid #00558f;\n"+
	 "}\n\n"+
	 "ul.suckerfish.vertical ul li, ul.suckerfish.vertical li a, ul.suckerfish.vertical li:hover a, ul.suckerfish.vertical li.sfhover a {\n"+
	 "	border-left: 0.8em solid #00558f;\n"+
	 "}\n\n"+
	 "ul.suckerfish.vertical li a, ul.suckerfish.vertical li:hover a, ul.suckerfish.vertical li.sfhover a,  ul.suckerfish.vertical li.sfhover a:hover{\n"+
	 "	width:8em;\n"+
	 "}\n\n"+
	 "ul.suckerfish.vertical {\n"+
	 "	width:10em; text-align:left;\n"+
	 "	float:left;\n"+
	 "}\n\n"+
	 "ul.suckerfish.vertical li a {\n"+
	 "	padding: 0.5em 1em 0.5em 1em;\n"+
	 "	border-top:1px solid  #fff;\n"+
	 "}\n\n"+
	 "ul.suckerfish.vertical, ul.suckerfish.vertical ul {\n"+
	 "	line-height:1.4em;\n"+
	 "}\n\n"+
	 "ul.suckerfish.vertical li:hover ul, ul.suckerfish.vertical li.sfhover ul { \n"+
	 "	margin: -2.4em 0 0 10.9em;\n"+
	 "}\n\n"+
	 "ul.suckerfish.vertical li:hover ul li a, ul.suckerfish.vertical li.sfhover ul li a {\n"+
	 "	border: 0px solid #FFF;\n"+
	 "}\n\n"+
	 "ul.suckerfish.vertical li:hover a, ul.suckerfish.vertical li.sfhover a{\n"+
	 "	padding-right:1.1em;\n"+
	 "}\n\n"+
	 "ul.suckerfish.vertical li:hover ul li, ul.suckerfish.vertical li.sfhover ul li {\n"+
	 "	border-bottom:1px solid  #fff;\n"+
	 "}\n\n"+
	 "/***** END LAYOUT AND APPEARANCE: VERTICAL *****/\n"+
	 "/*}}}*/";
store.addNotification("StyleSheetDropDownMenuPlugin",refreshStyles);
//!END-PLUGIN-CODE
// %/
題目:老庫庫紡織公司,因公司網路年久失修,希望找網路達人改善公司的網路, 目前公司網路架構如下:
三十部個人電腦、二部伺服器,分置於十一及十二樓層。十一樓是屬於決策單位,此層樓有十部電腦,小機房也在十一樓(含二部 Server),其餘均在十二樓,請同學針對這家公司提出改善計畫
提示:

   1. 請畫出網路架構圖(用 Visio 繪製)
   2. 硬體報價(網路裝置品牌報價)、服務報價

注意:老闆的預算只有十萬元哦!
(老師的評分標準,視各組同學所提出的方案,成本價格合理又可改善企業網路最佳解決方案為優)

<<toBalaNotes "1">>


///%1
//%/


是非題作答說明:以下共有20題,請於每題括號()中作答,題意正確請畫○,錯誤請畫╳。每題5分,總分100分。

( )1、個資法是用來保障民眾個人隱私的法律。

( )2、「個人資料保護法」的前身是「電腦處理個人資料保護法」。

( )3、個資法正式實施時間由行政院決定。

( )4、姓名、出生年月日、身分證號、特徵、聯絡方式等可直接或間接識別出這位民眾的資料都是個人資料。

( )5、抄寫在紙上的個資,不會受到個資法的規範。

( )6、個資法是法務部門的工作,員工不需要了解。

( )7、違反個資法頂多被罰錢,不會有刑責。

( )8、公家機關不需要遵守個資法。

( )9、一般民眾不需要遵守個資法。

( )10、營收不高的中小企業,不需要遵守個資法。

( )11、只有蒐集個資,但還沒有使用時,可以不遵守個資法的規範。

( )12、民眾有權要求企業停止蒐集自己的個人資料。

( )13、企業只要做好資訊安全,就足以符合個資法的規範。

( )14、企業擁有的個資大多儲存在資訊系統中,所以,個資保護交給資訊部門負責就夠了。

( )15、臺灣企業只要將蒐集顧客個資的網站設在海外機房,就不會受到個資法的規範。

( )16、企業委託第三方廠商蒐集個資,就可以不用對這些個資的違法行為負責。

( )17、中央主管機關依法有權派人檢查企業的個資保護措施。

( )18、地方縣市政府依法有權派人檢查企業的個資保護措施。

( )19、企業發生個資外洩事件時,只要有20位受到影響的當事人提出告訴,就可以進行團體訴訟來求償。

( )20、單一個資外洩事件造成多人權利受損時,若無法估算實際損失,求償總金額的上限是2億元。

解答:個資法觀念隨堂考1(基礎觀念篇)

第1題解答:O
個資法第1條規定,為規範個人資料之蒐集、處理及利用,以避免人格全受侵害,並促進個人資料之合理利用,特制定本法。

第2題解答:O
「個人資料保護法」的前身是「電腦處理個人資料保護法」。

第3題解答:O
個資法第56條規定,實施日期由行政院決定,但行政院尚未宣布施行時間。

第4題解答:O
個資法第2條第一項第一款規定,個人資料:指自然人之姓名、出生年月日、國民身分證統一編號、護照號碼、特徵、指紋、婚姻、家庭、教育、職業、病歷、醫療、基因、性生活、健康檢查、犯罪前科、聯絡方式、財務情況、社會活動及其他得以直接或間接方式識別該個人之資料。

第5題解答:X
個資不論採取何種保存形式,包括紙本和數位形式,都需要遵循個資法的規範。

第6題解答:X
企業中的每一名員工都有機會經手、處理或利用到個人資料,所以,人人都必須了解個資法。

第7題解答:X
個資法第41條規定,違反相關條款,足生損害於他人者,處二年以下有期徒刑、拘役或科或併科新臺幣二十萬元以下罰金。

第8題解答:X
個資法一體適用於各產業,不論公務機關或非公務機關都需要遵循個資法。

第9題解答:X
個資法規範的非公務機關包括了自然人、法人和其他團體,民眾就是所謂的自然人。

第10題解答:X
個資法規範的非公務機關包括了自然人、法人和其他團體。企業屬於非公務機關,不分產業、營收規模都有納入規範。

第11題解答:X
個資法規範了個人資料的蒐集、處理及利用。只有蒐集還沒使用也要符合個資法。

第12題解答:O
個資法第 3條規定,民眾對個人資料的權利包括了查詢或請求閱覽、請求製給複製本、請求補充或更正、請求停止蒐集、處理或利用,以及請求刪除。

第13題解答:X
個資法的精神是隱私權保護,涵蓋範圍比資訊安全更廣,只有確保資訊安全還不夠。

第14題解答:X
老闆或任何員工蒐集、處理或利用個資時,都需要遵循個資法,所以,這不只是資訊部門的責任,而是全公司所有成員的責任。

第15題解答:X
個資法第51條第二項規定,公務機關及非公務機關,在中華民國領域外對中華民國人民個人資料蒐集、處理或利用者,亦適用本法。所以,臺灣企業網站設置在海外仍要符合個資法規範。

第16題解答:X
個資法第4條規定,受公務機關或非公務機關委託蒐集、處理或利用個人資料者,於本法適用範圍內,視同委託機關。

第17題解答:O
中央主管機關依法有權派人檢查企業的個資保護措施。

第18題解答:O
地方縣市政府依法有權派人檢查企業的個資保護措施。

第19題解答:O
個資法第34條規定,20位以上因同一原因受損害的當事人可以提出團體訴訟來求償。

第20題解答:O
個資法第28條第4項規定,對於同一原因事實造成多數當事人權利受侵害之事件,經當事人請求損害賠償者,其合計最高總額以新臺幣二億元為限。但因該原因事實所涉利益超過新臺幣二億元者,以該所涉利益為限。
<<toBalaNotes "1">>


///%1
//%/
是非題作答說明:以下共有20題,請於每題括號()中作答,題意正確請畫○,錯誤請畫╳。每題5分,總分100分。

( )1、新版個資法已於民國99年5月26日由總統公告,公告後就開始實施。

( )2、新版個資法不只保護電子資料,也將紙本資料納入保護範圍之內。

( )3、個資法實施後,公司不能在網頁上公布員工的任何個人資料。

( )4、企業內部蒐集的民眾個人資料,民眾無權要求企業刪除。

( )5、當企業委託第三方廠商來蒐集顧客個人資料時,若發生了個資外洩問題,一切都由委外廠商負責賠償即可。

( )6、為了充分了解客戶情報,企意搜集到個人資料內容越多越好,這些個資未來都可以任意運用。

( )7、醫療、基因、性生活、健康檢查及犯罪前科等個人敏感性資料,只要有法律明文規定,還是可以蒐集、處理或利用。

( )8、個資的蒐集、處理和利用,如果需要徵求當事人的書面同意時,只能使用紙本形式的書面同意書。

( )9、企業任何蒐集、處理和利用個資的行為,都需要事先告知這些個資的當事人。

( )10、企業蒐集的個資使用期限屆滿後,取得當事人書面同意就能繼續再利用這些個資。

( )11、企業如果發生個資外洩事件時,為了避免造成當事人的恐慌,除非被媒體揭露,否則企業不需要通知個資當事人有個資外洩的事情。

( )12、民眾向企業請求,瀏覽自己保存在企業中的個人資料時,因為這是個資法規定的當事人權利,所以民眾不需要支付任何費用。

( )13、企業合法利用民眾個資來行銷時,若當事人表示拒絕接受行銷,企業可以等過一陣子之後,再重新嘗試一次。

( )14、企業發生個資外洩導致民眾權利受損時,受此事件影響的民眾可聯合求償,金額上限是2億元,若能證明實際損害超過2億元,則可以實際損害求償。

( )15、民眾若因企業個資外洩造成個人權利損害,即使事隔超過10年,都可以向造成個資外洩的企業進行求償。

( )16、個資法為了保護個資當事人的權益,只要有20位以上的當事人提出告訴,就可以進行團體訴訟。

( )17、個資求償需由當事人提出告訴,但意圖販售個資營利的行為則屬於公訴罪。

( )18、企業因個資外洩遭判罰鍰時,公司負責人若不能證明自己盡到防止個資外洩的義務,負責人也要接受相同金額的罰鍰。

( )19、民眾為了朋友慶生而整理親友名單和聯絡電話時,也要符合個資法的規範。

( )20、員工未經當事人同意,逕行將親友姓名和手機,提供給企業作為行銷之用。企業必須在個資法施行後的1年內,告知這些間接取得聯絡資訊的當事人,讓他們知道企業擁有這些聯絡資料。

{{item1{解答:個資法觀念隨堂考2(進階觀念篇)}}}

第1題解答:X
新版個資法已於民國99年5月26日由總統公告,但實施時間須由行政院決定,目前尚未實施。

第2題解答:O
只要是個人資料,不論是電子、紙本資料或在任何載具上,都屬於個資法的保護範圍。

第3題解答:X
上網公開屬於利用行為的一種,只要符合個資法對利用行為的要求,個資是可以上網公開。例如有其他法律規定時可公開, 像是上市公司依法要在財報中揭露發言人聯絡方式。

第4題解答:X
根據新版個資法第3條規定,當事人就其個人資料可以行使查詢或請求閱覽,請求製給複製本,請求補充或更正,請求停止蒐集、處理或利用,以及請求刪除等權利,而且不得預先拋棄或以特約限制。

第5題解答:X
根據新版個資法第4條規定,受公務機關或非公務機關委託蒐集、處理或利用個人資料者,於本法適用範圍內,視同委託機關。

第6題解答:X
根據個資法第5條規定,個人資料之蒐集、處理或利用,不得逾越特定目的之必要範圍,應與蒐集之目的具有正當合理之關聯。企業對個人資料的運用,應有合理限制。

第7題解答:O
根據新版個資法第6條規定,有關醫療、基因、性生活、健康檢查及犯罪前科之個人資料,不得蒐集、處理或利用;但如果有其他法律相關規定等,經一定合法程序所做的蒐集、處理或利用之個人資料,才可以進行敏感性個資的蒐集、處理和利用。

第8題解答:X
根據已釋出的個資法施行細則草案版本,書面同意可以採用電子文件表示。根據電子簽章法的精神,企業取得書面同意時,能以電子文件的形式表示,除特定情況需要數位簽章外,其餘的電子文件形式,只要企業自負舉證責任即可採用。

第9題解答:X
根據新版個資法第8條第2項規定,有下列情形之一者,得免告知:一、依法律規定得免告知。二、個人資料之蒐集係公務機關執行法定職務或非公務機關履行法定義務所必要。三、告知將妨害公務機關執行法定職務。四、告知將妨害第三人之重大利益。五、當事人明知應告知之內容。

第10題解答:O
根據新版個資法第11條第3項規定,個人資料蒐集之特定目的消失或期限屆滿時,應主動或依當事人之請求,刪除、停止處理或利用該個人資料。但因執行職務或業務所必須或經當事人書面同意者,不在此限。

第11題解答:X
根據新版個資法第12條規定,公務機關或非公務機關違反本法規定,致個人資料被竊取、洩漏、竄改或其他侵害者,應查明後以適當方式通知當事人。

第12題解答:X
根據新版個資法第14條規定,查詢或請求閱覽個人資料或製給複製本者,公務機關或非公務機關得酌收必要成本費用。

第13題解答:X
根據新版個資法第20條第2項規定,非公務機關利用個人資料行銷者,當事人表示拒絕接受行銷時,應即停止利用其個人資料行銷。

第14題解答:O
根據新版個資法第28條,非公務機關違反個資法規定時,對於同一原因事實造成多數當事人權利受侵害之事件,經當事人請求損害賠償者,其合計最高總額以新臺幣二億元為限。但因該原因事實所涉利益超過新臺幣二億元者,以該所涉利益為限。同一原因事實造成之損害總額逾前項金額時,被害人所受賠償金額,不受第三項所定每人每一事件最低賠償金額新臺幣五百元之限制。

第15題解答:X
根據新版個資法第30條規定,損害賠償請求權,自請求權人知有損害及賠償義務人時起,因二年間不行使而消滅;自損害發生時起,逾五年者,亦同。

第16題解答:O
根據個資法第34條第1項規定,對於同一原因事實造成多數當事人權利受侵害之事件,財團法人或公益社團法人經受有損害之當事人20人以上以書面授與訴訟實施權者,得以自己之名義,提起損害賠償訴訟。

第17題解答:O
根據新版個資法第45條規定,本章之罪,須告訴乃論。但犯第四十一條第二項個資意圖營利之罪者,或對公務機關犯第四十二條之罪者,不在此限。

第18題解答:O
根據新版個資法第50條規定,非公務機關之代表人、管理人或其他有代表權人,因該非公務機關依前三條規定受罰鍰處罰時,除能證明已盡防止義務者外,應並受同一額度罰鍰之處罰。

第19題解答:X
根據新版個資法第51條第1項規定,有下列情形之一者,不適用新版個資法規定:一、自然人為單純個人或家庭活動之目的,而蒐集、處理或利用個人資料。二、於公開場所或公開活動中所蒐集、處理或利用之未與其他個人資料結合之影音資料。

第20題解答:O
根據新版個資法第54條規定,本法修正施行前非由當事人提供之個人資料,依第九條規定應於處理或利用前向當事人為告知者,應自本法修正施行之日起一年內完成告知,逾期未告知而處理或利用者,以違反第九條規定論處。 

<<toBalaNotes "1">>

///%1
//%/
<<importTiddlers inline>>
<<exportTiddlers inline>>
/***
|''Name:''|LaunchApplicationPlugin|
|''Author:''|Lyall Pearce|
|''Source:''|http://www.Remotely-Helpful.com/TiddlyWiki/LaunchApplication.html|
|''License:''|[[Creative Commons Attribution-Share Alike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''Version:''|1.4.0|
|''~CoreVersion:''|2.3.0|
|''Requires:''| |
|''Overrides:''| |
|''Description:''|Launch an application from within TiddlyWiki using a button|
!!!!!Usage
<<<
{{{<<LaunchApplication "buttonLabel" "tooltip" "application" ["arguments" ...]>>}}}
{{{<<LaunchApplicationButton "buttonLabel" "tooltip" "application" ["arguments" ...]>>}}}
{{{<<LaunchApplicationLink "buttonLabel" "tooltip" "application" ["arguments" ...]>>}}}
* buttonLabel is anything you like
* tooltip is anything you like
* application is a path to the executable (which is Operating System dependant)
* arguments is any command line arguments the application requires.
* You must supply relative path from the location of the TiddlyWiki OR a fully qualified path
* Forward slashes works fine for Windows

{{{<<LaunchApplication...>>}}} functions the same as {{{<<LaunchApplicationButton...>>}}}

eg.

{{{
<<LaunchApplicationButton "Emacs" "Linux Emacs" "file:///usr/bin/emacs">>
}}}
<<LaunchApplicationButton "Emacs" "Linux Emacs" "file:///usr/bin/emacs">>

{{{
<<LaunchApplicationLink "LocalProgram" "Program relative to Tiddly html file" "localDir/bin/emacs">>
}}}
<<LaunchApplicationLink "LocalProgram" "Program relative to Tiddly html file" "localDir/bin/emacs">>
					     
{{{
<<LaunchApplicationButton "Open Notepad" "Text Editing" "file:///e:/Windows/notepad.exe">>
}}}
<<LaunchApplicationButton "Open Notepad" "Text Editing" "file:///e:/Windows/notepad.exe">>

{{{
<<LaunchApplicationLink "C Drive" "Folder" "file:///c:/">>
}}}
<<LaunchApplicationLink "C Drive" "Folder" "file:///c:/">>


!!!!!Revision History
* 1.1.0 - leveraged some tweaks from from Bradly Meck's version (http://bradleymeck.tiddlyspot.com/#LaunchApplicationPlugin) and the example text.
* 1.2.0 - Make launching work in Linux too and use displayMessage() to give diagnostics/status info.
* 1.3.0 - execute programs relative to TiddlyWiki html file plus fix to args for firefox.
* 1.3.1 - parameters to the macro are properly parsed, allowing dynamic paramters using {{{ {{javascript}} }}} notation.
* 1.4.0 - updated core version and fixed empty tooltip and added launch link capability
***/
ZigBee 是一種無線網路協定,主要由 ZigBee Alliance 制定,底層是採用 IEEE 802.15.4 標準規範的媒體存取層與實體層。主要特色有低速、低耗電、低成本、支援大量網路節點、支援多種網路拓撲、低复杂度、快速、可靠、安全。

{{item1{ZigBee是什麼?}}}
ZigBee是一種家庭區域網路,特別為取代不斷增加的獨立遙控器而設計。當初建構ZigBee是為了滿足市場對支援低資料速率、低功耗、安全可靠的基於標準的低成本無線網路的需求。為解決這樣的需求,ZigBee聯盟在IEEE 802.15.4無線標準之上開發了標準化的應用軟體。該聯盟與IEEE密切合作以保證為市場提供一個整合的、完整的和可互操作的網路。例如,該工作組將提供包括ZigBee軟體層的802.15.4系統互通性測試認證。

ZigBee聯盟還將作為ZigBee設備的官方測試和認證部門。ZigBee是唯一滿足絕大多數遠端檢測、控制和感測器網路應用的基於標準的技術。

將IEEE 802.15.4 看成是無線傳輸的實體部分,ZigBee是邏輯網路和應用軟體部分或許會有所幫助,如圖1所示。在緊接著標準開放系統互連(Open Systems Interconnection,OSI)參考模型之後,ZigBee協議堆疊按層構建。頭兩層是實體層(PHY)和媒體存取層(MAC),在IEEE 802.15.4標準中定義。在這兩層之上的層由ZigBee聯盟定義。IEEE工作組在2003年通過了PHY和MAC的第一次草案。網路(NWK)層的最終版本預期在今年的某個時間推出。

滿足ZigBee標準的產品工作在全球的免授權頻段,包括2.4GHz(全球)、 902到928MHz(美洲)和868MHz(歐洲)。在2.7GHz(16個通道)可以達到250Kbps的原始資料吞吐率,在915MHz(10個通道)為40Kbps,868MHz(1個通道)為20Kbps。預計的傳輸距離為10公尺到75公尺,取決於輸出功率和環境參數。像Wi-Fi和 Zigbee利用2.4GHz頻段直接序列擴頻,採用偏移-正交相移鍵控調製。通道頻寬為2MHz,通道間距為5MHz。868和900MHz頻段也採用直接序列擴頻,但是採用二進位相移鍵控。
本文網址 : http://www.ithome.com.tw/itadm/article.php?c=60768

不明來路的執行檔案連結不能點,這已經是很多人都擁有的資安常識。不過你是否也知道,PDF也有可能成為攻擊手法的一種?

不明來路的執行檔案連結不能點,這已經是很多人都擁有的資安常識。不過你是否也知道,PDF也有可能成為攻擊手法的一種?不光如此,最近更有資安研究員展示了不用利用PDF Reader軟體漏洞,就能以社交工程和PDF檔案原本允許的功能,誘騙使用者連上惡意網站或執行惡意程式的手法。


最近,兩位資安研究員,相繼發現了不需要透過漏洞,就能利用PDF原本的功能,進行惡意攻擊的手法,並且公開將過程展示在Youtube上。事實上,透過 PDF這一類文件檔案進行的攻擊手法,已經越來越普遍,這也使得這兩位研究員的發現,掀起了一股風波。

在臺灣,每年行政院國家資通安全會報都會進行「電子郵件社交工程演練」,針對各個機關發送社交工程攻擊手法的模擬攻擊電子郵件,假冒各個不同單位發信,測試看看有多少人會無預警的打開郵件裡的連結或附檔。以2007年12月的結果來看,平均24.17%的使用者會打開郵件;16.29%的使用者會進一步打開連結或附件。其中,詐騙成功率最高的,是以夾帶惡意文件檔的方式誘騙使用者點擊。測試中,每年都有5~8%的使用者會打開這樣類型的惡意文件檔案。

[[與社交工程手法混用,惡意文件檔成為有效攻擊手法|http://www.ithome.com.tw/itadm/article.php?c=60768&s=2]]
傳統來路不明的執行檔和連結,誘騙使用者點擊的攻擊手法,已經逐漸不那麼有效了;但是文件檔,如PDF、Office文件等,則反而成為了新的可利用手法

[[不需漏洞,攻擊者也可以透過PDF讓使用者執行程式|http://www.ithome.com.tw/itadm/article.php?c=60768&s=3]]
透過在PDF檔案中寫入/Launch指令的手法,可以讓使用者只要執行特定的PDF檔案,連帶就自動執行其他任何程式

[[不要高估 PDF 的安全性|http://www.ithome.com.tw/itadm/article.php?c=60768&s=4]]
目前看來,唯一能夠阻止這種手法的防範之道,只有透過偏好設定裡的信任管理程式,把允許使用外部應用程式開啟非PDF檔案附件的選項關掉

[[社交工程結合惡意文件防不勝防|http://www.ithome.com.tw/itadm/article.php?c=60768&s=5]]
幾位國外的資安研究員公開展示了不用透過漏洞,直接以社交工程與惡意文件檔案結合的方式,執行惡意程式的手法

[[可能的攻擊手法|http://www.ithome.com.tw/itadm/article.php?c=60768&s=6]]
一為先變更Reader的設定,再竊取資料;二為可能透過PDF做DDoS或破壞性的攻擊

[[防堵 PDF 文件攻擊的4大方法|http://www.ithome.com.tw/itadm/article.php?c=60768&s=7]]
雖然目前還沒有完全能夠百分之百防護的有效方法,不過對於企業或組織來說,還是有4個方法可以參考使用,多管齊下降低危險性 
目前現有的協作產品如微軟自家SharePoint、IBM Lotus等,都需部署伺服器,檔案要透過伺服器存取。不過走P2P架構的Groove,檔案就存在使用者電腦。

微軟去年推出Office 2007產品線旗下的協同作業平台Groove,六月將有文版產品,和先前推出協作平台SharePoint不同的是,Groove走的是P2P架構,不需部署伺服器。

Groove在去年推出Office 2007時就已包含在內,不過只有英文版本。目前在商用版、旗鑑版當中都附有Groove,也可單買。

台灣微軟營運暨行銷事業群資深產品行銷經理盧道正指出,Groove是文件分享的協作工具,此產品的特殊之處在於採用P2P架構。目前現有的協作產品如微軟自家SharePoint、IBM Lotus等,都需部署伺服器,檔案要透過伺服器存取。不過走P2P架構的Groove,檔案就存在使用者電腦。

盧道正說,雖然同是協作軟體,但Groove和SharePoint並不會有衝突,因為Groove適合多對多的應用,而SharePoint則適合一對多,並不會造成自家產品互打的狀況。

微軟在上月(3/17)針對學生族群引進國外的校園低價專案時,同時宣佈推出含有Groove的Office旗鑑版本。由於不需部署伺服器,可簡單的連線使用,因此微軟也希望藉由校園專案將Groove推向學生族群。

這也是Groove和SharePoint的區隔,因為部署簡單,所以不僅可用於企業內部文件分享、討論,學生在進行團體報告時也可以 Groove搭配Office使用。而且價格低廉,透過學生專案購買含有Groove的旗鑑版Office為1990元;而在六月中文版推出後,以單一產品購買要五千多元。

消費端檔案分享產品暫不引進台灣

除了企業端協作軟體外,微軟本月(4)也在國外正式發表針對消費市場的Office Live Workspace,不過目前暫無打算引進台灣。

盧道正澄清,Office Live Workspace並不能算是「線上版」的Office,使用者電腦中還是必須裝有文書處理軟體,Office Live Workspace只是進行檔案分享,如同協作平台,並可共用螢幕。

Office Live Workspace走的也是伺服器架構,不過是微軟針對消費端的產品,SharePoint則是主攻企業端。對於微軟上週(4/18)開始進行封閉測試、代號為Albany的生產力軟體套件,台灣微軟則表示並不清楚。
以公司內部來說,我想除了打掃的阿桑之外,最圓融、最常在大家身旁奔走的人,一定少不了「MIS」,因為他通常都得要火裡來、水裡去,那邊需要救火就往那邊去,所以對於MIS來說,對於每個人的處事原則,或多或少都有一定程度的瞭解,知道對那些人應該強硬,那些人適合委婉,這一點在處理上面交辦事務的時候,絕對可以派上用場。

當然也是有冷面的MIS存在,通常都是讓人敬畏三分,非到必要絕不找他上門的隱藏人物,雖然這種型態的MIS也能處置好某些事務(尤其是要硬派作風才能夠推行的事),但是,對於要處理更細膩與人互動的問題時,這類MIS就會相當為難,畢竟他對於其它同儕的心性,瞭解的並不夠深,很容易就會弄巧成拙或是把自己搞的焦頭爛額。

除此之外,MIS應該採用的處置方式,除了考量人性之外,最好在資訊專業上也要有所堅持,千萬不要因為使用者的諸多要求而自亂陣腳,很多時候使用者的習慣並不代表唯一途徑,有時他們的做法不太合乎邏輯(延用舊法),這時候最好的方式就是以身作則,自己實際去體驗一次他們的做法,再跟自己所設想的方式來比較,如果能夠為他們來爭取到更多的休息時間,我想對於使用者來說,也就會有更多的誘因,千萬不要一昧的為改變而改變,因為有時他們看見的點,遠比我們這些臨危受命的空降部隊來的精闢。

雖然事必躬親不是一件完全正確的事,但是對於很多基層員工來說,那是一種最能夠讓他們信服的方式,同時也可以跟他們心中對那種愛唱高調的主管的區隔,也不妨是一種好的問題解決方式,只不過使用的時機得要經過評估,畢竟還是有時效壓力存在。

結論

從上述看來,MIS的立場與處置其實跟主管很類似,只不過他卻是最直接的執行者,他並不像很多主管,下面還有很多人可以使喚,因此,自己得要面對很多心態上的調整跟轉換,同時還要考量自己對於時間分配的功力,因為MIS同時還要處理自己手邊的庶務,畢竟MIS手上東西之雜,早已經是眾所皆知。

其實我只是想要突顯每個IT工作者,很有可能會因為自己的立場而有不同的處置方式,像程式開發者可能會因為自己的立場,忽略了使用者體驗所產生的負面影響;專案經理會因為自己的高度,忘記下面新鮮肝的戰力還有多少?

有時候置身處地的去"思考",或許能夠得到更多不一樣的腦內革命,縱使不一定得要親力親為,但是在立場跟處置方式之間,應該不僅只有一種方式,有時候繞個圈反而能夠走得比較遠,端看你是想要比氣長,還是想要搶時機,有時也可看出你的工作哲學及生涯規畫,並非每件事都非黑即白,有時多點不一樣的光彩,或許能有無限的可能,只是差在一念之間。 
文/郭和杰 (記者) 2010-01-18 	

經電算中心調查,在這次的網站被駭事件中,確定實體伺服器並未遭受入侵,駭客利用的是未修補的Apache漏洞。

教育部所屬的品德教育資源網站在周日晚間遭駭,並緊急將被駭的網站撤下。據了解,駭客所利用的是Apache漏洞。

「品德教育資源網」是教育部電子計算機中心委由國家教育研究院所架設,實體伺服器架設在國家教育研究院內。據電算中心組長莊育秀表示,昨夜在得知網站被駭之後,立即於深夜將被駭網頁撤下,並在今晨已派員前往教研所了解狀況。

經電算中心調查,在這次的網站被駭事件中,確定實體伺服器並未遭受入侵,駭客利用的是未修補的Apache漏洞。Apache是一個開放源碼的網頁伺服器,由於其跨平台特性而相當受到歡迎。

不過對於更多技術細節電算中心不願透露。據電算機中心表示,該網站大約在下午兩點半就正常上線,並已做好相關的系統備援。

教育部網站遭駭的訊息大約在周日晚間近11點時,首先由重灌狂人不來恩噗浪上發送出。昨夜連上該網站之後可見被駭網頁底色變黑之外,還有「Game Over」、帶有髏頭符號的「You’re Down!」,以及「HackeD By Tm3yShell7」等字樣。

據被駭網頁所留的資訊,品德教育網被駭可能起因於該網站把澳門的「德育中心網站」分類為「國外」網站而引起中國駭客的不滿。該名駭客在品德教育中心相關的網頁抓圖下方留話給網管人員「To administrator:大哥,你當您是美國的呢?把澳門叫國外?!……」等挑釁味十足的文字。

由於攻擊的技術細節不得而知,因此針對這個攻擊資安業者皆表示無法做深入分析。

但趨勢科技技術支援部經理簡勝財表示,通常來說,企業在避免網頁攻擊方面首先要注意經常修補作業系統、網頁伺服器、應用程式等安全漏洞之外,還必需注意網路管理權限的設定,例如預設的管理權限不能設得太高。此外,應用程式對於特殊字元(例如#、%、$…)的使用一定要做好管理。

然而,對於漏洞的修補問題,簡勝財表示,企業往往會陷於兩難。當企業知道有新漏洞時,若不修補,怕遭攻擊;若修補,又擔心因此而讓軟體無法正常運作等諸多問題。趨勢在去年底所推出的DeepSecurity可為企業提供進階的相關伺服器防護。

「李宗瑞」的相關新聞,果然具有高度吸引力,新北市政府日前在對員工進行資安測試時,竟然拿李宗瑞的影片「釣魚」,結果有近千名員工「中招」,必須上2個小時的資訊安全課程。

根據《蘋果日報》報導,新北市研考會2周前發出一封惡意電子郵件,給市府6179名公務員,郵件主旨竟然就寫著「李宗瑞影片,趕快下載呦!」經清查後發現,共有996名員工點選,由於員工對資訊安全的危機意識不足,將分梯次上資安課程。

不過,新北市政府的這項做法也引發爭議,一位被「釣魚」成功的女性員工在接受《蘋果日報》訪問時就表示:「大家都想看啊,被叫去上課好丟臉!」另一位在街頭接受訪問的黃小姐也認為新北市的做法是不對的!「怎麼可以用李宗瑞這種情色的議題來做測試,應該要有更細膩的規格來檢視人性。」

陳同學也對《蘋果日報》表示,「我覺得很不合理,每個人都有好奇心,這種作法有引誘犯罪的嫌疑,而且這個話題這麼夯,我也想看看。」

新北市資訊中心則表示,會針對時下熱門的各種話題,例如團購、旅遊等題材進行演練,因為李宗瑞是時下最受矚目的話題,才會這樣設計,沒想到有這麼多員工好奇。
華碩董事長施崇堂宣稱,所謂的Wintel時代已經終結。意思是PC市場不再能由一家OS廠商與一家CPU廠商所主導。Wintel的陣亡將為系統廠商提供能夠再度活躍於IT市場的新機會。

Wintel指的是Windows與Intel的組合,泛指使用英特爾的x86相容處理器執行Microsoft Windows的個人電腦,它通常被用來形容兩家公司在PC市場的主宰地位。

造成這種轉變當然得歸功於平板電腦市場的爆炸性成長,但我認為原因並非如此單純。我認為得歸因於行動PC的消費端化。當然,當桌上系統必須因為業務關係而具有可攜性時,我們發明了筆電。然而,當消費者開始購買筆電比企業購買的桌上系統還多的時候,Wintel的沒落就已經啟動了。

在這個現象發生時,網際網路也同時變的更為強大。由於相容性對消費者而言不像對企業般重要,於是非Wintel相容的替代方案開始嶄露頭角。PC突然變成不只能執行一種功能的電子裝置,而且它不一定是來自Wintel的組合。

 (ZDNet Taiwan編輯部/T.I.M譯)
/***
|<html><a name="Top"/></html>''Name:''|PartTiddlerPlugin|
|''Version:''|1.0.9 (2007-07-14)|
|''Source:''|http://tiddlywiki.abego-software.de/#PartTiddlerPlugin|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license]]|
|''CoreVersion:''|2.1.3|
|''Browser:''|Firefox 1.0.4+; InternetExplorer 6.0|
!Table of Content<html><a name="TOC"/></html>
* <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Description',null, event)">Description, Syntax</a></html>
* <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Applications',null, event)">Applications</a></html>
** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('LongTiddler',null, event)">Refering to Paragraphs of a Longer Tiddler</a></html>
** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Citation',null, event)">Citation Index</a></html>
** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('TableCells',null, event)">Creating "multi-line" Table Cells</a></html>
** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Tabs',null, event)">Creating Tabs</a></html>
** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Sliders',null, event)">Using Sliders</a></html>
* <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Revisions',null, event)">Revision History</a></html>
* <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Code',null, event)">Code</a></html>
!Description<html><a name="Description"/></html>
With the {{{<part aPartName> ... </part>}}} feature you can structure your tiddler text into separate (named) parts. 
Each part can be referenced as a "normal" tiddler, using the "//tiddlerName//''/''//partName//" syntax (e.g. "About/Features").  E.g. you may create links to the parts (e.g. {{{[[Quotes/BAX95]]}}} or {{{[[Hobbies|AboutMe/Hobbies]]}}}), use it in {{{<<tiddler...>>}}} or {{{<<tabs...>>}}} macros etc.


''Syntax:'' 
|>|''<part'' //partName// [''hidden''] ''>'' //any tiddler content// ''</part>''|
|//partName//|The name of the part. You may reference a part tiddler with the combined tiddler name "//nameOfContainerTidder//''/''//partName//. <<br>>If you use a partName containing spaces you need to quote it (e.g. {{{"Major Overview"}}} or {{{[[Shortcut List]]}}}).|
|''hidden''|When defined the content of the part is not displayed in the container tiddler. But when the part is explicitly referenced (e.g. in a {{{<<tiddler...>>}}} macro or in a link) the part's content is displayed.|
|<html><i>any&nbsp;tiddler&nbsp;content</i></html>|<html>The content of the part.<br>A part can have any content that a "normal" tiddler may have, e.g. you may use all the formattings and macros defined.</html>|
|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|
<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!Applications<html><a name="Applications"/></html>
!!Refering to Paragraphs of a Longer Tiddler<html><a name="LongTiddler"/></html>
Assume you have written a long description in a tiddler and now you want to refer to the content of a certain paragraph in that tiddler (e.g. some definition.) Just wrap the text with a ''part'' block, give it a nice name, create a "pretty link" (like {{{[[Discussion Groups|Introduction/DiscussionGroups]]}}}) and you are done.

Notice this complements the approach to first writing a lot of small tiddlers and combine these tiddlers to one larger tiddler in a second step (e.g. using the {{{<<tiddler...>>}}} macro). Using the ''part'' feature you can first write a "classic" (longer) text that can be read "from top to bottom" and later "reuse" parts of this text for some more "non-linear" reading.

<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!!Citation Index<html><a name="Citation"/></html>
Create a tiddler "Citations" that contains your "citations". 
Wrap every citation with a part and a proper name. 

''Example''
{{{
<part BAX98>Baxter, Ira D. et al: //Clone Detection Using Abstract Syntax Trees.// 
in //Proc. ICSM//, 1998.</part>

<part BEL02>Bellon, Stefan: //Vergleich von Techniken zur Erkennung duplizierten Quellcodes.// 
Thesis, Uni Stuttgart, 2002.</part>

<part DUC99>Ducasse, Stéfane et al: //A Language Independent Approach for Detecting Duplicated Code.// 
in //Proc. ICSM//, 1999.</part>
}}}

You may now "cite" them just by using a pretty link like {{{[[Citations/BAX98]]}}} or even more pretty, like this {{{[[BAX98|Citations/BAX98]]}}}.

<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!!Creating "multi-line" Table Cells<html><a name="TableCells"/></html>
You may have noticed that it is hard to create table cells with "multi-line" content. E.g. if you want to create a bullet list inside a table cell you cannot just write the bullet list
{{{
* Item 1
* Item 2
* Item 3
}}}
into a table cell (i.e. between the | ... | bars) because every bullet item must start in a new line but all cells of a table row must be in one line.

Using the ''part'' feature this problem can be solved. Just create a hidden part that contains the cells content and use a {{{<<tiddler >>}}} macro to include its content in the table's cell.

''Example''
{{{
|!Subject|!Items|
|subject1|<<tiddler ./Cell1>>|
|subject2|<<tiddler ./Cell2>>|

<part Cell1 hidden>
* Item 1
* Item 2
* Item 3
</part>
...
}}}

Notice that inside the {{{<<tiddler ...>>}}} macro you may refer to the "current tiddler" using the ".".

BTW: The same approach can be used to create bullet lists with items that contain more than one line.

<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!!Creating Tabs<html><a name="Tabs"/></html>
The build-in {{{<<tabs ...>>}}} macro requires that you defined an additional tiddler for every tab it displays. When you want to have "nested" tabs you need to define a tiddler for the "main tab" and one for every tab it contains. I.e. the definition of a set of tabs that is visually displayed at one place is distributed across multiple tiddlers.

With the ''part'' feature you can put the complete definition in one tiddler, making it easier to keep an overview and maintain the tab sets.

''Example''
The standard tabs at the sidebar are defined by the following eight tiddlers:
* SideBarTabs
* TabAll
* TabMore
* TabMoreMissing
* TabMoreOrphans
* TabMoreShadowed
* TabTags
* TabTimeline

Instead of these eight tiddlers one could define the following SideBarTabs tiddler that uses the ''part'' feature:
{{{
<<tabs txtMainTab 
    Timeline Timeline SideBarTabs/Timeline 
    All 'All tiddlers' SideBarTabs/All 
    Tags 'All tags' SideBarTabs/Tags 
    More 'More lists' SideBarTabs/More>>
<part Timeline hidden><<timeline>></part>
<part All hidden><<list all>></part>
<part Tags hidden><<allTags>></part>
<part More hidden><<tabs txtMoreTab 
    Missing 'Missing tiddlers' SideBarTabs/Missing 
    Orphans 'Orphaned tiddlers' SideBarTabs/Orphans 
    Shadowed 'Shadowed tiddlers' SideBarTabs/Shadowed>></part>
<part Missing hidden><<list missing>></part>
<part Orphans hidden><<list orphans>></part>
<part Shadowed hidden><<list shadowed>></part>
}}}

Notice that you can easily "overwrite" individual parts in separate tiddlers that have the full name of the part.

E.g. if you don't like the classic timeline tab but only want to see the 100 most recent tiddlers you could create a tiddler "~SideBarTabs/Timeline" with the following content:
{{{
<<forEachTiddler 
		sortBy 'tiddler.modified' descending 
		write '(index < 100) ? "* [["+tiddler.title+"]]\n":""'>>
}}}
<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!!Using Sliders<html><a name="Sliders"/></html>
Very similar to the build-in {{{<<tabs ...>>}}} macro (see above) the {{{<<slider ...>>}}} macro requires that you defined an additional tiddler that holds the content "to be slid". You can avoid creating this extra tiddler by using the ''part'' feature

''Example''
In a tiddler "About" we may use the slider to show some details that are documented in the tiddler's "Details" part.
{{{
...
<<slider chkAboutDetails About/Details details "Click here to see more details">>
<part Details hidden>
To give you a better overview ...
</part>
...
}}}

Notice that putting the content of the slider into the slider's tiddler also has an extra benefit: When you decide you need to edit the content of the slider you can just doubleclick the content, the tiddler opens for editing and you can directly start editing the content (in the part section). In the "old" approach you would doubleclick the tiddler, see that the slider is using tiddler X, have to look for the tiddler X and can finally open it for editing. So using the ''part'' approach results in a much short workflow.

<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!Revision history<html><a name="Revisions"/></html>
* v1.0.9 (2007-07-14)
** Bugfix: Error when using the SideBarTabs example and switching between "More" and "Shadow". Thanks to cmari for reporting the issue.
* v1.0.8 (2007-06-16)
** Speeding up display of tiddlers containing multiple pard definitions. Thanks to Paco Rivière for reporting the issue.
** Support "./partName" syntax inside <<tabs ...>> macro
* v1.0.7 (2007-03-07)
** Bugfix: <<tiddler "./partName">> does not always render correctly after a refresh (e.g. like it happens when using the "Include" plugin). Thanks to Morris Gray for reporting the bug.
* v1.0.6 (2006-11-07)
** Bugfix: cannot edit tiddler when UploadPlugin by Bidix is installed. Thanks to José Luis González Castro for reporting the bug.
* v1.0.5 (2006-03-02)
** Bugfix: Example with multi-line table cells does not work in IE6. Thanks to Paulo Soares for reporting the bug.
* v1.0.4 (2006-02-28)
** Bugfix: Shadow tiddlers cannot be edited (in TW 2.0.6). Thanks to Torsten Vanek for reporting the bug.
* v1.0.3 (2006-02-26)
** Adapt code to newly introduced Tiddler.prototype.isReadOnly() function (in TW 2.0.6). Thanks to Paulo Soares for reporting the problem.
* v1.0.2 (2006-02-05)
** Also allow other macros than the "tiddler" macro use the "." in the part reference (to refer to "this" tiddler)
* v1.0.1 (2006-01-27)
** Added Table of Content for plugin documentation. Thanks to RichCarrillo for suggesting.
** Bugfix: newReminder plugin does not work when PartTiddler is installed. Thanks to PauloSoares for reporting.
* v1.0.0 (2006-01-25)
** initial version
想向你辭去情人的職務。任職一年多來,在崗位上我努力學習,克盡職守,對你噓寒問暖,小心翼翼,揣測你的需要,滿足你各方面需求。在感情提供你慰藉,讓你有被愛的感覺;在行動上,等待、接送、陪伴、更只是基本工作。雖不經手財務,卻要負起所有買單重責;三不五時還要送禮討你歡心。一個稱職的情人要溫柔體貼,還要心胸寬闊。聽你提及對別的男人的大方及讚賞,不可以醋勁大發。剛任職之時不知如何拿捏,犯了幾次錯誤竟敢與你鬧情緒, 幾度你想把我開除,後來在我保證不再犯的前提下,你勉強再給我觀察期。這些時日以來,幾經思索,感謝你給我這次機會。但我確實不適任此職位,想向你申請調回朋友部門。看你對那部門同仁有說有笑,三不五時還會請他們小聚一番,有點羨慕他們?上班時間彈性,不用隨 call隨到,不用接送,不用買單,不用送禮,不用面對你冷漠一面,可看到你陽光似的笑容,聽到你幽默言談。而我雖佔了情人的缺,除了責任加重卻沒任何特殊待遇;沒有甜言蜜語,沒有多一點關心,沒有禮物,沒有...決定辭去這職務,至於你是否願讓我調部門,一切尊重你的裁決....

  一個盡心盡力的員工
  敬上

女生的回覆

  Dear:
  關於您轉調部門的提議,經過董事家長會開會討論,以下決議事項向您說明:
  因您當初面試時的職務為情人,標準與要求一開始就跟朋友不同,雖然試用期間你的表現不好差點被開除,但念在你苦苦哀求且信誓旦旦的說明你可以改進與勝任,才予以留任。情人屬於正職工作,與兼職的朋友部門不同,當然責任與工作相對也比較多,但是薪資及福利保證優於朋友部門,情人有按摩、親親、抱抱、陪同參予家庭聚會與煮夜宵的紅利與福利,還有很好的陞遷渠道,可以升為老公、爸爸、阿公...等,這些絕對都是朋友部門所沒有的。最後,因目前朋友部門沒有職缺,情人又是重要職務,因此在未尋獲新人或職務代理人並完成交接前,先將您轉調到備胎部門,這個部門的人員不需要每天面對老闆,應該可以暫時讓您的責任跟壓力不那麼大。等情人職務有人可以交接時,可再將您轉調到地下情人部門,當然若屆時朋友部門有缺也可轉調到朋友部門,或是您要離職也可以,當然自動離職是沒有遣散費的。謝謝您一年多來的努力...

  董事會成員代表
  敬上

利用分層概念建置儲存系統,並按存取頻率,動態地讓資料在不同層級儲存裝置上,自動遷移存放位置,企圖在效能與成本間取得最佳平衡

分層儲存概念由來已久,可在不同等級儲存設備間自動搬移資料階層式儲存管理(Hierarchical Storage Management)產品,問世亦有十多年時間。

早期的HSM產品多半採用獨立部署的軟體形式,而且是以面對應用程式的方式運作。後來Compellent、3PAR等廠商則推出了整合在磁碟陣列控制器中的自動分層儲存功能,可作為儲存設備底層的基礎服務,免除另外安裝軟體的需要,還能提供更精細的管理功能。

近年來隨著高性能固態儲存裝置(SSD)的發展,進一步推動了自動分層儲存技術的需求,就連儲存界龍頭廠商EMC,亦在不久前推出了可適用於旗下主力儲存產品線的FAST全自動分層儲存技術,讓自動分層儲存技術走出過去僅針對特定領域、或新創公司產品的局面,開始進入主流廠商產品線中。

目的是兼顧效能與成本
階層式儲存管理的目的,是利用不同效能/價格的儲存設備組成儲存系統,藉以分別適應前端不同應用的需求,讓關鍵應用使用高效能儲存裝置,非關鍵應用則使用效能較低但也較廉價的儲存裝置,以便在控制儲存成本的同時,又能確保關鍵應用可獲得必要的效能。

顯然的,要讓階層式儲存管理發生效用,關鍵在於如何為前端不同需求的應用,適當地分配由不同層級儲存設備提供的空間,特別是必須因應前端存取行為的變化,持續調整後端儲存空間配置,以便讓儲存空間利用效率,始終維持在一定的水準上。

[img[img/linux/hfs01.jpg]]

''分層儲存技術的類型''

前述目的的實現,牽涉到三個基本程序:首先是儲存裝置的分層。傳統上通常依磁碟效能將系統分為三層:
{{{
第1層:效能最高、但單位容量價格也最高的1.5萬FC或SAS介面轉硬碟。

第2層:效能與單位容量價格中等的1萬轉FC或SAS介面硬碟。

第3層:效能最低、但單位容量價格也便宜的7,200轉SATA介面硬碟。
}}}

近來隨著固態硬碟的逐漸普及,也改變了傳統的儲存分層區分,由固態硬碟取代1.5萬轉硬碟的第1層地位,或是增加一個效能更高的第0層。

其次,資料先以預設配置分布在不同層級的儲存裝置上,接下來必須對前端存取行為進行持續的追蹤與記錄。

最後,便可依照追蹤與統計結果,定期執行資料搬移工作,將存取頻率高的資料搬移到由高效能儲存裝置組成的磁碟區,存取頻率低的資料則搬移到較低效能儲存裝置組成的磁碟區。

如此可限制系統耗用的高階儲存裝置容量,讓高階儲存裝置只用於存放高存取頻率的資料,而將大部份資料都存放在低價設備上,讓磁碟配置達到效能與成本最佳化。

前述工作可以人工執行,不過若涉及大型、複雜環境的管理,更好的做法是交由可按預設政策自動執行的系統來執行,藉以達到「全自動化分層儲存」。

自動化分層儲存基本上是兩個功能的綜合——資料存取行為的追蹤統計,以及定期的資料搬移。而依追蹤統計與資料搬移所針對的標的不同,又可分為以檔案為基礎、以區塊為基礎等兩種類型,前者是應用在NAS領域,後者則是應用在儲存區域網路領域,依執行的統計追蹤與資料搬移的單位粒度,又可分為區塊或 Volume兩種類型。

''粒度越小越有利''
一般說來,系統執行存取行為分析與資料搬移時,採用越小的粒度越有利,以幾百KB為單位的區塊來執行搬移作業,顯然比以數GB為單位的Volume或LUN,或以可能大到數百MB的檔案為單位更為理想,不僅消耗的資源較少,也能達到更高的儲存資源配置效率。

也就是說,在一個數GB的Volume或數百MB的檔案中,經常被存取的大都只是其中一小部分區塊(而非整個Volume或整份檔案),因此在執行資料分層遷移作業時,若系統能以更小的區塊作為單位,便能將真正經常存取的那些區塊保留在高效能儲存區域上,其餘部分則遷移到低價的儲存區域保存。比起遷移整個 Volume或整份檔案,在區塊層級上運作的系統,將更能發揮儲存空間的效益,牽涉到的資料搬移量也較小,可限制對系統運作造成的衝擊。

當然自動分層儲存也不是毫無代價。由於追蹤所有儲存區域或資料的存取行為,是執行自動化分層儲存的基礎,為了追蹤的需要,導致必須為資料區塊或檔案,附加上額外的metadata或標記,這除了會耗損實際可用容量外,也會增加控制器的負擔。而且若運作的粒度越小,則相對應須追蹤的metadata數量也越多,相對也更增加控制器的負荷。

另外資料搬移動作也相當消耗磁碟資源,因此妥當設定資料遷移政策,也成為實際部署自動分層儲存技術非常重要的環節,除了必須避開系統尖峰時間外,執行排程的設定也有許多需要考量之處—若資料搬移作業時程間隔過長,顯然無法讓儲存空間配置持續維持在最佳效率的組態上:但若資料搬移作業太過頻繁,又有影響正常存取的疑慮。

<html><img src="img/linux/hfs02.jpg" /></html>
前些日子和異塵兄在討論 螢幕截圖是用 JPG 格式來存好呢,或是用 PNG 格式比較好?基於科學的精神,上網找了一下,Wikipedia 果然敘述的鉅細靡遺,PNG 和 JPG 優缺點分析如下:

JPEG can produce a smaller file than PNG for photographic (and photo-like) images since it uses a lossy encoding method specifically designed for photographic image data. Using PNG instead of a high-quality JPEG for such images would result in a large increase in filesize (often 5-10 times) with negligible gain in quality.

JPEG 在面對自然影像的時候,由於是採用失真壓縮演算法,因此壓縮率比 PNG 還要大。簡單來說,如果一張 風景照片 你用 JPG 來存,需要 1MB 的話,用 PNG 就要 5MB~10MB,雖然 PNG 檔案較大但是在視覺品質上面並沒有顯著的優越。

PNG is a better choice than JPEG for storing images that contain text, line art, or other images with sharp transitions. Where an image contains both sharp transitions and photographic parts a choice must be made between the large but sharp PNG and a small JPEG with artifacts around sharp transitions. JPEG also does not support transparency.

PNG 在處理包含文字、線條和明顯輪廓的影像 則較 JPG 來的優越,當影像有明顯輪廓邊緣,JPG 的失真演算法在處理這種邊緣上就會產生瑕疵,PNG 採用無失真演算法,因此影像品質較佳。

JPEG is a poor choice for storing images that require further editing as it suffers from generation loss, whereas lossless formats do not. This makes PNG useful for saving temporary photographs that require successive editing. When the photograph is ready to be distributed, it can then be saved as a JPEG, and this limits the information loss to just one generation.

若影像儲存在未來是需要更進一步的編輯修改的話則 PNG 是比較好的選擇,若是用 JPG 不斷的存取編輯,那麼圖像的品質就越來越差了。當影像已經編輯完畢準備散發傳播的話,JPG 則可以幫你縮小體積,卻不損失太多的畫質。

因此,寫 Blog 用的電腦視窗截圖,全面改用 PNG 吧,因為面對 這種 文字、線條和輪廓明顯的圖像,PNG 的檔案其實不會比 JPG 大多少,有時候可能還比較小呢 :)

圖像及引述文字來源 @ http://en.wikipedia.org/wiki/Portable_Network_Graphics#Comparison_with
蘋果電腦創辦人賈伯斯的傳奇,大家早就耳熟能詳。然而我們除了聽他的故事、用他的產品,毫無疑問地,我們還能向他學管理。
文/陳孟珠 圖/
2008年9月 Cheers 雜誌
地獄來的老闆:蘋果電腦創辦人 史帝夫.賈伯斯(Steve Jobs)

老實說,史帝夫.賈伯斯(Steve Jobs)或許不是經理人的最佳典範,他狂妄、自戀,是個標準的完美主義加菁英論者,還認為大部份人都是笨蛋。但這些強烈的個人特質,卻也是讓蘋果電腦如此獨一無二的企業哲學。

在《連線》雜誌(WIRED)記者所出版的新書《深入賈伯斯》(Inside Steve's Brain)這本新書及近幾期《財星》雜誌(FORTUNE)多次的報導中,不難發現賈伯斯的幾項個人特質,包含像是「專注」、「完美主義」、「菁英主義」、「專制」等等。如果從經營與管理的角度重新詮釋理解,在行銷、產品設計與用人標準上,賈伯斯都有他的獨到見解。

''第1堂課:學會說「不」''

和其他科技品牌大廠如新力(SONY)或三星(SAMSUNG)比起來,蘋果電腦的產品種類並不算多,這是賈伯斯專注的結果。他堅持蘋果電腦只需專注在他們擅長的領域,把這些產品做到最好。從1990年代末期到2000年初,蘋果電腦最多只有6條產品線。即使到後來,也只增加了iPhone、Apple TV和一些iPod配件商品。反觀新力,光隨身聽就有600多種規格,新力總裁霍華德.史汀格(Howard Stringer)曾哀嘆地說,真希望新力只有3項產品啊。

傳統觀念認為,企業能提供愈多產品選擇愈好。然而每個產品勢必耗損企業資源(時間、人力、金錢),蘋果電腦選擇穩紮穩打,產品數量少卻能攻下市佔率(iPod約佔MP3隨身聽市場的7成)。

對賈伯斯來說,專注的另一層含義是說「不」。當每一家廠商都推出某一種產品,提供一樣的規格,蘋果電腦有勇氣與自信給消費者不一樣的。就像1998年推出的iMac,賈伯斯打破當時電腦的標準規格,拿掉軟碟機,並首度在電腦上使用USB介面。

雖然當時市場並不看好這項決定,但賈伯斯深信,iMac被定位在「網路電腦」,使用者會選擇用網路來傳輸、存取資料。這項改變讓iMac顯得極有未來感,而蘋果電腦也完成了創造劃時代產品的目的。

''第2堂課:顧客放最後''

很多企業喜歡聲稱他們是顧客導向,產品行銷人員謙虛地使用問卷或焦點團體訪談(focus group)來接觸使用者,直接問他們到底需要什麼。賈伯斯卻不信這套,他只專注於觀察使用者經驗,而且是他自己的使用經驗。

在科技產品上展現創意,是個人意念的表達。藝術家不可能依賴焦點團體訪談來決定創作方向,消費者也無法告訴企業如何進行科技創新。亨利.福特(Henry Ford)曾說,如果當年他問消費者想要什麼,他們會說要一匹跑得更快的馬,而不是一部奔馳的汽車。

美國最大的設計研究所,伊立諾理工大學設計學院院長派屈克.惠特尼(Patrick Whitney)也明白表示,焦點團體訪談不適用於科技創新,「使用者無法告訴你他們要什麼,而是應該去觀察並發現他們想要的。」

''第3堂課:不計成本追求完美''

不計成本地追求完美,是賈伯斯的信念,也是蘋果電腦傑出設計的祕密。

1999年1月,正當蘋果電腦要推出一系列彩色iMac前夕,賈伯斯正在舞台上練習他的產品發表演說。一位在場的美國《時代》雜誌(TIME)記者事後轉述,賈伯斯為了讓舞台上的新產品看來更耀眼,即使只是提前1秒鐘打亮燈光,他也一試再試。

回到產品設計面,賈伯斯認為設計指的是產品「功能」而不是外觀。為了貫徹他想讓科技產品簡單好用的理想,一個產品可能經歷了無數次的從頭來過,他也改良了設計流程,讓不同團隊同時參與,而不是一個接一個的線性流程。

完美產品設計的最高境界,是所謂看不見的設計。蘋果電腦在意電源開關顯示的亮度與顏色,在意電源線的設計,甚至連電腦內部線路的安排也賞心悅目。因為這些細節的視覺與觸感,讓蘋果電腦的產品獨樹一格。

為了追求完美,賈伯斯不諱言經常會碰到瓶頸。而突破瓶頸的方法,就是停下來。在製作皮克斯(Pixar)動畫電影公司的第一部作品《玩具總動員》(Toy Story)期間,團隊曾停工長達5個月,這段期間賈伯斯仍然照付薪水讓團隊「遊手好閒」。如果沒有勇氣停下來思考、重新想像,就不會有後來一炮而紅的動畫電影。

''第4堂課:只用最頂尖聰明的人''

賈伯斯有個令人走避的惡名:地獄來的老闆。他對團隊的要求很高,也無法忍受不夠聰明的員工。在他最著名的每週一馬拉松式會議裡,他會和相關團隊檢視整個事業體,包含上週公司賣了哪些產品、每一個還在發展中的商品、每一個遇到瓶頸的設計,一件一件仔細檢視討論。

你一定會納悶,為什麼還是有無數菁英願意跟在地獄來的老闆身邊做事?因為他創造了一個環境,在這裡你可以完成其他地方無法完成的事。比如,蘋果電腦推出的任何一款電腦,其獨特之處在於作業系統與硬體之間的完美結合。蘋果電腦幾乎是業界唯一足以兼顧設計軟體與硬體的企業,大部份電腦使用的作業軟體與硬體廠商是沒有交集的。但也因為這項優勢,蘋果電腦可以發展出從裡到外更符合使用者需求的產品。

要找到最佳員工很難,想自己培養出優秀員工也不容易,最好的辦法,就是像賈伯斯一樣,打造一個競爭者無法取代的環境,和參與者一起完成夢想。

''第5堂課:創新=借用與連結''

談到創新,賈伯斯總愛引用畫家畢卡索(Picasso)的名言:「好的藝術家懂複製,偉大的藝術家則擅偷取。」他從不認為借用別人的點子是件可恥的事。

賈伯斯給的兩個創新關鍵字是「借用」與「連結」。但前提是,你得先知道別人做了什麼。

賈伯斯時時關注市場動態,無論是新科技或新產品問世,在觀察與了解後做改良、借用或連結,是蘋果電腦擅長的手段。MP3隨身聽iPod和智慧型手機iPhone是改良市場產品的結果,而當年iMac上的USB介面,則是前所未有的借用與連結。蘋果電腦極少自己發明全新技術,他們把技術從實驗室拿出來,以簡單好用的方式交給一般人。

連結,則需要涉獵多元文化與豐富人生經驗。賈伯斯一直對設計、建築與科技領域保有極高興趣,他的辦公室裡總堆滿了被他拆解過的電子零件,他甚至會仔細檢視同業大廠新力公司宣傳手冊的字型、排版和紙的重量,他也經常帶著團隊參訪博物館以及各種特別的展覽,以攝取設計與建築領域的養分。

再多的技巧,終究還是別忘了激發團隊的熱情,那是蘋果電腦成功的源頭。研發出第一代蘋果電腦的團隊曾經像奴隸一般工作長達3年,他們依舊熱愛那種每週工作90小時的生活。因為賈伯斯讓他們相信,他們所設計的電腦將會改變整個產業、整個時代,他們是融合科技與文化的藝術家,他們將無可取代。

不論你喜歡這個人與否,賈伯斯特立獨行的管理與領導風格,確實帶給許多管理者不同的思考面向,重新思索過去習以為常的管理原則,是否依舊適用。
網址 : http://www.ithome.com.tw/itadm/article.php?c=78363&s=1

2年前,趨勢科技開始將資安服務所用的資料庫平臺,從MySQL延伸到NoSQL類型的資料庫,在正式環境中實際部署了包括MongoDB與Cassandra等分散式資料庫平臺。為了打造能管理10萬臺行動裝置的雲端服務MDM,趨勢科技使用MongoDB來儲存這些裝置所產生的各項管理記錄。

當初,趨勢科技會考慮使用MongoDB,主要是因為MDM雲端服務更新資料的速度非常頻繁,應用特性與關聯式資料庫的使用型態完全不同,趨勢科技研究開發部技術經理于慶源解釋,關聯式資料庫的設計,原本就是以讀取資料的應用型態為主,而MDM雲端服務的特性,除了必須考量資料讀取之外,更重要的是有大量資料寫入需求。MDM雲端服務是提供給企業管理行動裝置的服務,因此,當多間企業同時啟用時,從帳號註冊到後續追蹤行動裝置所產生的資料訊息,可能會有上萬筆資料同時寫入資料庫的需求。為了因應這種寫入需求,趨勢科技決定採用MongoDB。

于慶源表示,趨勢科技過去也是用MySQL資料庫來做產品服務,直到兩年前開始關注NoSQL,當時,MongoDB是相對成熟的分散式資料庫,而MongoDB正是因應大量資料寫入需求而產生,完全符合趨勢科技MDM雲端服務的營運要求。

未來,趨勢科技對外提供雲端服務的資料庫架構,將會以MongoDB為核心,目前除了MDM雲端服務之外,另一個中小企業資安服務平臺Worry Free Business Security雲端服務,也同樣部署在MongoDB平臺上。 
&nbsp;&nbsp;&nbsp;''我的最新文章''
<<showUpdates excludeTag:excludeLists write:'(index < 10) ? "|"+(index+1)+"|"+ tiddler.modified.formatString("YYYY-0MM-0DD")+ "|[[" + tiddler.title+"]]|"+tiddler.tags+"|\n" : ""'>>