<commit_before>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"strings"
	"sync"

	"github.com/fatih/color"
	"github.com/mitchellh/go-homedir"
)

type cliOptions struct {
	dir  string
	from string
	to   string
	file string
	help bool
}

func (this *cliOptions) valid() bool {
	return this.from != "" && this.to != ""
}

func (this *cliOptions) expandDir() {
	dir, _ := homedir.Expand(this.dir)
	this.dir = dir
}

func (this *cliOptions) display() {
	options := color.CyanString("replacing:   ")
	options += color.GreenString("%s\n", this.from)
	options += color.CyanString("with:        ")
	options += color.GreenString("%s\n", this.to)
	options += color.CyanString("in files:    ")
	options += color.GreenString("%s\n", this.file)
	options += color.CyanString("starting in: ")
	options += color.GreenString("%s\n", this.dir)
	fmt.Print(options)
}

var wg sync.WaitGroup
var banner string = ` ____            _
|  _ \ ___ _ __ | | __ _  ___ ___
| |_) / _ \ '_ \| |/ _' |/ __/ _ \
|  _ <  __/ |_) | | (_| | (_|  __/
|_| \_\___| .__/|_|\__'_|\___\___|
          |_|

`

func main() {

	var options cliOptions

	flag.StringVar(&options.dir, "dir", ".", "The directory to traverse.")
	flag.StringVar(&options.from, "from", "", "The text to replace.")
	flag.StringVar(&options.to, "to", "", "The replacement text.")
	flag.StringVar(&options.file, "file", "*", "The glob file pattern to match.")
	flag.BoolVar(&options.help, "help", false, "Show help.")
	flag.Parse()

	if (!options.valid()) || options.help {
		color.Cyan(banner)
		flag.Usage()

	} else {
		options.expandDir()
		options.display()

		err := filepath.Walk(options.dir, func(fullPath string, info os.FileInfo, err error) error {

			if err != nil {
				return err
			}

			if info.IsDir() {
				return nil
			}

			wg.Add(1)
			go handlePath(fullPath, &options)

			return nil
		})

		if err != nil {
			fmt.Fprintln(os.Stderr, color.RedString(err.Error()))
			return
		}

		wg.Wait()
	}
}

func processPath(fullPath string, options *cliOptions) {
	defer wg.Done()

	contents, err := ioutil.ReadFile(fullPath)
	if err != nil {
		fmt.Fprintln(os.Stderr, color.RedString(err.Error()))
		return
	}

	newContents := strings.Replace(string(contents), options.from, options.to, -1)
	if newContents != string(contents) {

		err = ioutil.WriteFile(fullPath, []byte(newContents), 0)
		if err != nil {
			fmt.Fprintln(os.Stderr, color.RedString(err.Error()))
			return
		}

		color.Magenta(fullPath)
	}
}

func handlePath(fullPath string, options *cliOptions) {
	defer wg.Done()

	matched, err := filepath.Match(options.file, path.Base(fullPath))
	if err != nil {
		fmt.Fprintln(os.Stderr, color.RedString(err.Error()))
		return
	}

	if matched {
		wg.Add(1)
		go processPath(fullPath, options)
	}
}
<commit_msg>Refactored a little.<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"strings"
	"sync"
	"sync/atomic"

	"github.com/fatih/color"
	"github.com/mitchellh/go-homedir"
)

type cliOptions struct {
	dir  string
	from string
	to   string
	file string
	help bool
}

func (this *cliOptions) valid() bool {
	return this.from != "" && this.to != ""
}

func (this *cliOptions) display() {
	options := color.CyanString("replacing:   ")
	options += color.GreenString("%s\n", this.from)
	options += color.CyanString("with:        ")
	options += color.GreenString("%s\n", this.to)
	options += color.CyanString("in files:    ")
	options += color.GreenString("%s\n", this.file)
	options += color.CyanString("starting in: ")
	options += color.GreenString("%s\n", this.dir)
	fmt.Print(options)
}

func (this *cliOptions) parse() {
	flag.StringVar(&this.dir, "dir", ".", "The directory to traverse.")
	flag.StringVar(&this.from, "from", "", "The text to replace.")
	flag.StringVar(&this.to, "to", "", "The replacement text.")
	flag.StringVar(&this.file, "file", "*", "The glob file pattern to match.")
	flag.BoolVar(&this.help, "help", false, "Show help.")
	flag.Parse()
	dir, _ := homedir.Expand(this.dir)
	this.dir = dir
}

func (this *cliOptions) usage() {
	var banner string = ` ____            _
|  _ \ ___ _ __ | | __ _  ___ ___
| |_) / _ \ '_ \| |/ _' |/ __/ _ \
|  _ <  __/ |_) | | (_| | (_|  __/
|_| \_\___| .__/|_|\__'_|\___\___|
          |_|

`
	color.Cyan(banner)
	flag.Usage()
}

type fileHandler struct {
	options *cliOptions
	wg      sync.WaitGroup
	total   int64
}

func (this *fileHandler) count() {
	atomic.AddInt64(&this.total, 1)
}

func (this *fileHandler) init(options *cliOptions) {
	this.options = options
}

func (this *fileHandler) handlePath(fullPath string) {
	defer this.wg.Done()

	matched, err := filepath.Match(this.options.file, path.Base(fullPath))
	if err != nil {
		fmt.Fprintln(os.Stderr, color.RedString(err.Error()))
		return
	}

	if matched {
		this.wg.Add(1)
		go this.processPath(fullPath)
	}
}

func (this *fileHandler) processPath(fullPath string) {
	defer this.wg.Done()

	contents, err := ioutil.ReadFile(fullPath)
	if err != nil {
		fmt.Fprintln(os.Stderr, color.RedString(err.Error()))
		return
	}

	newContents := strings.Replace(string(contents), this.options.from, this.options.to, -1)
	if newContents != string(contents) {

		err = ioutil.WriteFile(fullPath, []byte(newContents), 0)
		if err != nil {
			fmt.Fprintln(os.Stderr, color.RedString(err.Error()))
			return
		}

		this.count()
		color.Magenta(fullPath)
	}
}

func (this *fileHandler) walk() error {
	return filepath.Walk(this.options.dir, func(fullPath string, info os.FileInfo, err error) error {

		if err != nil {
			return err
		}

		if info.IsDir() {
			return nil
		}

		this.wg.Add(1)
		go this.handlePath(fullPath)

		return nil
	})
}

func main() {

	var options cliOptions
	options.parse()

	var files fileHandler
	files.init(&options)

	if (!options.valid()) || options.help {
		options.usage()

	} else {
		options.display()
		err := files.walk()

		if err != nil {
			fmt.Fprintln(os.Stderr, color.RedString(err.Error()))
			return
		}

		files.wg.Wait()
		fmt.Printf("%d file(s) updated\n", files.total)
	}
}
<|endoftext|>


<commit_before>// govcl project main.go
// go.exe build -i -ldflags="-H windowsgui"
package main

import (
	"fmt"

	"github.com/ying32/govcl/vcl"
	"github.com/ying32/govcl/vcl/exts/tools"
	"github.com/ying32/govcl/vcl/rtl"
	"github.com/ying32/govcl/vcl/rtl/version"
	"github.com/ying32/govcl/vcl/types"
	"github.com/ying32/govcl/vcl/win"
)

var (
	mainForm *vcl.TForm
	trayicon *vcl.TTrayIcon
)

func main() {

	// mac下记得发布时去掉
	tools.RunWithMacOSApp()
	// 异常捕获
	defer func() {
		err := recover()
		if err != nil {
			fmt.Println("Exception: ", err)
			vcl.ShowMessage(err.(error).Error())
		}
	}()

	fmt.Println("InheritsFrom：", vcl.Application.InheritsFrom(vcl.TObjectClass()))
	fmt.Println("InheritsFrom：", vcl.Application.InheritsFrom(vcl.TComponentClass()))
	fmt.Println("InheritsFrom：", vcl.Application.InheritsFrom(vcl.TControlClass()))

	fmt.Println("main")
	vcl.Application.SetIconResId(3)
	vcl.Application.Initialize()

	vcl.Application.SetOnException(func(sender vcl.IObject, e *vcl.Exception) {
		fmt.Println("exception.")
	})

	vcl.Application.SetTitle("Hello World! 系统信息：" + version.OSVersion.ToString())
	vcl.Application.SetMainFormOnTaskBar(true)
	// 窗口自动根据系统绽放，默认为true
	//vcl.Application.SetFormScaled(false)

	mainForm = vcl.Application.CreateForm()
	mainForm.SetWidth(800)
	mainForm.SetHeight(600)
	mainForm.SetOnClose(func(Sender vcl.IObject, Action *types.TCloseAction) {
		fmt.Println("close")
	})

	// 窗口大小约束
	mainForm.SetOnConstrainedResize(func(sender vcl.IObject, minWidth, minHeight, maxWidth, maxHeight *int32) {
		*minWidth = 800
		*minHeight = 600
		*maxWidth = 800
		*maxHeight = 600
	})

	mainForm.SetOnDestroy(func(sender vcl.IObject) {
		fmt.Println("Form Destroy.")
	})

	fmt.Println("MainForm ClientRect: ", mainForm.ClientRect())
	filename := vcl.Application.ExeName()
	fmt.Println("application.ExeName: ", filename)
	fmt.Println("path: ", rtl.ExtractFilePath(filename))
	fmt.Println("fileExists: ", rtl.FileExists(filename))

	mainForm.SetOnCloseQuery(func(Sender vcl.IObject, CanClose *bool) {
		*CanClose = vcl.MessageDlg("是否退出?", types.MtInformation, types.MbYes, types.MbNo) == types.MrYes
		fmt.Println("OnCloseQuery")
	})

	mainForm.SetCaption(vcl.Application.Title())
	mainForm.EnabledMaximize(false)
	mainForm.SetDoubleBuffered(true)
	//mainForm.SetPosition(types.PoScreenCenter)
	//mainForm.ScreenCenter()
	mainForm.WorkAreaCenter()
	mainForm.SetKeyPreview(true)
	mainForm.SetOnKeyDown(func(Sender vcl.IObject, Key *types.Char, Shift types.TShiftState) {
		fmt.Println(rtl.InSets(uint32(Shift), types.SsCtrl))
		fmt.Println("key:", *Key)
	})

	mainForm.SetOnMouseDown(func(sender vcl.IObject, button types.TMouseButton, shift types.TShiftState, x, y int32) {
		fmt.Println("Button:", button == types.MbLeft, ", X:", x, ", y:", y)
		fmt.Println("OnMouseDown")
	})

	chk := vcl.NewCheckBox(mainForm)
	chk.SetParent(mainForm)
	chk.SetChecked(true)
	chk.SetCaption("测试")
	chk.SetLeft(1)
	chk.SetTop(60)
	chk.SetOnClick(func(vcl.IObject) {
		fmt.Println("chk.Checked=", chk.Checked())
	})

	// action
	action := vcl.NewAction(mainForm)
	action.SetCaption("action1")
	action.SetOnUpdate(func(sender vcl.IObject) {
		vcl.ActionFromObj(sender).SetEnabled(chk.Checked())
	})
	action.SetOnExecute(func(vcl.IObject) {
		fmt.Println("action execute")
	})
	btn := vcl.NewButton(mainForm)
	btn.SetParent(mainForm)
	btn.SetBounds(250, 30, 90, 25)
	btn.SetCaption("action")
	btn.SetAction(action)

	trayicon = vcl.NewTrayIcon(mainForm)
	if rtl.LcLLoaded() {
		trayicon.SetIcon(vcl.Application.Icon()) //不设置会自动使用Application.Icon
	}

	trayicon.SetHint(mainForm.Caption())
	trayicon.SetVisible(true)
	trayicon.SetOnClick(func(vcl.IObject) {
		trayicon.SetBalloonTitle("test")
		trayicon.SetBalloonTimeout(10000)
		trayicon.SetBalloonHint("我是提示正文啦")
		trayicon.ShowBalloonHint()
		fmt.Println("TrayIcon Click.")
	})

	// img
	img := vcl.NewImage(mainForm)
	img.SetBounds(132, 30, 156, 97)
	img.SetParent(mainForm)
	img.Picture().LoadFromFile("./imgs/1.jpg")
	//img.SetStretch(true)
	img.SetProportional(true)

	// linklabel
	linklbl := vcl.NewLinkLabel(mainForm)
	linklbl.SetAlign(types.AlBottom)
	linklbl.SetCaption("govcl测试链接")
	linklbl.SetParent(mainForm)
	linklbl.SetOnLinkClick(func(sender vcl.IObject, link string, linktype types.TSysLinkType) {
		fmt.Println("link label: ", link, ", type: ", linktype)
		rtl.SysOpen(link)
	})

	// menu
	mainMenu := vcl.NewMainMenu(mainForm)
	item := vcl.NewMenuItem(mainForm)
	item.SetCaption("File(&F)")
	mainMenu.Items().Add(item)

	item2 := vcl.NewMenuItem(mainForm)
	item2.SetCaption("MemoryStreamTest")
	item2.SetOnClick(func(vcl.IObject) {
		mem := vcl.NewMemoryStream()
		defer mem.Free()
		mem.Write([]byte("测试"))
		mem.SaveToFile("test.txt")

		mem.SetPosition(0)
		n, bs := mem.Read(int32(mem.Size()))
		fmt.Println("n:", n, ", bs:", bs, ", str:", string(bs))
	})
	item.Add(item2)

	item2 = vcl.NewMenuItem(mainForm)
	item2.SetCaption("Exit(&E)")
	item2.SetShortCutFromString("Ctrl+Q")
	item2.SetOnClick(func(vcl.IObject) {
		mainForm.Close()
	})
	item.Add(item2)

	//	mainForm.EnabledMinimize(false)
	//	mainForm.EnabledSystemMenu(false)

	button := vcl.NewButton(mainForm)

	button.SetCaption("消息")
	button.SetParent(mainForm)
	button.SetOnClick(func(vcl.IObject) {
		fmt.Println("button click")
		vcl.ShowMessage("这是一个消息")
		vcl.Application.MessageBox("Hello!", "Message", win.MB_YESNO+win.MB_ICONINFORMATION)
	})
	button.SetLeft(50)
	button.SetTop(50)
	button.SetAlign(types.AlRight)

	edit := vcl.NewEdit(mainForm)
	edit.SetParent(mainForm)
	edit.SetLeft(1)
	edit.SetTop(30)
	edit.SetTextHint("测试")
	edit.SetOnChange(func(vcl.IObject) {
		fmt.Println("edit OnChange")
	})

	button2 := vcl.NewButton(mainForm)
	button2.SetParent(mainForm)
	button2.SetCaption("a")
	button2.SetWidth(100)
	button2.SetHeight(28)
	button2.SetOnClick(func(vcl.IObject) {
		fmt.Println("button2 click")

		edit.SetText("Hello!")
		fmt.Println("ScreenWidth:", vcl.Screen.Width(), ", ScreenHeight:", vcl.Screen.Height())
	})
	button2.SetAlign(types.AlTop)

	combo := vcl.NewComboBox(mainForm)
	combo.SetAlign(types.AlBottom)
	combo.SetParent(mainForm)
	combo.SetText("ffff")
	combo.Items().Add("1")
	combo.Items().Add("2")
	combo.SetItemIndex(0)
	combo.SetOnChange(func(vcl.IObject) {
		if combo.ItemIndex() != -1 {
			fmt.Println("combo Change: ", combo.Items().Strings(combo.ItemIndex()))
		}

	})

	page := vcl.NewPageControl(mainForm)
	page.SetParent(mainForm)
	page.SetAlign(types.AlBottom)
	sheet := vcl.NewTabSheet(mainForm)
	sheet.SetPageControl(page)
	sheet.SetCaption("第一页")

	// 需要先将TabSheet设置了父窗口，TListView才可用，不然就会报错
	lv1 := vcl.NewListView(mainForm)
	lv1.SetAlign(types.AlClient)
	lv1.SetParent(sheet)

	lv1.SetViewStyle(types.VsReport)
	lv1.SetRowSelect(true)
	lv1.SetReadOnly(true)
	lv1.SetGridLines(true)
	col := lv1.Columns().Add()
	col.SetCaption("序号")
	col.SetWidth(100)
	// 强制柱头宽，即使被调整也会被还原
	col.SetMaxWidth(100)
	col.SetMinWidth(100)
	col = lv1.Columns().Add()
	col.SetCaption("名称")
	col.SetWidth(200)
	col = lv1.Columns().Add()
	col.SetCaption("内容")
	col.SetWidth(200)
	lv1.SetOnClick(func(vcl.IObject) {
		if lv1.ItemIndex() != -1 {
			item := lv1.Selected() // lv1.Items().Item(lv1.ItemIndex())
			fmt.Println(item.Caption(),
				item.SubItems().Strings(0),
				item.SubItems().Strings(1))
		}
	})

	lv1.Items().BeginUpdate()
	for i := 1; i <= 50; i++ {
		lstitem := lv1.Items().Add()
		lstitem.SetCaption(fmt.Sprintf("%d", i))
		lstitem.SubItems().Add(fmt.Sprintf("第%d", i))
		lstitem.SubItems().Add(fmt.Sprintf("内容%d", i))
	}
	lv1.Items().EndUpdate()

	sheet = vcl.NewTabSheet(mainForm)
	sheet.SetCaption("第二页")
	sheet.SetPageControl(page)

	// -----------TreeView 不同Node弹出不同菜单，两个右键例程不同使用

	tvpm1 := vcl.NewPopupMenu(mainForm)
	mItem := vcl.NewMenuItem(mainForm)
	mItem.SetCaption("第一种")
	tvpm1.Items().Add(mItem)

	tvpm2 := vcl.NewPopupMenu(mainForm)
	mItem = vcl.NewMenuItem(mainForm)
	mItem.SetCaption("第二种")
	tvpm2.Items().Add(mItem)

	tv1 := vcl.NewTreeView(mainForm)
	tv1.SetAutoExpand(true)
	tv1.SetParent(sheet)
	tv1.SetAlign(types.AlClient)
	//	tv1.SetRightClickSelect(true)
	tv1.SetOnClick(func(vcl.IObject) {
		if tv1.SelectionCount() > 0 {
			node := tv1.Selected()
			fmt.Println("text:", node.Text(), ", index:", node.Index())
		}
	})

	tv1.SetOnMouseDown(func(sender vcl.IObject, button types.TMouseButton, shift types.TShiftState, x, y int32) {
		if button == types.MbRight {
			node := tv1.GetNodeAt(x, y)
			if node != nil && node.IsValid() {
				// 自由决择是否选中
				node.SetSelected(true)
				// 根据Level来判断，这里只是做演示
				p := vcl.Mouse.CursorPos()
				switch node.Level() {
				case 0:
					tvpm1.Popup(p.X, p.Y)
				case 1:
					tvpm2.Popup(p.X, p.Y)
				}
				fmt.Println("node.Level():", node.Level(), ", text:", node.Text())
			}
		}
	})

	tv1.Items().BeginUpdate()
	node := tv1.Items().AddChild(nil, "首个")
	for i := 1; i <= 50; i++ {
		tv1.Items().AddChild(node, fmt.Sprintf("Node%d", i))
	}
	node = tv1.Items().AddChild(nil, "第二个")
	for i := 1; i <= 50; i++ {
		tv1.Items().AddChild(node, fmt.Sprintf("Node%d", i))
	}
	tv1.Items().EndUpdate()

	fmt.Println("Compoment Count:", mainForm.ComponentCount())
	//	mainForm.ScreenCenter()

	lbl := vcl.NewLabel(mainForm)
	lbl.SetCaption("标签")
	lbl.SetAlign(types.AlBottom)
	fmt.Println("InheritsFromControl:", mainForm.InheritsFrom(vcl.TControlClass()))
	fmt.Println("InheritsFromWinControl:", mainForm.InheritsFrom(vcl.TWinControlClass()))
	fmt.Println("InheritsFromComponent:", mainForm.InheritsFrom(vcl.TComponentClass()))
	fmt.Println("InheritsFromWinControl:", lbl.InheritsFrom(vcl.TWinControlClass()))

	vcl.Application.Run()
}
<commit_msg>update main.go<commit_after>// govcl project main.go
// go.exe build -i -ldflags="-H windowsgui"
package main

import (
	"fmt"

	"github.com/ying32/govcl/vcl"
	"github.com/ying32/govcl/vcl/exts/tools"
	"github.com/ying32/govcl/vcl/rtl"
	"github.com/ying32/govcl/vcl/rtl/version"
	"github.com/ying32/govcl/vcl/types"
	"github.com/ying32/govcl/vcl/win"
)

var (
	mainForm *vcl.TForm
	trayicon *vcl.TTrayIcon
)

func main() {

	// mac下记得发布时去掉
	tools.RunWithMacOSApp()
	// 异常捕获
	defer func() {
		err := recover()
		if err != nil {
			fmt.Println("Exception: ", err)
			vcl.ShowMessage(err.(error).Error())
		}
	}()

	fmt.Println("InheritsFrom：", vcl.Application.InheritsFrom(vcl.TObjectClass()))
	fmt.Println("InheritsFrom：", vcl.Application.InheritsFrom(vcl.TComponentClass()))
	fmt.Println("InheritsFrom：", vcl.Application.InheritsFrom(vcl.TControlClass()))

	fmt.Println("main")
	vcl.Application.SetIconResId(3)
	vcl.Application.Initialize()

	vcl.Application.SetOnException(func(sender vcl.IObject, e *vcl.Exception) {
		fmt.Println("exception.")
	})

	vcl.Application.SetTitle("Hello World! 系统信息：" + version.OSVersion.ToString())
	vcl.Application.SetMainFormOnTaskBar(true)
	// 窗口自动根据系统绽放，默认为false
	//vcl.Application.SetFormScaled(true)

	mainForm = vcl.Application.CreateForm()
	mainForm.SetWidth(800)
	mainForm.SetHeight(600)
	mainForm.SetOnClose(func(Sender vcl.IObject, Action *types.TCloseAction) {
		fmt.Println("close")
	})

	// 窗口大小约束
	mainForm.SetOnConstrainedResize(func(sender vcl.IObject, minWidth, minHeight, maxWidth, maxHeight *int32) {
		*minWidth = 800
		*minHeight = 600
		*maxWidth = 800
		*maxHeight = 600
	})

	mainForm.SetOnDestroy(func(sender vcl.IObject) {
		fmt.Println("Form Destroy.")
	})

	fmt.Println("MainForm ClientRect: ", mainForm.ClientRect())
	filename := vcl.Application.ExeName()
	fmt.Println("application.ExeName: ", filename)
	fmt.Println("path: ", rtl.ExtractFilePath(filename))
	fmt.Println("fileExists: ", rtl.FileExists(filename))

	mainForm.SetOnCloseQuery(func(Sender vcl.IObject, CanClose *bool) {
		*CanClose = vcl.MessageDlg("是否退出?", types.MtInformation, types.MbYes, types.MbNo) == types.MrYes
		fmt.Println("OnCloseQuery")
	})

	mainForm.SetCaption(vcl.Application.Title())
	mainForm.EnabledMaximize(false)
	mainForm.SetDoubleBuffered(true)
	//mainForm.SetPosition(types.PoScreenCenter)
	//mainForm.ScreenCenter()
	mainForm.WorkAreaCenter()
	mainForm.SetKeyPreview(true)
	mainForm.SetOnKeyDown(func(Sender vcl.IObject, Key *types.Char, Shift types.TShiftState) {
		fmt.Println(rtl.InSets(uint32(Shift), types.SsCtrl))
		fmt.Println("key:", *Key)
	})

	mainForm.SetOnMouseDown(func(sender vcl.IObject, button types.TMouseButton, shift types.TShiftState, x, y int32) {
		fmt.Println("Button:", button == types.MbLeft, ", X:", x, ", y:", y)
		fmt.Println("OnMouseDown")
	})

	chk := vcl.NewCheckBox(mainForm)
	chk.SetParent(mainForm)
	chk.SetChecked(true)
	chk.SetCaption("测试")
	chk.SetLeft(1)
	chk.SetTop(60)
	chk.SetOnClick(func(vcl.IObject) {
		fmt.Println("chk.Checked=", chk.Checked())
	})

	// action
	action := vcl.NewAction(mainForm)
	action.SetCaption("action1")
	action.SetOnUpdate(func(sender vcl.IObject) {
		vcl.ActionFromObj(sender).SetEnabled(chk.Checked())
	})
	action.SetOnExecute(func(vcl.IObject) {
		fmt.Println("action execute")
	})
	btn := vcl.NewButton(mainForm)
	btn.SetParent(mainForm)
	btn.SetBounds(250, 30, 90, 25)
	btn.SetCaption("action")
	btn.SetAction(action)

	trayicon = vcl.NewTrayIcon(mainForm)
	if rtl.LcLLoaded() {
		trayicon.SetIcon(vcl.Application.Icon()) //不设置会自动使用Application.Icon
	}

	trayicon.SetHint(mainForm.Caption())
	trayicon.SetVisible(true)
	trayicon.SetOnClick(func(vcl.IObject) {
		trayicon.SetBalloonTitle("test")
		trayicon.SetBalloonTimeout(10000)
		trayicon.SetBalloonHint("我是提示正文啦")
		trayicon.ShowBalloonHint()
		fmt.Println("TrayIcon Click.")
	})

	// img
	img := vcl.NewImage(mainForm)
	img.SetBounds(132, 30, 156, 97)
	img.SetParent(mainForm)
	img.Picture().LoadFromFile("./imgs/1.jpg")
	//img.SetStretch(true)
	img.SetProportional(true)

	// linklabel
	linklbl := vcl.NewLinkLabel(mainForm)
	linklbl.SetAlign(types.AlBottom)
	linklbl.SetCaption("govcl测试链接")
	linklbl.SetParent(mainForm)
	linklbl.SetOnLinkClick(func(sender vcl.IObject, link string, linktype types.TSysLinkType) {
		fmt.Println("link label: ", link, ", type: ", linktype)
		rtl.SysOpen(link)
	})

	// menu
	mainMenu := vcl.NewMainMenu(mainForm)
	item := vcl.NewMenuItem(mainForm)
	item.SetCaption("File(&F)")
	mainMenu.Items().Add(item)

	item2 := vcl.NewMenuItem(mainForm)
	item2.SetCaption("MemoryStreamTest")
	item2.SetOnClick(func(vcl.IObject) {
		mem := vcl.NewMemoryStream()
		defer mem.Free()
		mem.Write([]byte("测试"))
		mem.SaveToFile("test.txt")

		mem.SetPosition(0)
		n, bs := mem.Read(int32(mem.Size()))
		fmt.Println("n:", n, ", bs:", bs, ", str:", string(bs))
	})
	item.Add(item2)

	item2 = vcl.NewMenuItem(mainForm)
	item2.SetCaption("Exit(&E)")
	item2.SetShortCutFromString("Ctrl+Q")
	item2.SetOnClick(func(vcl.IObject) {
		mainForm.Close()
	})
	item.Add(item2)

	//	mainForm.EnabledMinimize(false)
	//	mainForm.EnabledSystemMenu(false)

	button := vcl.NewButton(mainForm)

	button.SetCaption("消息")
	button.SetParent(mainForm)
	button.SetOnClick(func(vcl.IObject) {
		fmt.Println("button click")
		vcl.ShowMessage("这是一个消息")
		vcl.Application.MessageBox("Hello!", "Message", win.MB_YESNO+win.MB_ICONINFORMATION)
	})
	button.SetLeft(50)
	button.SetTop(50)
	button.SetAlign(types.AlRight)

	edit := vcl.NewEdit(mainForm)
	edit.SetParent(mainForm)
	edit.SetLeft(1)
	edit.SetTop(30)
	edit.SetTextHint("测试")
	edit.SetOnChange(func(vcl.IObject) {
		fmt.Println("edit OnChange")
	})

	button2 := vcl.NewButton(mainForm)
	button2.SetParent(mainForm)
	button2.SetCaption("a")
	button2.SetWidth(100)
	button2.SetHeight(28)
	button2.SetOnClick(func(vcl.IObject) {
		fmt.Println("button2 click")

		edit.SetText("Hello!")
		fmt.Println("ScreenWidth:", vcl.Screen.Width(), ", ScreenHeight:", vcl.Screen.Height())
	})
	button2.SetAlign(types.AlTop)

	combo := vcl.NewComboBox(mainForm)
	combo.SetAlign(types.AlBottom)
	combo.SetParent(mainForm)
	combo.SetText("ffff")
	combo.Items().Add("1")
	combo.Items().Add("2")
	combo.SetItemIndex(0)
	combo.SetOnChange(func(vcl.IObject) {
		if combo.ItemIndex() != -1 {
			fmt.Println("combo Change: ", combo.Items().Strings(combo.ItemIndex()))
		}

	})

	page := vcl.NewPageControl(mainForm)
	page.SetParent(mainForm)
	page.SetAlign(types.AlBottom)
	sheet := vcl.NewTabSheet(mainForm)
	sheet.SetPageControl(page)
	sheet.SetCaption("第一页")

	// 需要先将TabSheet设置了父窗口，TListView才可用，不然就会报错
	lv1 := vcl.NewListView(mainForm)
	lv1.SetAlign(types.AlClient)
	lv1.SetParent(sheet)

	lv1.SetViewStyle(types.VsReport)
	lv1.SetRowSelect(true)
	lv1.SetReadOnly(true)
	lv1.SetGridLines(true)
	col := lv1.Columns().Add()
	col.SetCaption("序号")
	col.SetWidth(100)
	// 强制柱头宽，即使被调整也会被还原
	col.SetMaxWidth(100)
	col.SetMinWidth(100)
	col = lv1.Columns().Add()
	col.SetCaption("名称")
	col.SetWidth(200)
	col = lv1.Columns().Add()
	col.SetCaption("内容")
	col.SetWidth(200)
	lv1.SetOnClick(func(vcl.IObject) {
		if lv1.ItemIndex() != -1 {
			item := lv1.Selected() // lv1.Items().Item(lv1.ItemIndex())
			fmt.Println(item.Caption(),
				item.SubItems().Strings(0),
				item.SubItems().Strings(1))
		}
	})

	lv1.Items().BeginUpdate()
	for i := 1; i <= 50; i++ {
		lstitem := lv1.Items().Add()
		lstitem.SetCaption(fmt.Sprintf("%d", i))
		lstitem.SubItems().Add(fmt.Sprintf("第%d", i))
		lstitem.SubItems().Add(fmt.Sprintf("内容%d", i))
	}
	lv1.Items().EndUpdate()

	sheet = vcl.NewTabSheet(mainForm)
	sheet.SetCaption("第二页")
	sheet.SetPageControl(page)

	// -----------TreeView 不同Node弹出不同菜单，两个右键例程不同使用

	tvpm1 := vcl.NewPopupMenu(mainForm)
	mItem := vcl.NewMenuItem(mainForm)
	mItem.SetCaption("第一种")
	tvpm1.Items().Add(mItem)

	tvpm2 := vcl.NewPopupMenu(mainForm)
	mItem = vcl.NewMenuItem(mainForm)
	mItem.SetCaption("第二种")
	tvpm2.Items().Add(mItem)

	tv1 := vcl.NewTreeView(mainForm)
	tv1.SetAutoExpand(true)
	tv1.SetParent(sheet)
	tv1.SetAlign(types.AlClient)
	//	tv1.SetRightClickSelect(true)
	tv1.SetOnClick(func(vcl.IObject) {
		if tv1.SelectionCount() > 0 {
			node := tv1.Selected()
			fmt.Println("text:", node.Text(), ", index:", node.Index())
		}
	})

	tv1.SetOnMouseDown(func(sender vcl.IObject, button types.TMouseButton, shift types.TShiftState, x, y int32) {
		if button == types.MbRight {
			node := tv1.GetNodeAt(x, y)
			if node != nil && node.IsValid() {
				// 自由决择是否选中
				node.SetSelected(true)
				// 根据Level来判断，这里只是做演示
				p := vcl.Mouse.CursorPos()
				switch node.Level() {
				case 0:
					tvpm1.Popup(p.X, p.Y)
				case 1:
					tvpm2.Popup(p.X, p.Y)
				}
				fmt.Println("node.Level():", node.Level(), ", text:", node.Text())
			}
		}
	})

	tv1.Items().BeginUpdate()
	node := tv1.Items().AddChild(nil, "首个")
	for i := 1; i <= 50; i++ {
		tv1.Items().AddChild(node, fmt.Sprintf("Node%d", i))
	}
	node = tv1.Items().AddChild(nil, "第二个")
	for i := 1; i <= 50; i++ {
		tv1.Items().AddChild(node, fmt.Sprintf("Node%d", i))
	}
	tv1.Items().EndUpdate()

	fmt.Println("Compoment Count:", mainForm.ComponentCount())
	//	mainForm.ScreenCenter()

	lbl := vcl.NewLabel(mainForm)
	lbl.SetCaption("标签")
	lbl.SetAlign(types.AlBottom)
	fmt.Println("InheritsFromControl:", mainForm.InheritsFrom(vcl.TControlClass()))
	fmt.Println("InheritsFromWinControl:", mainForm.InheritsFrom(vcl.TWinControlClass()))
	fmt.Println("InheritsFromComponent:", mainForm.InheritsFrom(vcl.TComponentClass()))
	fmt.Println("InheritsFromWinControl:", lbl.InheritsFrom(vcl.TWinControlClass()))

	vcl.Application.Run()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"time"

	"github.com/felixangell/phi-editor/cfg"
	"github.com/felixangell/phi-editor/gui"
	"github.com/felixangell/strife"
)

const (
	PRINT_FPS bool = true
)

type PhiEditor struct {
	gui.BaseComponent
	running     bool
	defaultFont *strife.Font
}

func (n *PhiEditor) handleEvent(evt strife.StrifeEvent) {
	for _, comp := range n.GetComponents() {
		gui.HandleEvent(comp, evt)
	}
}

func (n *PhiEditor) init(cfg *cfg.TomlConfig) {
	mainView := gui.NewView(1280, 720, cfg)

	args := os.Args
	if len(args) > 1 {
		// TODO check these are files
		// that actually exist here?
		for _, arg := range args[1:] {
			mainView.AddBuffer().OpenFile(arg)
		}
	} else {
		// we have no args, open up a scratch file
		tempFile, err := ioutil.TempFile("/var/tmp/", "phi-editor-")
		if err != nil {
			log.Println("Failed to create temp file", err.Error())
			os.Exit(1)
		}

		mainView.AddBuffer().OpenFile(tempFile.Name())
	}

	{
		palette := gui.NewCommandPalette(cfg)
		palette.Resize(1280/3, 72)
		// mainView.AddComponent(palette)
	}

	n.AddComponent(mainView)

	// TODO put me somewhere else:
	// also improve the font loading code
	var fontFolder string

	switch runtime.GOOS {
	case "windows":
		fontFolder = filepath.Join(os.Getenv("WINDIR"), "fonts")
	case "darwin":
		fontFolder = "/Library/Fonts/"
	case "linux":
		fontFolder = "/usr/share/fonts/"
	}

	fontPath := filepath.Join(fontFolder, cfg.Editor.Font_Face) + ".ttf"

	font, err := strife.LoadFont(fontPath, cfg.Editor.Font_Size)
	if err != nil {
		panic(err)
	}
	n.defaultFont = font
}

func (n *PhiEditor) dispose() {
	for _, comp := range n.GetComponents() {
		gui.Dispose(comp)
	}
}

func (n *PhiEditor) update() bool {
	needsRender := false
	for _, comp := range n.GetComponents() {
		dirty := comp.OnUpdate()
		if dirty {
			needsRender = true
		}
	}
	return needsRender
}

func (n *PhiEditor) render(ctx *strife.Renderer) {
	ctx.SetFont(n.defaultFont)

	for _, child := range n.GetComponents() {
		gui.Render(child, ctx)
	}
}

func main() {
	config := cfg.Setup()

	ww, wh := 1280, 720
	window := strife.SetupRenderWindow(ww, wh, strife.DefaultConfig())
	window.SetTitle("Hello world!")
	window.SetResizable(true)

	editor := &PhiEditor{running: true}
	window.HandleEvents(func(evt strife.StrifeEvent) {
		switch evt.(type) {
		case *strife.CloseEvent:
			window.Close()
		default:
			editor.handleEvent(evt)
		}
	})

	window.Create()

	{
		size := "16"
		switch runtime.GOOS {
		case "windows":
			size = "256"
		case "darwin":
			size = "512"
		case "linux":
			size = "96"
		default:
			log.Println("unrecognized runtime ", runtime.GOOS)
		}

		icon, err := strife.LoadImage("./res/icons/icon" + size + ".png")
		if err != nil {
			log.Println("Failed to load icon ", err.Error())
		} else {
			window.SetIconImage(icon)
			defer icon.Destroy()
		}
	}

	editor.init(&config)

	timer := strife.CurrentTimeMillis()
	frames, updates := 0, 0
	fps, ups := frames, updates

	ctx := window.GetRenderContext()

	ctx.Clear()
	editor.render(ctx)
	ctx.Display()

	for {
		window.PollEvents()
		if window.CloseRequested() {
			break
		}

		if editor.update() || config.Render.Always_Render {
			ctx.Clear()
			editor.render(ctx)

			// this is only printed on each
			// render...
			ctx.SetColor(strife.White)
			ctx.String(fmt.Sprintf("fps: %d, ups %d", fps, ups), ww-256, wh-128)

			ctx.Display()
			frames += 1
		}
		updates += 1

		if strife.CurrentTimeMillis()-timer > 1000 {
			timer = strife.CurrentTimeMillis()
			fps, ups = frames, updates
			frames, updates = 0, 0
		}

		if config.Render.Throttle_Cpu_Usage {
			// todo put in the config how long
			// we sleep for!
			time.Sleep(16)
		}
	}

	editor.dispose()
}
<commit_msg>pass empty string into ioutil.TempDir<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"time"

	"github.com/felixangell/phi-editor/cfg"
	"github.com/felixangell/phi-editor/gui"
	"github.com/felixangell/strife"
)

const (
	PRINT_FPS bool = true
)

type PhiEditor struct {
	gui.BaseComponent
	running     bool
	defaultFont *strife.Font
}

func (n *PhiEditor) handleEvent(evt strife.StrifeEvent) {
	for _, comp := range n.GetComponents() {
		gui.HandleEvent(comp, evt)
	}
}

func (n *PhiEditor) init(cfg *cfg.TomlConfig) {
	mainView := gui.NewView(1280, 720, cfg)

	args := os.Args
	if len(args) > 1 {
		// TODO check these are files
		// that actually exist here?
		for _, arg := range args[1:] {
			mainView.AddBuffer().OpenFile(arg)
		}
	} else {
		// we have no args, open up a scratch file
		tempFile, err := ioutil.TempFile("", "phi-editor-")
		if err != nil {
			log.Println("Failed to create temp file", err.Error())
			os.Exit(1)
		}

		mainView.AddBuffer().OpenFile(tempFile.Name())
	}

	{
		palette := gui.NewCommandPalette(cfg)
		palette.Resize(1280/3, 72)
		// mainView.AddComponent(palette)
	}

	n.AddComponent(mainView)

	// TODO put me somewhere else:
	// also improve the font loading code
	var fontFolder string

	switch runtime.GOOS {
	case "windows":
		fontFolder = filepath.Join(os.Getenv("WINDIR"), "fonts")
	case "darwin":
		fontFolder = "/Library/Fonts/"
	case "linux":
		fontFolder = "/usr/share/fonts/"
	}

	fontPath := filepath.Join(fontFolder, cfg.Editor.Font_Face) + ".ttf"

	font, err := strife.LoadFont(fontPath, cfg.Editor.Font_Size)
	if err != nil {
		panic(err)
	}
	n.defaultFont = font
}

func (n *PhiEditor) dispose() {
	for _, comp := range n.GetComponents() {
		gui.Dispose(comp)
	}
}

func (n *PhiEditor) update() bool {
	needsRender := false
	for _, comp := range n.GetComponents() {
		dirty := comp.OnUpdate()
		if dirty {
			needsRender = true
		}
	}
	return needsRender
}

func (n *PhiEditor) render(ctx *strife.Renderer) {
	ctx.SetFont(n.defaultFont)

	for _, child := range n.GetComponents() {
		gui.Render(child, ctx)
	}
}

func main() {
	config := cfg.Setup()

	ww, wh := 1280, 720
	window := strife.SetupRenderWindow(ww, wh, strife.DefaultConfig())
	window.SetTitle("Hello world!")
	window.SetResizable(true)

	editor := &PhiEditor{running: true}
	window.HandleEvents(func(evt strife.StrifeEvent) {
		switch evt.(type) {
		case *strife.CloseEvent:
			window.Close()
		default:
			editor.handleEvent(evt)
		}
	})

	window.Create()

	{
		size := "16"
		switch runtime.GOOS {
		case "windows":
			size = "256"
		case "darwin":
			size = "512"
		case "linux":
			size = "96"
		default:
			log.Println("unrecognized runtime ", runtime.GOOS)
		}

		icon, err := strife.LoadImage("./res/icons/icon" + size + ".png")
		if err != nil {
			log.Println("Failed to load icon ", err.Error())
		} else {
			window.SetIconImage(icon)
			defer icon.Destroy()
		}
	}

	editor.init(&config)

	timer := strife.CurrentTimeMillis()
	frames, updates := 0, 0
	fps, ups := frames, updates

	ctx := window.GetRenderContext()

	ctx.Clear()
	editor.render(ctx)
	ctx.Display()

	for {
		window.PollEvents()
		if window.CloseRequested() {
			break
		}

		if editor.update() || config.Render.Always_Render {
			ctx.Clear()
			editor.render(ctx)

			// this is only printed on each
			// render...
			ctx.SetColor(strife.White)
			ctx.String(fmt.Sprintf("fps: %d, ups %d", fps, ups), ww-256, wh-128)

			ctx.Display()
			frames += 1
		}
		updates += 1

		if strife.CurrentTimeMillis()-timer > 1000 {
			timer = strife.CurrentTimeMillis()
			fps, ups = frames, updates
			frames, updates = 0, 0
		}

		if config.Render.Throttle_Cpu_Usage {
			// todo put in the config how long
			// we sleep for!
			time.Sleep(16)
		}
	}

	editor.dispose()
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"image"
	"image/jpeg"
	"image/png"
	"log"
	"os"
	"path/filepath"
	"flag"
	"github.com/oliamb/cutter"
)

func cropAndSave(inputFilePath string, cWidth int, cHeight int) () {

	// Check if we can handle this image
	fileExtension := filepath.Ext(inputFilePath)
	if fileExtension != ".jpg" && fileExtension != ".png" {
		log.Fatal("Cannot handle image of this type")
	}

	inputFileDir, inputFileName := filepath.Split(inputFilePath)
	f, err := os.Open(inputFilePath)
	if err != nil {
		log.Fatal("Cannot open file", err)
	}
	defer f.Close()

	// We first decode the image
	img, _, err := image.Decode(f)
	if err != nil {
		log.Fatal("Cannot decode image:", err)
	}

	// Perform the cropping
	croppedImg, err := cutter.Crop(img, cutter.Config{
		Height:  cHeight,
		Width:   cWidth,
		Mode:    cutter.TopLeft,
		Anchor:  image.Point{60, 10},
		Options: 0,
	})

	if err != nil {
		log.Fatal("Cannot crop image:", err)
	}

	// Write the cropped image into a file
	croppedFileName := "cropped_" + inputFileName
	croppedFilePath := filepath.Join(inputFileDir, croppedFileName)
	croppedFile, err := os.Create(croppedFilePath)
	if err != nil {
		log.Fatal("Could not save cropped image")
	}
	defer croppedFile.Close()

	// Now we encode the cropped image data using the appropriate
	// encoder and save it to the above file
	switch fileExtension {
	case ".png":
		err = png.Encode(croppedFile, croppedImg)
	case ".jpg":
		err = jpeg.Encode(croppedFile, croppedImg, &jpeg.Options{})
	}

	if err != nil {
		log.Fatal("Error saving")
	}
	fmt.Printf("Saved cropped image as %s\n", croppedFilePath)
}

func main() {

	// Setup the flags
	cHeight := flag.Int("height", 0, "Crop Height")
	cWidth := flag.Int("width", 0, "Crop Width")
	flag.Parse()

	//Check flags, file name specified
	if *cHeight == 0 {
		log.Fatal("Must specify the Crop Height")
	}

	if *cWidth == 0 {
		log.Fatal("Must specify crop width")
	}

	if len(flag.Args()) == 0 {
		log.Fatal("Must specify at least 1 image to crop")
	}

	// Open the file specified as the first argument
	inputFilePath := flag.Args()[0]
	cropAndSave(inputFilePath, *cWidth, *cHeight)
}
<commit_msg>Simple comment describing what cropit is<commit_after>// Simple command line program to crop images
package main

import (
	"errors"
	"fmt"
	"image"
	"image/jpeg"
	"image/png"
	"log"
	"os"
	"path/filepath"
	"flag"
	"github.com/oliamb/cutter"
)

func cropAndSave(inputFilePath string, cWidth int, cHeight int) () {

	// Check if we can handle this image
	fileExtension := filepath.Ext(inputFilePath)
	if fileExtension != ".jpg" && fileExtension != ".png" {
		log.Fatal("Cannot handle image of this type")
	}

	inputFileDir, inputFileName := filepath.Split(inputFilePath)
	f, err := os.Open(inputFilePath)
	if err != nil {
		log.Fatal("Cannot open file", err)
	}
	defer f.Close()

	// We first decode the image
	img, _, err := image.Decode(f)
	if err != nil {
		log.Fatal("Cannot decode image:", err)
	}

	// Perform the cropping
	croppedImg, err := cutter.Crop(img, cutter.Config{
		Height:  cHeight,
		Width:   cWidth,
		Mode:    cutter.TopLeft,
		Anchor:  image.Point{60, 10},
		Options: 0,
	})

	if err != nil {
		log.Fatal("Cannot crop image:", err)
	}

	// Write the cropped image into a file
	croppedFileName := "cropped_" + inputFileName
	croppedFilePath := filepath.Join(inputFileDir, croppedFileName)
	croppedFile, err := os.Create(croppedFilePath)
	if err != nil {
		log.Fatal("Could not save cropped image")
	}
	defer croppedFile.Close()

	// Now we encode the cropped image data using the appropriate
	// encoder and save it to the above file
	switch fileExtension {
	case ".png":
		err = png.Encode(croppedFile, croppedImg)
	case ".jpg":
		err = jpeg.Encode(croppedFile, croppedImg, &jpeg.Options{})
	}

	if err != nil {
		log.Fatal("Error saving")
	}
	fmt.Printf("Saved cropped image as %s\n", croppedFilePath)
}

func main() {

	// Setup the flags
	cHeight := flag.Int("height", 0, "Crop Height")
	cWidth := flag.Int("width", 0, "Crop Width")
	flag.Parse()

	//Check flags, file name specified
	if *cHeight == 0 {
		log.Fatal("Must specify the Crop Height")
	}

	if *cWidth == 0 {
		log.Fatal("Must specify crop width")
	}

	if len(flag.Args()) == 0 {
		log.Fatal("Must specify at least 1 image to crop")
	}

	// Open the file specified as the first argument
	inputFilePath := flag.Args()[0]
	cropAndSave(inputFilePath, *cWidth, *cHeight)
}
<|endoftext|>


<commit_before>package main

import (
	"container/list"
	"github.com/gorilla/websocket"
	"html/template"
	"labix.org/v2/mgo"
	"log"
	"net/http"
	"os"
	"time"
)

var upgrader = websocket.Upgrader{}

var clients = list.New()

type message struct {
	Name    string
	Message string
	Time    time.Time
}

func newClient(w http.ResponseWriter, r *http.Request) {
	ws, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		panic(err)
	}

	el := clients.PushBack(ws)
	log.Printf("Got a new client %p, now have: %d clients", ws, clients.Len())

	// Monitor the connection and remove from clients list when it closes
	for {
		if err = ws.ReadJSON(nil); err != nil {
			clients.Remove(el)
		}
	}
}

func notifyUsers(msg message) {
	for e := clients.Front(); e != nil; e = e.Next() {
		ws := e.Value.(*websocket.Conn)
		log.Printf("Notifying user %p of new message", ws)
		go websocket.WriteJSON(ws, msg)
	}
}

func postMessage(resp http.ResponseWriter, req *http.Request) {
	session, err := mgo.Dial(os.Getenv("MONGOHQ_URL"))
	if err != nil {
		panic(err)
	}
	db := session.DB("")
	collection := db.C("posts")

	if req.Method != "POST" {
		return
	}

	name := req.FormValue("name")
	if name == "" {
		name = "Anonymous coward"
	}
	msg := req.FormValue("message")
	if msg == "" {
		msg = "Gosh, nothing to say?!"
	}
	m := message{name, msg, time.Now()}
	err = collection.Insert(m)
	if err != nil {
		panic(err)
	}
	session.Close()
	go notifyUsers(m)
}

func home(resp http.ResponseWriter, req *http.Request) {
	session, err := mgo.Dial(os.Getenv("MONGOHQ_URL"))
	if err != nil {
		panic(err)
	}
	db := session.DB("")
	collection := db.C("posts")

	home, err := template.ParseFiles("home.html")
	if err != nil {
		panic(err)
	}

	var messages [10]message
	msg_count := 0
	iter := collection.Find(nil).Sort("-time").Batch(10).Iter()
	for msg_count < 10 && iter.Next(&messages[msg_count]) {
		msg_count += 1
	}
	if err := iter.Close(); err != nil {
		panic(err)
	}
	session.Close()

	ctx := map[string]interface{}{
		"title":    "How do you like them apples?!",
		"messages": messages[:msg_count],
	}

	home.Execute(resp, ctx)
}

func main() {
	http.HandleFunc("/websocket/", newClient)

	http.HandleFunc("/msg.mst", func(w http.ResponseWriter, r *http.Request) {
		http.ServeFile(w, r, "msg.mst")
	})
	http.HandleFunc("/post/message/", postMessage)
	http.HandleFunc("/", home)
	err := http.ListenAndServe(":"+os.Getenv("PORT"), nil)
	if err != nil {
		panic(err)
	}
}
<commit_msg>Stop processing after errors.<commit_after>package main

import (
	"container/list"
	"github.com/gorilla/websocket"
	"html/template"
	"labix.org/v2/mgo"
	"log"
	"net/http"
	"os"
	"time"
)

var upgrader = websocket.Upgrader{}

var clients = list.New()

type message struct {
	Name    string
	Message string
	Time    time.Time
}

func newClient(w http.ResponseWriter, r *http.Request) {
	ws, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		panic(err)
	}

	el := clients.PushBack(ws)
	log.Printf("Got a new client %p, now have: %d clients", ws, clients.Len())

	// Monitor the connection and remove from clients list when it closes
	for {
		if err = ws.ReadJSON(nil); err != nil {
			clients.Remove(el)
			return
		}
	}
}

func notifyUsers(msg message) {
	for e := clients.Front(); e != nil; e = e.Next() {
		ws := e.Value.(*websocket.Conn)
		log.Printf("Notifying user %p of new message", ws)
		go websocket.WriteJSON(ws, msg)
	}
}

func postMessage(resp http.ResponseWriter, req *http.Request) {
	session, err := mgo.Dial(os.Getenv("MONGOHQ_URL"))
	if err != nil {
		panic(err)
	}
	db := session.DB("")
	collection := db.C("posts")

	if req.Method != "POST" {
		return
	}

	name := req.FormValue("name")
	if name == "" {
		name = "Anonymous coward"
	}
	msg := req.FormValue("message")
	if msg == "" {
		msg = "Gosh, nothing to say?!"
	}
	m := message{name, msg, time.Now()}
	err = collection.Insert(m)
	if err != nil {
		panic(err)
	}
	session.Close()
	go notifyUsers(m)
}

func home(resp http.ResponseWriter, req *http.Request) {
	session, err := mgo.Dial(os.Getenv("MONGOHQ_URL"))
	if err != nil {
		panic(err)
	}
	db := session.DB("")
	collection := db.C("posts")

	home, err := template.ParseFiles("home.html")
	if err != nil {
		panic(err)
	}

	var messages [10]message
	msg_count := 0
	iter := collection.Find(nil).Sort("-time").Batch(10).Iter()
	for msg_count < 10 && iter.Next(&messages[msg_count]) {
		msg_count += 1
	}
	if err := iter.Close(); err != nil {
		panic(err)
	}
	session.Close()

	ctx := map[string]interface{}{
		"title":    "How do you like them apples?!",
		"messages": messages[:msg_count],
	}

	home.Execute(resp, ctx)
}

func main() {
	http.HandleFunc("/websocket/", newClient)

	http.HandleFunc("/msg.mst", func(w http.ResponseWriter, r *http.Request) {
		http.ServeFile(w, r, "msg.mst")
	})
	http.HandleFunc("/post/message/", postMessage)
	http.HandleFunc("/", home)
	err := http.ListenAndServe(":"+os.Getenv("PORT"), nil)
	if err != nil {
		panic(err)
	}
}
<|endoftext|>


<commit_before>package main

import "io"
import "os"

import "github.com/codegangsta/cli"
import "github.com/NCI-GDC/gdc-client/client"

// Logging flags shared between all commands.
var log_flags = []cli.Flag{
	cli.BoolFlag{
		Name:  "verbose",
		Usage: "verbose logging",
	},
	cli.BoolFlag{
		Name:  "debug",
		Usage: "debug logging",
	},
}

// Auth flags shared between all commands.
var auth_flags = []cli.Flag{
	cli.StringFlag{
		Name:  "T, token",
		Usage: "token string",
	},
	cli.StringFlag{
		Name:  "t, token-file",
		Usage: "token file",
	},
}

// Host flags shared between all commands.
var host_flags = []cli.Flag{
	cli.StringFlag{
		Name:   "H, host",
		Usage:  "GDC API host",
		Value:  "gdc-api.nci.nih.gov",
		EnvVar: "GDC_API_HOST",
	},
	cli.IntFlag{
		Name:   "P, port",
		Usage:  "GDC API port",
		Value:  443,
		EnvVar: "GDC_API_PORT",
	},
}

func main() {
	app := cli.NewApp()

	app.Name = "gdc-client"
	app.Usage = "The Genomics Data Commons Command Line Client"
	app.UsageText = "gdc-client [command] ..."

	var globals = []cli.Flag{}
	globals = append(globals, log_flags...)
	globals = append(globals, auth_flags...)
	globals = append(globals, host_flags...)

	app.Commands = []cli.Command{
		{
			Name:      "query",
			Flags:     append(globals, []cli.Flag{}...),
			Usage:     "query metadata using GDC DSL",
			Action:    query,
			Category:  "metadata query",
			ArgsUsage: "query",
		},
		{
			Name:      "upload",
			Flags:     append(globals, []cli.Flag{}...),
			Usage:     "upload data by GDC UUID",
			Action:    upload,
			Category:  "data transfer",
			ArgsUsage: "id [path]",
		},
		{
			Name:      "download",
			Flags:     append(globals, []cli.Flag{}...),
			Usage:     "download data by GDC UUID",
			Action:    download,
			Category:  "data transfer",
			ArgsUsage: "id [path]",
		},
	}

	app.Run(os.Args)
}

// Deconstruct a cli context and call download
// using context arguments and flags.
func download(c *cli.Context) {
	var gdc = client.NewClient(
		c.String("host"),
		c.Int("port"),
	)

	var res, _ = gdc.Download(
		c.Args()[0],
		c.String("token"),
	)

	io.Copy(os.Stdout, res)
}

// Deconstruct a cli context and call upload
// using context arguments and flags.
func upload(c *cli.Context) {
}

// Deconstruct a cli context and call query
// using context arguments and flags.
func query(c *cli.Context) {
}
<commit_msg>fixes client import<commit_after>package main

import "io"
import "os"

import "github.com/codegangsta/cli"
import "github.com/gudCodes/gdc-client/client"

// Logging flags shared between all commands.
var log_flags = []cli.Flag{
	cli.BoolFlag{
		Name:  "verbose",
		Usage: "verbose logging",
	},
	cli.BoolFlag{
		Name:  "debug",
		Usage: "debug logging",
	},
}

// Auth flags shared between all commands.
var auth_flags = []cli.Flag{
	cli.StringFlag{
		Name:  "T, token",
		Usage: "token string",
	},
	cli.StringFlag{
		Name:  "t, token-file",
		Usage: "token file",
	},
}

// Host flags shared between all commands.
var host_flags = []cli.Flag{
	cli.StringFlag{
		Name:   "H, host",
		Usage:  "GDC API host",
		Value:  "gdc-api.nci.nih.gov",
		EnvVar: "GDC_API_HOST",
	},
	cli.IntFlag{
		Name:   "P, port",
		Usage:  "GDC API port",
		Value:  443,
		EnvVar: "GDC_API_PORT",
	},
}

func main() {
	app := cli.NewApp()

	app.Name = "gdc-client"
	app.Usage = "The Genomics Data Commons Command Line Client"
	app.UsageText = "gdc-client [command] ..."

	var globals = []cli.Flag{}
	globals = append(globals, log_flags...)
	globals = append(globals, auth_flags...)
	globals = append(globals, host_flags...)

	app.Commands = []cli.Command{
		{
			Name:      "query",
			Flags:     append(globals, []cli.Flag{}...),
			Usage:     "query metadata using GDC DSL",
			Action:    query,
			Category:  "metadata query",
			ArgsUsage: "query",
		},
		{
			Name:      "upload",
			Flags:     append(globals, []cli.Flag{}...),
			Usage:     "upload data by GDC UUID",
			Action:    upload,
			Category:  "data transfer",
			ArgsUsage: "id [path]",
		},
		{
			Name:      "download",
			Flags:     append(globals, []cli.Flag{}...),
			Usage:     "download data by GDC UUID",
			Action:    download,
			Category:  "data transfer",
			ArgsUsage: "id [path]",
		},
	}

	app.Run(os.Args)
}

// Deconstruct a cli context and call download
// using context arguments and flags.
func download(c *cli.Context) {
	var gdc = client.NewClient(
		c.String("host"),
		c.Int("port"),
	)

	var res, _ = gdc.Download(
		c.Args()[0],
		c.String("token"),
	)

	io.Copy(os.Stdout, res)
}

// Deconstruct a cli context and call upload
// using context arguments and flags.
func upload(c *cli.Context) {
}

// Deconstruct a cli context and call query
// using context arguments and flags.
func query(c *cli.Context) {
}
<|endoftext|>


<commit_before>package main

import (
	"compress/gzip"
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path"
	"regexp"
	"strings"
)

type gitHandler struct {
	method      string
	regexp      *regexp.Regexp
	handle_func func(string, string, string, http.ResponseWriter, *http.Request)
	rpc         string
}

var http_client = &http.Client{}

// Command-line options
var repo_root string
var listen_addr = flag.String("listen_addr", "localhost:8181", "Listen address for HTTP server")
var auth_backend = flag.String("auth_backend", "http://localhost:8080", "Authentication/authorization backend")

var git_handlers = [...]gitHandler{
	gitHandler{"GET", regexp.MustCompile(`\A(/..*)/info/refs\z`), handle_get_info_refs, ""},
	gitHandler{"POST", regexp.MustCompile(`\A(/..*)/git-upload-pack\z`), handle_post_rpc, "git-upload-pack"},
	gitHandler{"POST", regexp.MustCompile(`\A(/..*)/git-receive-pack\z`), handle_post_rpc, "git-receive-pack"},
}

func main() {
	// Parse the command-line
	flag.Parse()
	repo_root = flag.Arg(0)
	log.Printf("repo_root: %s", repo_root)

	http.HandleFunc("/", git_handler)
	log.Fatal(http.ListenAndServe(*listen_addr, nil))
}

func git_handler(w http.ResponseWriter, r *http.Request) {
	var user string

	log.Print(r.Method, " ", r.URL)

	for _, g := range git_handlers {
		path_match := g.regexp.FindStringSubmatch(r.URL.Path)
		if r.Method == g.method && path_match != nil {
			auth_response, err := do_auth_request(r)
			if err != nil {
				fail_500(w, err)
				return
			}
			if auth_response.StatusCode != 200 {
				// The Git request is not allowed by the backend. Maybe the client
				// needs to send HTTP Basic credentials.
				// Forward the response from the auth backend to our client
				for k, v := range auth_response.Header {
					w.Header()[k] = v
				}
				w.WriteHeader(auth_response.StatusCode)
				io.Copy(w, auth_response.Body)
				return
			}
			// The auth backend told us who the user is according to them
			if _, err := fmt.Fscan(auth_response.Body, &user); err != nil {
				fail_500(w, err)
				return
			}
			g.handle_func(user, g.rpc, path.Join(repo_root, path_match[1]), w, r)
			return
		}
	}
	http.Error(w, "Not found", 404)
}

func do_auth_request(r *http.Request) (result *http.Response, err error) {
	url := fmt.Sprintf("%s%s", *auth_backend, r.URL.RequestURI())
	auth_req, err := http.NewRequest(r.Method, url, nil)
	if err != nil {
		return nil, err
	}
	for k, v := range r.Header {
		auth_req.Header[k] = v
	}
	result, err = http_client.Do(auth_req)
	if err != nil {
		return nil, err
	}
	return result, nil
}

func handle_get_info_refs(user string, _ string, path string, w http.ResponseWriter, r *http.Request) {
	rpc := r.URL.Query().Get("service")
	switch rpc {
	case "git-upload-pack", "git-receive-pack":
		cmd := exec.Command("git", strings.TrimPrefix(rpc, "git-"), "--stateless-rpc", "--advertise-refs", path)
		set_cmd_env(cmd, user)
		stdout, err := cmd.StdoutPipe()
		if err != nil {
			fail_500(w, err)
			return
		}
		if err := cmd.Start(); err != nil {
			fail_500(w, err)
			return
		}
		w.Header().Add("Content-Type", fmt.Sprintf("application/x-%s-advertisement", rpc))
		no_cache(w)
		w.WriteHeader(200)
		if err := pkt_line(w, fmt.Sprintf("# service=%s\n", rpc)); err != nil {
			panic(err)
		}
		if err := pkt_flush(w); err != nil {
			panic(err)
		}
		if _, err := io.Copy(w, stdout); err != nil {
			panic(err) // No point in sending 500 to the client
		}
		if err := cmd.Wait(); err != nil {
			panic(err) // No point in sending 500 to the client
		}
	case "":
		// The 'dumb' Git HTTP protocol is not supported
		http.Error(w, "Not found", 404)
	}
}

func set_cmd_env(cmd *exec.Cmd, user string) {
	cmd.Env = []string{fmt.Sprintf("PATH=%s", os.Getenv("PATH")), fmt.Sprintf("GL_ID=%s", user)}
}

func handle_post_rpc(user string, rpc string, path string, w http.ResponseWriter, r *http.Request) {
	var body io.Reader
	var err error

	if r.Header.Get("Content-Encoding") == "gzip" {
		body, err = gzip.NewReader(r.Body)
		if err != nil {
			fail_500(w, err)
			return
		}
	} else {
		body = r.Body
	}
	cmd := exec.Command("git", strings.TrimPrefix(rpc, "git-"), "--stateless-rpc", path)
	set_cmd_env(cmd, user)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		fail_500(w, err)
		return
	}
	stdin, err := cmd.StdinPipe()
	if err != nil {
		fail_500(w, err)
		return
	}
	if err := cmd.Start(); err != nil {
		fail_500(w, err)
		return
	}
	if _, err := io.Copy(stdin, body); err != nil {
		fail_500(w, err)
		return
	}
	stdin.Close()

	w.Header().Add("Content-Type", fmt.Sprintf("application/x-%s-result", rpc))
	no_cache(w)
	w.WriteHeader(200)
	if _, err := io.Copy(w, stdout); err != nil {
		panic(err) // No point in sending 500 to the client
	}
	if err := cmd.Wait(); err != nil {
		panic(err) // No point in sending 500 to the client
	}
}

func pkt_line(w io.Writer, s string) error {
	_, err := fmt.Fprintf(w, "%04x%s", len(s)+4, s)
	return err
}

func pkt_flush(w io.Writer) error {
	_, err := fmt.Fprint(w, "0000")
	return err
}

func fail_500(w http.ResponseWriter, err error) {
	http.Error(w, "Internal server error", 500)
	log.Print(err)
}

func no_cache(w http.ResponseWriter) {
	w.Header().Add("Cache-Control", "no-cache")
}
<commit_msg>Make sure Go closes all pipes<commit_after>package main

import (
	"compress/gzip"
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path"
	"regexp"
	"strings"
)

type gitHandler struct {
	method      string
	regexp      *regexp.Regexp
	handle_func func(string, string, string, http.ResponseWriter, *http.Request)
	rpc         string
}

var http_client = &http.Client{}

// Command-line options
var repo_root string
var listen_addr = flag.String("listen_addr", "localhost:8181", "Listen address for HTTP server")
var auth_backend = flag.String("auth_backend", "http://localhost:8080", "Authentication/authorization backend")

var git_handlers = [...]gitHandler{
	gitHandler{"GET", regexp.MustCompile(`\A(/..*)/info/refs\z`), handle_get_info_refs, ""},
	gitHandler{"POST", regexp.MustCompile(`\A(/..*)/git-upload-pack\z`), handle_post_rpc, "git-upload-pack"},
	gitHandler{"POST", regexp.MustCompile(`\A(/..*)/git-receive-pack\z`), handle_post_rpc, "git-receive-pack"},
}

func main() {
	// Parse the command-line
	flag.Parse()
	repo_root = flag.Arg(0)
	log.Printf("repo_root: %s", repo_root)

	http.HandleFunc("/", git_handler)
	log.Fatal(http.ListenAndServe(*listen_addr, nil))
}

func git_handler(w http.ResponseWriter, r *http.Request) {
	var user string

	log.Print(r.Method, " ", r.URL)

	for _, g := range git_handlers {
		path_match := g.regexp.FindStringSubmatch(r.URL.Path)
		if r.Method == g.method && path_match != nil {
			auth_response, err := do_auth_request(r)
			if err != nil {
				fail_500(w, err)
				return
			}
			if auth_response.StatusCode != 200 {
				// The Git request is not allowed by the backend. Maybe the client
				// needs to send HTTP Basic credentials.
				// Forward the response from the auth backend to our client
				for k, v := range auth_response.Header {
					w.Header()[k] = v
				}
				w.WriteHeader(auth_response.StatusCode)
				io.Copy(w, auth_response.Body)
				return
			}
			// The auth backend told us who the user is according to them
			if _, err := fmt.Fscan(auth_response.Body, &user); err != nil {
				fail_500(w, err)
				return
			}
			g.handle_func(user, g.rpc, path.Join(repo_root, path_match[1]), w, r)
			return
		}
	}
	http.Error(w, "Not found", 404)
}

func do_auth_request(r *http.Request) (result *http.Response, err error) {
	url := fmt.Sprintf("%s%s", *auth_backend, r.URL.RequestURI())
	auth_req, err := http.NewRequest(r.Method, url, nil)
	if err != nil {
		return nil, err
	}
	for k, v := range r.Header {
		auth_req.Header[k] = v
	}
	result, err = http_client.Do(auth_req)
	if err != nil {
		return nil, err
	}
	return result, nil
}

func handle_get_info_refs(user string, _ string, path string, w http.ResponseWriter, r *http.Request) {
	rpc := r.URL.Query().Get("service")
	switch rpc {
	case "git-upload-pack", "git-receive-pack":
		cmd := exec.Command("git", strings.TrimPrefix(rpc, "git-"), "--stateless-rpc", "--advertise-refs", path)
		set_cmd_env(cmd, user)
		stdout, err := cmd.StdoutPipe()
		if err != nil {
			fail_500(w, err)
			return
		}
		defer stdout.Close()
		if err := cmd.Start(); err != nil {
			fail_500(w, err)
			return
		}
		w.Header().Add("Content-Type", fmt.Sprintf("application/x-%s-advertisement", rpc))
		no_cache(w)
		w.WriteHeader(200)
		if err := pkt_line(w, fmt.Sprintf("# service=%s\n", rpc)); err != nil {
			panic(err)
		}
		if err := pkt_flush(w); err != nil {
			panic(err)
		}
		if _, err := io.Copy(w, stdout); err != nil {
			panic(err) // No point in sending 500 to the client
		}
		if err := cmd.Wait(); err != nil {
			panic(err) // No point in sending 500 to the client
		}
	case "":
		// The 'dumb' Git HTTP protocol is not supported
		http.Error(w, "Not found", 404)
	}
}

func set_cmd_env(cmd *exec.Cmd, user string) {
	cmd.Env = []string{fmt.Sprintf("PATH=%s", os.Getenv("PATH")), fmt.Sprintf("GL_ID=%s", user)}
}

func handle_post_rpc(user string, rpc string, path string, w http.ResponseWriter, r *http.Request) {
	var body io.Reader
	var err error

	if r.Header.Get("Content-Encoding") == "gzip" {
		body, err = gzip.NewReader(r.Body)
		if err != nil {
			fail_500(w, err)
			return
		}
	} else {
		body = r.Body
	}
	cmd := exec.Command("git", strings.TrimPrefix(rpc, "git-"), "--stateless-rpc", path)
	set_cmd_env(cmd, user)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		fail_500(w, err)
		return
	}
	defer stdout.Close()
	stdin, err := cmd.StdinPipe()
	if err != nil {
		fail_500(w, err)
		return
	}
	defer stdin.Close()
	if err := cmd.Start(); err != nil {
		fail_500(w, err)
		return
	}
	if _, err := io.Copy(stdin, body); err != nil {
		fail_500(w, err)
		return
	}
	stdin.Close()

	w.Header().Add("Content-Type", fmt.Sprintf("application/x-%s-result", rpc))
	no_cache(w)
	w.WriteHeader(200)
	if _, err := io.Copy(w, stdout); err != nil {
		panic(err) // No point in sending 500 to the client
	}
	if err := cmd.Wait(); err != nil {
		panic(err) // No point in sending 500 to the client
	}
}

func pkt_line(w io.Writer, s string) error {
	_, err := fmt.Fprintf(w, "%04x%s", len(s)+4, s)
	return err
}

func pkt_flush(w io.Writer) error {
	_, err := fmt.Fprint(w, "0000")
	return err
}

func fail_500(w http.ResponseWriter, err error) {
	http.Error(w, "Internal server error", 500)
	log.Print(err)
}

func no_cache(w http.ResponseWriter) {
	w.Header().Add("Cache-Control", "no-cache")
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/penberg/ustat/ustat"
	"gopkg.in/urfave/cli.v1"
	"os"
	"regexp"
	"time"
)

func main() {
	app := cli.NewApp()
	app.Name = "ustat"
	app.Usage = "Unified system statistics collector"
	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "c,cpu",
			Usage: "Enable CPU stats collection",
		},
		cli.BoolFlag{
			Name:  "i,int",
			Usage: "Enable interrupt stats collection",
		},
		cli.BoolFlag{
			Name:  "n,net",
			Usage: "Enable network stats collection",
		},
		cli.BoolFlag{
			Name:  "d,disk",
			Usage: "Enable disk stats collection",
		},
		cli.StringFlag{
			Name:  "grep",
			Usage: "Regular expression patter for filtering stats",
		},
	}
	app.Action = func(ctx *cli.Context) error {
		stats := make([]*ustat.Stat, 0)
		if ctx.Bool("cpu") {
			stats = append(stats, ustat.NewCpusStat())
		}
		if ctx.Bool("int") {
			stats = append(stats, ustat.NewInterruptsStat())
		}
		if ctx.Bool("net") {
			stats = append(stats, ustat.NewNetStat())
		}
		if ctx.Bool("disk") {
			stats = append(stats, ustat.NewDiskStat())
		}
		pattern := ctx.String("grep")
		if len(stats) == 0 {
			return cli.NewExitError("No stats enabled", 1)
		}
		fmt.Printf("# This file has been generated by ustat.\n")
		fmt.Printf("#\n")
		fmt.Printf("# Column descriptions:\n")
		for _, stat := range stats {
			for _, description := range stat.Descriptions {
				matched, err := regexp.MatchString(pattern, description)
				if err != nil || !matched {
					continue
				}
				fmt.Printf("# %s\n", description)
			}
		}
		for _, stat := range stats {
			for _, name := range stat.Names {
				matched, err := regexp.MatchString(pattern, name)
				if err != nil || !matched {
					continue
				}
				fmt.Printf("%s\t", name)
			}
		}
		fmt.Println("")
		for {
			for _, stat := range stats {
				values := stat.Reader.Read()
				for idx, value := range values {
					matched, err := regexp.MatchString(pattern, stat.Names[idx])
					if err != nil || !matched {
						continue
					}
					fmt.Printf("%d\t", value)
				}
			}
			fmt.Println("")
			time.Sleep(1 * time.Second)
		}
		return nil
	}
	app.Run(os.Args)
}
<commit_msg>Optimize regexp matching if no pattern is defined<commit_after>package main

import (
	"fmt"
	"github.com/penberg/ustat/ustat"
	"gopkg.in/urfave/cli.v1"
	"os"
	"regexp"
	"time"
)

func main() {
	app := cli.NewApp()
	app.Name = "ustat"
	app.Usage = "Unified system statistics collector"
	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "c,cpu",
			Usage: "Enable CPU stats collection",
		},
		cli.BoolFlag{
			Name:  "i,int",
			Usage: "Enable interrupt stats collection",
		},
		cli.BoolFlag{
			Name:  "n,net",
			Usage: "Enable network stats collection",
		},
		cli.BoolFlag{
			Name:  "d,disk",
			Usage: "Enable disk stats collection",
		},
		cli.StringFlag{
			Name:  "grep",
			Usage: "Regular expression patter for filtering stats",
		},
	}
	app.Action = func(ctx *cli.Context) error {
		stats := make([]*ustat.Stat, 0)
		if ctx.Bool("cpu") {
			stats = append(stats, ustat.NewCpusStat())
		}
		if ctx.Bool("int") {
			stats = append(stats, ustat.NewInterruptsStat())
		}
		if ctx.Bool("net") {
			stats = append(stats, ustat.NewNetStat())
		}
		if ctx.Bool("disk") {
			stats = append(stats, ustat.NewDiskStat())
		}
		pattern := ctx.String("grep")
		if len(stats) == 0 {
			return cli.NewExitError("No stats enabled", 1)
		}
		fmt.Printf("# This file has been generated by ustat.\n")
		fmt.Printf("#\n")
		fmt.Printf("# Column descriptions:\n")
		for _, stat := range stats {
			for _, description := range stat.Descriptions {
				if pattern != "" {
					matched, err := regexp.MatchString(pattern, description)
					if err != nil || !matched {
						continue
					}
				}
				fmt.Printf("# %s\n", description)
			}
		}
		for _, stat := range stats {
			for _, name := range stat.Names {
				if pattern != "" {
					matched, err := regexp.MatchString(pattern, name)
					if err != nil || !matched {
						continue
					}
				}
				fmt.Printf("%s\t", name)
			}
		}
		fmt.Println("")
		for {
			for _, stat := range stats {
				values := stat.Reader.Read()
				for idx, value := range values {
					if pattern != "" {
						matched, err := regexp.MatchString(pattern, stat.Names[idx])
						if err != nil || !matched {
							continue
						}
					}
					fmt.Printf("%d\t", value)
				}
			}
			fmt.Println("")
			time.Sleep(1 * time.Second)
		}
		return nil
	}
	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/exec"
	"time"

	"github.com/anacrolix/torrent"
	"github.com/dustin/go-humanize"
	"github.com/julienschmidt/httprouter"
)

var t torrent.Torrent
var seed *bool
var vlc *bool
var progress int64

const clearScreen = "\033[H\033[2J"

// Exit statuses.
const (
	_                       = iota
	exitNoTorrentProvided   = iota
	exitErrorCreatingClient = iota
	exitErrorAddingTorrent  = iota
)

func main() {
	// Set up flags.
	seed = flag.Bool("seed", true, "Seed after finished downloading")
	vlc = flag.Bool("vlc", false, "Open vlc to play the file")

	flag.Parse()
	if len(flag.Args()) == 0 {
		usage()
		os.Exit(exitNoTorrentProvided)
	}

	// Start up the torrent client.
	client, err := torrent.NewClient(&torrent.Config{
		DataDir:  os.TempDir(),
		NoUpload: !(*seed),
	})

	if err != nil {
		log.Fatal(err)
		os.Exit(exitErrorCreatingClient)
	}

	// Add the magnet url.
	if t, err = client.AddMagnet(flag.Arg(0)); err != nil {
		log.Fatal(err)
		os.Exit(exitErrorAddingTorrent)
	}

	// Start downloading files.
	go func() {
		<-t.GotInfo()
		t.DownloadAll()
	}()

	// Http handler.
	go func() {
		router := httprouter.New()
		router.GET("/", getFile)
		log.Fatal(http.ListenAndServe(":8080", router))
	}()

	if *vlc {
		go func() {
			for !readyForPlayback() {
				time.Sleep(time.Second)
			}
			log.Printf("Playing in vlc")

			// @todo decide command to run based on os.
			exec.Command("open", "-a", "vlc", "http://localhost:8080").Start()
		}()
	}

	// Cli render loop.
	for true {
		render()
		time.Sleep(time.Second)
	}
}

func readyForPlayback() bool {
	percentage := float64(t.BytesCompleted()) / float64(t.Length())

	return percentage > 0.05
}

func render() {
	var currentProgress = t.BytesCompleted()
	speed := humanize.Bytes(uint64(currentProgress-progress)) + "/s"
	progress = currentProgress

	percentage := float64(t.BytesCompleted()) / float64(t.Length()) * 100
	complete := humanize.Bytes(uint64(t.BytesCompleted()))
	size := humanize.Bytes(uint64(t.Length()))
	connections := len(t.Conns)

	print(clearScreen)
	fmt.Println(t.Name())
	fmt.Println("=============================================================")
	if t.BytesCompleted() > 0 {
		fmt.Printf("Progress: \t%s / %s  %.2f%%\n", complete, size, percentage)
	}
	if t.BytesCompleted() < t.Length() {
		fmt.Printf("Download speed: %s\n", speed)
	}
	fmt.Printf("Connections: \t%d\n", connections)
}

func usage() {
	flag.Usage()
}

func getLargestFile() torrent.File {
	var target torrent.File
	var maxSize int64

	for _, file := range t.Files() {
		if maxSize < file.Length() {
			maxSize = file.Length()
			target = file
		}
	}

	return target
}

func getFile(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	target := getLargestFile()
	entry, err := NewFileReader(target)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	defer entry.Close()

	http.ServeContent(w, r, target.DisplayPath(), time.Now(), entry)
}
<commit_msg>Drop httprouter<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/exec"
	"time"

	"github.com/anacrolix/torrent"
	"github.com/dustin/go-humanize"
)

var t torrent.Torrent
var seed *bool
var vlc *bool
var progress int64

const clearScreen = "\033[H\033[2J"

// Exit statuses.
const (
	_                       = iota
	exitNoTorrentProvided   = iota
	exitErrorCreatingClient = iota
	exitErrorAddingTorrent  = iota
)

func main() {
	// Set up flags.
	seed = flag.Bool("seed", true, "Seed after finished downloading")
	vlc = flag.Bool("vlc", false, "Open vlc to play the file")

	flag.Parse()
	if len(flag.Args()) == 0 {
		usage()
		os.Exit(exitNoTorrentProvided)
	}

	// Start up the torrent client.
	client, err := torrent.NewClient(&torrent.Config{
		DataDir:  os.TempDir(),
		NoUpload: !(*seed),
	})

	if err != nil {
		log.Fatal(err)
		os.Exit(exitErrorCreatingClient)
	}

	// Add the magnet url.
	if t, err = client.AddMagnet(flag.Arg(0)); err != nil {
		log.Fatal(err)
		os.Exit(exitErrorAddingTorrent)
	}

	// Start downloading files.
	go func() {
		<-t.GotInfo()
		t.DownloadAll()
	}()

	// Http handler.
	go func() {
		http.HandleFunc("/", getFile)
		log.Fatal(http.ListenAndServe(":8080", nil))
	}()

	if *vlc {
		go func() {
			for !readyForPlayback() {
				time.Sleep(time.Second)
			}
			log.Printf("Playing in vlc")

			// @todo decide command to run based on os.
			exec.Command("open", "-a", "vlc", "http://localhost:8080").Start()
		}()
	}

	// Cli render loop.
	for true {
		render()
		time.Sleep(time.Second)
	}
}

func readyForPlayback() bool {
	percentage := float64(t.BytesCompleted()) / float64(t.Length())

	return percentage > 0.05
}

func render() {
	var currentProgress = t.BytesCompleted()
	speed := humanize.Bytes(uint64(currentProgress-progress)) + "/s"
	progress = currentProgress

	percentage := float64(t.BytesCompleted()) / float64(t.Length()) * 100
	complete := humanize.Bytes(uint64(t.BytesCompleted()))
	size := humanize.Bytes(uint64(t.Length()))
	connections := len(t.Conns)

	print(clearScreen)
	fmt.Println(t.Name())
	fmt.Println("=============================================================")
	if t.BytesCompleted() > 0 {
		fmt.Printf("Progress: \t%s / %s  %.2f%%\n", complete, size, percentage)
	}
	if t.BytesCompleted() < t.Length() {
		fmt.Printf("Download speed: %s\n", speed)
	}
	fmt.Printf("Connections: \t%d\n", connections)
}

func usage() {
	flag.Usage()
}

func getLargestFile() torrent.File {
	var target torrent.File
	var maxSize int64

	for _, file := range t.Files() {
		if maxSize < file.Length() {
			maxSize = file.Length()
			target = file
		}
	}

	return target
}

func getFile(w http.ResponseWriter, r *http.Request) {
	target := getLargestFile()
	entry, err := NewFileReader(target)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	defer entry.Close()

	http.ServeContent(w, r, target.DisplayPath(), time.Now(), entry)
}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"os/signal"
	"syscall"
	"fmt"
	"flag"
	"time"
	"strconv"
	"net/http"
	"math/rand"

	"github.com/gorilla/mux"
	"github.com/golang/glog"
	"github.com/GeertJohan/go.rice"

	"github.com/espebra/filebin/app/config"
	"github.com/espebra/filebin/app/model"
	"github.com/espebra/filebin/app/api"
)

var cfg = config.Global
var githash = "No githash provided"
var buildstamp = "No buildstamp provided"

var staticBox *rice.Box
var templateBox *rice.Box

func generateReqId(n int) string {
        var letters = []rune("abcdefghijklmnopqrstuvwxyz0123456789")
        b := make([]rune, n)
        for i := range b {
                b[i] = letters[rand.Intn(len(letters))]
        }
        return string(b)
}

func teardown() {
    glog.Flush()
}

func init() {
	rand.Seed(time.Now().UTC().UnixNano())

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	signal.Notify(c, syscall.SIGTERM)
	go func() {
		<-c
		teardown()
		os.Exit(1)
	}()

	defer glog.Flush()

	flag.StringVar(&cfg.Baseurl, "baseurl",
		cfg.Baseurl, "Baseurl used when generating links.")

	flag.StringVar(&cfg.Filedir, "filedir",
		cfg.Filedir, "Directory to store uploaded files.")

	flag.StringVar(&cfg.Tempdir, "tempdir",
		cfg.Tempdir, "Directory to temporarily store files during upload.")

	flag.StringVar(&cfg.Logdir, "logdir",
		cfg.Logdir, "Directory to write log files to.")

	//flag.StringVar(&cfg.Thumbdir, "thumbdir",
	//	cfg.Thumbdir, "Path to thumbnail directory")

	//flag.StringVar(&cfg.Database, "database",
	//	cfg.Database, "Path to database file")

	flag.StringVar(&cfg.Host, "host",
		cfg.Host, "Listen host.")

	flag.IntVar(&cfg.Port, "port",
		cfg.Port, "Listen port.")

	flag.IntVar(&cfg.Readtimeout, "readtimeout",
		cfg.Readtimeout, "Request read timeout in seconds.")

	flag.IntVar(&cfg.Writetimeout, "writetimeout",
		cfg.Writetimeout, "Response write timeout in seconds.")

	flag.IntVar(&cfg.Maxheaderbytes, "maxheaderbytes",
		cfg.Maxheaderbytes, "Max header size in bytes.")

	//flag.IntVar(&cfg.Pagination, "pagination",
	//	cfg.Pagination,
	//	"Files to show per page for pagination.")

	//flag.StringVar(&cfg.GeoIP2, "geoip2",
	//	cfg.GeoIP2, "Path to the GeoIP2 database file.")

	flag.Int64Var(&cfg.Expiration, "expiration",
		cfg.Expiration, "Tag expiration time in seconds after the last modification.")

	flag.BoolVar(&cfg.Verbose, "verbose",
		cfg.Verbose, "Verbose output.")

//	flag.StringVar(&cfg.TriggerNewTag, "trigger-new-tag",
//		cfg.TriggerNewTag,
//		"Trigger to execute when a new tag is created.")

	flag.StringVar(&cfg.TriggerUploadedFile,
		"trigger-uploaded-file",
		cfg.TriggerUploadedFile,
		"Command to execute when a file is uploaded.")

//	flag.StringVar(&cfg.TriggerExpiredTag, "trigger-expired-tag",
//		cfg.TriggerExpiredTag,
//		"Trigger to execute when a tag expires.")

	flag.BoolVar(&cfg.Version, "version",
		cfg.Version, "Show the version information.")

	flag.Parse()

	if cfg.Version {
		fmt.Println("Git Commit Hash: " + githash)
		fmt.Println("UTC Build Time: " + buildstamp)
		os.Exit(0)
	}

	//if (!IsDir(cfg.Logdir)) {
	//    fmt.Println("The specified log directory is not a directory: ",
	//        cfg.Logdir)
	//    os.Exit(2)
	//}

	flag.Lookup("logtostderr").Value.Set("false")
	flag.Lookup("log_dir").Value.Set(cfg.Logdir)
	flag.Lookup("log_dir").Value.Set(cfg.Logdir)
	flag.Lookup("v").Value.Set("100")

	if cfg.Port < 1 || cfg.Port > 65535 {
		glog.Fatal("Invalid port number, aborting.")
	}

	if cfg.Readtimeout < 1 || cfg.Readtimeout > 3600 {
		glog.Fatal("Invalid read timeout, aborting.")
	}

	if cfg.Writetimeout < 1 || cfg.Writetimeout > 3600 {
		glog.Fatal("Invalid write timeout, aborting.")
	}

	if cfg.Maxheaderbytes < 1 ||
		cfg.Maxheaderbytes > 2 << 40 {
		glog.Fatal("Invalid max header bytes, aborting.")
	}

	//if (!IsDir(cfg.Tempdir)) {
	//    Info.Fatal("The directory " + cfg.Tempdir +
	//        " does not exist.")
	//    os.Exit(2)
	//}

	//if (!IsDir(cfg.Filedir)) {
	//    glog.Fatal("The directory " + cfg.Filedir +
	//        " does not exist.")
	//}

	//if _, err := os.Stat(cfg.GeoIP2); err == nil {
	//    gi, err = geoip2.Open(cfg.GeoIP2)
	//    if err != nil {
	//        Info.Print("Could not open GeoIP2 database ", cfg.GeoIP2,
	//            ": ", err)
	//    }
	//    defer gi.Close()
	//} else {
	//    Info.Print("GeoIP2 database does not exist: ", cfg.GeoIP2)
	//}
}

func main() {
	// Initialize boxes
	staticBox = rice.MustFindBox("static")
	templateBox = rice.MustFindBox("templates")

	if cfg.Verbose {
		fmt.Println("Listen host: " + cfg.Host)
		fmt.Println("Listen port: " + strconv.Itoa(cfg.Port))
		fmt.Println("Read timeout: " +
			strconv.Itoa(cfg.Readtimeout) + " seconds")
		fmt.Println("Write timeout: " +
			strconv.Itoa(cfg.Writetimeout) + " seconds")
		fmt.Println("Max header size: " +
			strconv.Itoa(cfg.Maxheaderbytes) + " bytes")
		fmt.Println("Expiration time: " + strconv.FormatInt(cfg.Expiration, 10) +
			" seconds")
		fmt.Println("Files directory: " + cfg.Filedir)
		//fmt.Println("Thumbnail directory: " + cfg.Thumbdir)
		fmt.Println("Temp directory: " + cfg.Tempdir)
		fmt.Println("Log directory: " + cfg.Logdir)
		//fmt.Println("GeoIP2 database: " + cfg.GeoIP2)
		//fmt.Println("Pagination: " + strconv.Itoa(cfg.Pagination))
		fmt.Println("Baseurl: " + cfg.Baseurl)
		//fmt.Println("Trigger New tag: " + cfg.TriggerNewTag)

                var trigger = cfg.TriggerUploadedFile
                if trigger == "" {
                    trigger = "Not set"
                }
		fmt.Println("Trigger - Uploaded file: " + trigger)

		//fmt.Println("Trigger Expired tag: " + cfg.TriggerExpiredTag)
	}

	//err = Setup()
	//if err != nil {
	//    Error.Println("Database setup error: ", err)
	//}

	glog.Info("Filebin server starting on " + cfg.Host + ":" +
		strconv.Itoa(cfg.Port) + " from directory " +
		cfg.Filedir)

	router := mux.NewRouter()

	http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(staticBox.HTTPBox())))

	http.Handle("/", httpInterceptor(router))

	router.HandleFunc("/api", reqHandler(api.ViewAPI)).Methods("GET", "HEAD")
	router.HandleFunc("/doc", reqHandler(api.ViewDoc)).Methods("GET", "HEAD")
	router.HandleFunc("/", reqHandler(api.ViewIndex)).Methods("GET", "HEAD")
	router.HandleFunc("/", reqHandler(api.Upload)).Methods("POST")
	router.HandleFunc("/{tag:[A-Za-z0-9_-]+}", reqHandler(api.FetchTag)).Methods("GET", "HEAD")
	router.HandleFunc("/{tag:[A-Za-z0-9_-]+}/{filename:.+}", reqHandler(api.FetchFile)).Methods("GET", "HEAD")
	router.HandleFunc("/{tag:[A-Za-z0-9_-]+}/{filename:.+}", reqHandler(api.DeleteFile)).Methods("DELETE")

	//router.HandleFunc("/dashboard{_:/?}", ViewDashboard).Methods("GET", "HEAD")

	//router.HandleFunc("/", ViewIndex).Methods("GET", "HEAD")
	//router.HandleFunc("/upload{_:/?}", RedirectToNewTag).Methods("GET", "HEAD")
	//router.HandleFunc("/upload/{tag:[A-Za-z0-9_-]+}", RedirectOldTag)

	//router.HandleFunc("/{tag:[A-Za-z0-9_-]+}/page/{page:[0-9]+}{_:/?}",
	//    ViewTag).Methods("GET", "HEAD")
	//router.HandleFunc("/{tag:[A-Za-z0-9_-]+}{_:/?}", ViewTag).Methods("GET", "HEAD")

	//router.HandleFunc("/user{_:/?}", user.GetHomePage).Methods("GET")
	//router.HandleFunc("/user/view/{id:[0-9]+}", user.GetViewPage).Methods("GET")
	//router.HandleFunc("/user/{id:[0-9]+}", user.GetViewPage).Methods("GET")

	//// CSS and Javascript
	//fileServer := http.StripPrefix("/static/",
	//    http.FileServer(http.Dir("static")))
	//http.Handle("/static/", fileServer)

	err := http.ListenAndServe(cfg.Host + ":" +
		strconv.Itoa(cfg.Port), nil)

	if err != nil {
		glog.Fatal(err.Error())
	}
}

func reqHandler(fn func (http.ResponseWriter, *http.Request, config.Configuration, model.Context)) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		startTime := time.Now().UTC()

		//var req = ParseRequest(r)

		glog.Info("Request from " + r.RemoteAddr)
		glog.Info(r.Method + " " + r.RequestURI)
		//ReqId := generateReqId(16)
		//glog.Info("ReqId:", ReqId)

		// Populate the context for this request here
		var ctx = model.Context {}
		ctx.TemplateBox = templateBox
		ctx.StaticBox = staticBox
		ctx.Baseurl = cfg.Baseurl

		fn(w, r, cfg, ctx)

		finishTime := time.Now().UTC()
		elapsedTime := finishTime.Sub(startTime)

		//log.Info("Status " + w.Status)
		glog.Info("Processing time: " + elapsedTime.String())
		glog.Flush()
	}
}

func httpInterceptor(router http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		router.ServeHTTP(w, r)
	})
}

<commit_msg>Relax the rules for trailing slashes<commit_after>package main

import (
	"os"
	"os/signal"
	"syscall"
	"fmt"
	"flag"
	"time"
	"strconv"
	"net/http"
	"math/rand"

	"github.com/gorilla/mux"
	"github.com/golang/glog"
	"github.com/GeertJohan/go.rice"

	"github.com/espebra/filebin/app/config"
	"github.com/espebra/filebin/app/model"
	"github.com/espebra/filebin/app/api"
)

var cfg = config.Global
var githash = "No githash provided"
var buildstamp = "No buildstamp provided"

var staticBox *rice.Box
var templateBox *rice.Box

func generateReqId(n int) string {
        var letters = []rune("abcdefghijklmnopqrstuvwxyz0123456789")
        b := make([]rune, n)
        for i := range b {
                b[i] = letters[rand.Intn(len(letters))]
        }
        return string(b)
}

func teardown() {
    glog.Flush()
}

func init() {
	rand.Seed(time.Now().UTC().UnixNano())

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	signal.Notify(c, syscall.SIGTERM)
	go func() {
		<-c
		teardown()
		os.Exit(1)
	}()

	defer glog.Flush()

	flag.StringVar(&cfg.Baseurl, "baseurl",
		cfg.Baseurl, "Baseurl used when generating links.")

	flag.StringVar(&cfg.Filedir, "filedir",
		cfg.Filedir, "Directory to store uploaded files.")

	flag.StringVar(&cfg.Tempdir, "tempdir",
		cfg.Tempdir, "Directory to temporarily store files during upload.")

	flag.StringVar(&cfg.Logdir, "logdir",
		cfg.Logdir, "Directory to write log files to.")

	//flag.StringVar(&cfg.Thumbdir, "thumbdir",
	//	cfg.Thumbdir, "Path to thumbnail directory")

	//flag.StringVar(&cfg.Database, "database",
	//	cfg.Database, "Path to database file")

	flag.StringVar(&cfg.Host, "host",
		cfg.Host, "Listen host.")

	flag.IntVar(&cfg.Port, "port",
		cfg.Port, "Listen port.")

	flag.IntVar(&cfg.Readtimeout, "readtimeout",
		cfg.Readtimeout, "Request read timeout in seconds.")

	flag.IntVar(&cfg.Writetimeout, "writetimeout",
		cfg.Writetimeout, "Response write timeout in seconds.")

	flag.IntVar(&cfg.Maxheaderbytes, "maxheaderbytes",
		cfg.Maxheaderbytes, "Max header size in bytes.")

	//flag.IntVar(&cfg.Pagination, "pagination",
	//	cfg.Pagination,
	//	"Files to show per page for pagination.")

	//flag.StringVar(&cfg.GeoIP2, "geoip2",
	//	cfg.GeoIP2, "Path to the GeoIP2 database file.")

	flag.Int64Var(&cfg.Expiration, "expiration",
		cfg.Expiration, "Tag expiration time in seconds after the last modification.")

	flag.BoolVar(&cfg.Verbose, "verbose",
		cfg.Verbose, "Verbose output.")

//	flag.StringVar(&cfg.TriggerNewTag, "trigger-new-tag",
//		cfg.TriggerNewTag,
//		"Trigger to execute when a new tag is created.")

	flag.StringVar(&cfg.TriggerUploadedFile,
		"trigger-uploaded-file",
		cfg.TriggerUploadedFile,
		"Command to execute when a file is uploaded.")

//	flag.StringVar(&cfg.TriggerExpiredTag, "trigger-expired-tag",
//		cfg.TriggerExpiredTag,
//		"Trigger to execute when a tag expires.")

	flag.BoolVar(&cfg.Version, "version",
		cfg.Version, "Show the version information.")

	flag.Parse()

	if cfg.Version {
		fmt.Println("Git Commit Hash: " + githash)
		fmt.Println("UTC Build Time: " + buildstamp)
		os.Exit(0)
	}

	//if (!IsDir(cfg.Logdir)) {
	//    fmt.Println("The specified log directory is not a directory: ",
	//        cfg.Logdir)
	//    os.Exit(2)
	//}

	flag.Lookup("logtostderr").Value.Set("false")
	flag.Lookup("log_dir").Value.Set(cfg.Logdir)
	flag.Lookup("log_dir").Value.Set(cfg.Logdir)
	flag.Lookup("v").Value.Set("100")

	if cfg.Port < 1 || cfg.Port > 65535 {
		glog.Fatal("Invalid port number, aborting.")
	}

	if cfg.Readtimeout < 1 || cfg.Readtimeout > 3600 {
		glog.Fatal("Invalid read timeout, aborting.")
	}

	if cfg.Writetimeout < 1 || cfg.Writetimeout > 3600 {
		glog.Fatal("Invalid write timeout, aborting.")
	}

	if cfg.Maxheaderbytes < 1 ||
		cfg.Maxheaderbytes > 2 << 40 {
		glog.Fatal("Invalid max header bytes, aborting.")
	}

	//if (!IsDir(cfg.Tempdir)) {
	//    Info.Fatal("The directory " + cfg.Tempdir +
	//        " does not exist.")
	//    os.Exit(2)
	//}

	//if (!IsDir(cfg.Filedir)) {
	//    glog.Fatal("The directory " + cfg.Filedir +
	//        " does not exist.")
	//}

	//if _, err := os.Stat(cfg.GeoIP2); err == nil {
	//    gi, err = geoip2.Open(cfg.GeoIP2)
	//    if err != nil {
	//        Info.Print("Could not open GeoIP2 database ", cfg.GeoIP2,
	//            ": ", err)
	//    }
	//    defer gi.Close()
	//} else {
	//    Info.Print("GeoIP2 database does not exist: ", cfg.GeoIP2)
	//}
}

func main() {
	// Initialize boxes
	staticBox = rice.MustFindBox("static")
	templateBox = rice.MustFindBox("templates")

	if cfg.Verbose {
		fmt.Println("Listen host: " + cfg.Host)
		fmt.Println("Listen port: " + strconv.Itoa(cfg.Port))
		fmt.Println("Read timeout: " +
			strconv.Itoa(cfg.Readtimeout) + " seconds")
		fmt.Println("Write timeout: " +
			strconv.Itoa(cfg.Writetimeout) + " seconds")
		fmt.Println("Max header size: " +
			strconv.Itoa(cfg.Maxheaderbytes) + " bytes")
		fmt.Println("Expiration time: " + strconv.FormatInt(cfg.Expiration, 10) +
			" seconds")
		fmt.Println("Files directory: " + cfg.Filedir)
		//fmt.Println("Thumbnail directory: " + cfg.Thumbdir)
		fmt.Println("Temp directory: " + cfg.Tempdir)
		fmt.Println("Log directory: " + cfg.Logdir)
		//fmt.Println("GeoIP2 database: " + cfg.GeoIP2)
		//fmt.Println("Pagination: " + strconv.Itoa(cfg.Pagination))
		fmt.Println("Baseurl: " + cfg.Baseurl)
		//fmt.Println("Trigger New tag: " + cfg.TriggerNewTag)

                var trigger = cfg.TriggerUploadedFile
                if trigger == "" {
                    trigger = "Not set"
                }
		fmt.Println("Trigger - Uploaded file: " + trigger)

		//fmt.Println("Trigger Expired tag: " + cfg.TriggerExpiredTag)
	}

	//err = Setup()
	//if err != nil {
	//    Error.Println("Database setup error: ", err)
	//}

	glog.Info("Filebin server starting on " + cfg.Host + ":" +
		strconv.Itoa(cfg.Port) + " from directory " +
		cfg.Filedir)

	router := mux.NewRouter()

	http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(staticBox.HTTPBox())))

	http.Handle("/", httpInterceptor(router))

	// Accept trailing slashes.
	router.StrictSlash(true)

	router.HandleFunc("/api", reqHandler(api.ViewAPI)).Methods("GET", "HEAD")
	router.HandleFunc("/doc", reqHandler(api.ViewDoc)).Methods("GET", "HEAD")
	router.HandleFunc("/", reqHandler(api.ViewIndex)).Methods("GET", "HEAD")
	router.HandleFunc("/", reqHandler(api.Upload)).Methods("POST")
	router.HandleFunc("/{tag:[A-Za-z0-9_-]+}", reqHandler(api.FetchTag)).Methods("GET", "HEAD")
	router.HandleFunc("/{tag:[A-Za-z0-9_-]+}/{filename:.+}", reqHandler(api.FetchFile)).Methods("GET", "HEAD")
	router.HandleFunc("/{tag:[A-Za-z0-9_-]+}/{filename:.+}", reqHandler(api.DeleteFile)).Methods("DELETE")

	//router.HandleFunc("/dashboard{_:/?}", ViewDashboard).Methods("GET", "HEAD")

	//router.HandleFunc("/", ViewIndex).Methods("GET", "HEAD")
	//router.HandleFunc("/upload{_:/?}", RedirectToNewTag).Methods("GET", "HEAD")
	//router.HandleFunc("/upload/{tag:[A-Za-z0-9_-]+}", RedirectOldTag)

	//router.HandleFunc("/{tag:[A-Za-z0-9_-]+}/page/{page:[0-9]+}{_:/?}",
	//    ViewTag).Methods("GET", "HEAD")
	//router.HandleFunc("/{tag:[A-Za-z0-9_-]+}{_:/?}", ViewTag).Methods("GET", "HEAD")

	//router.HandleFunc("/user{_:/?}", user.GetHomePage).Methods("GET")
	//router.HandleFunc("/user/view/{id:[0-9]+}", user.GetViewPage).Methods("GET")
	//router.HandleFunc("/user/{id:[0-9]+}", user.GetViewPage).Methods("GET")

	//// CSS and Javascript
	//fileServer := http.StripPrefix("/static/",
	//    http.FileServer(http.Dir("static")))
	//http.Handle("/static/", fileServer)

	err := http.ListenAndServe(cfg.Host + ":" +
		strconv.Itoa(cfg.Port), nil)

	if err != nil {
		glog.Fatal(err.Error())
	}
}

func reqHandler(fn func (http.ResponseWriter, *http.Request, config.Configuration, model.Context)) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		startTime := time.Now().UTC()

		//var req = ParseRequest(r)

		glog.Info("Request from " + r.RemoteAddr)
		glog.Info(r.Method + " " + r.RequestURI)
		//ReqId := generateReqId(16)
		//glog.Info("ReqId:", ReqId)

		// Populate the context for this request here
		var ctx = model.Context {}
		ctx.TemplateBox = templateBox
		ctx.StaticBox = staticBox
		ctx.Baseurl = cfg.Baseurl

		fn(w, r, cfg, ctx)

		finishTime := time.Now().UTC()
		elapsedTime := finishTime.Sub(startTime)

		//log.Info("Status " + w.Status)
		glog.Info("Processing time: " + elapsedTime.String())
		glog.Flush()
	}
}

func httpInterceptor(router http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		router.ServeHTTP(w, r)
	})
}

<|endoftext|>