func (fs *FileSession) pushHandler(incomingPacket packet.PacketStd) { fmt.Println("processing push") //getting pushList from socket incomingBytes, _ := strconv.Atoi(incomingPacket.Data) pushListB := make([]byte, incomingBytes) i := 0 for i < incomingBytes { chunkSize, _ := fs.Connection.Read(pushListB[i:]) i = i + chunkSize fmt.Println("read so far: ", i) } //unmarshal data from socket to PacketList instance var client_pushList packet.PacketList client_pushList.ContentType = "push" client_pushList.Name = "client" flsize, _ := strconv.Atoi(incomingPacket.Name) flObj := make([]packet.PacketStd, flsize) client_pushList.Data = flObj error := json.Unmarshal(pushListB, &client_pushList) if error == nil { fmt.Println("push recieved, " + incomingPacket.Name + " entries\n") } else { fmt.Println(error.Error()) } //tells client push was recieved newPacket := packet.PacketStd{packet.Packet{"push", ""}, "PUSH_RECIEVED"} go newPacket.SendPacket(fs.Connection) //PacketList instance for server files(db) var server_fileList packet.PacketList db, error := sql.Open("sqlite3", "../gypo.db") if error != nil { fmt.Println(error.Error()) } else { //get number of files from db to use for file array size var dbFileCount int error = db.QueryRow("SELECT count(*) AS number FROM files WHERE user_id = ?", fs.User.Id).Scan(&dbFileCount) if error != nil { fmt.Println(error.Error()) } else { server_fileList.Data = make([]packet.PacketStd, dbFileCount) //fetches files from db and adds them to server_fileList rows, error := db.Query("SELECT filename, path, hash, is_dir FROM files WHERE user_id = ?", fs.User.Id) if error != nil { fmt.Println(error.Error()) } else { var is_dir int var rowContentType, rowName, rowData string var rowPacket packet.PacketStd //populates server_fileList.Data i = 0 for rows.Next() { error = rows.Scan(&rowContentType, &rowName, &rowData, &is_dir) //fmt.Println(i, " | ", is_dir) if error != nil { fmt.Println(error.Error()) } if is_dir == 1 { rowPacket.ContentType = "folder" rowPacket.Name = rowName rowPacket.Data = "" } else { rowPacket.ContentType = "hash" rowPacket.Name = rowName + rowContentType rowPacket.Data = rowData } server_fileList.Data[i] = rowPacket i++ } fmt.Println("server_fileList size: ", len(server_fileList.Data)) fmt.Println("client_pushList size: ", len(client_pushList.Data)) /* i = 0 for i < len(server_fileList.Data) { fmt.Println("ContentType: " + server_fileList.Data[i].ContentType + " | Name: " + server_fileList.Data[i].Name + " | Data: " + server_fileList.Data[i].Data) i++ } fmt.Println("\n\n\n\n") i = 0 for i < len(client_pushList.Data) { fmt.Println("ContentType: " + client_pushList.Data[i].ContentType + " | Name: " + client_pushList.Data[i].Name + " | Data: " + server_fileList.Data[i].Data) i++ }*/ //compares client_pushList to server_fileList nilPacket := packet.PacketStd{packet.Packet{"", ""}, ""} //to flag list entries as solved i = 0 j := 0 for i < len(client_pushList.Data) { //check if i is allready solved if len(client_pushList.Data[i].ContentType) > 0 { for j < len(server_fileList.Data) { //file if client_pushList.Data[i].ContentType == "hash" { //match if client_pushList.Data[i].Name == server_fileList.Data[j].Name { //update file if needed if client_pushList.Data[i].Data != server_fileList.Data[j].Data { client_pushList.Data[i].Data = "1" + client_pushList.Data[i].Data //adds '1' to indicate UPDATE(existing file) fs.tempHash[client_pushList.Data[i].Name] = client_pushList.Data[i] fmt.Println("hash for: " + client_pushList.Data[i].Name + " added to tempHash") //fmt.Println("path and filename the same, different hash | client: " + client_pushList.Data[i].Data + " server: " + server_fileList.Data[j].Data) newPacket := packet.PacketStd{packet.Packet{"hash", client_pushList.Data[i].Name}, "SEND_FILE_TRUE"} go newPacket.SendPacket(fs.Connection) fmt.Println(client_pushList.Data[i].Name + " exist, different hash, send\n") //flag list entries as solved client_pushList.Data[i] = nilPacket server_fileList.Data[j] = nilPacket } else { //files are identical, flag list entries as solved client_pushList.Data[i] = nilPacket server_fileList.Data[j] = nilPacket } } //path } else if client_pushList.Data[i].ContentType == "folder" { //match if client_pushList.Data[i].Name == server_fileList.Data[j].Name { //if both paths exist on server and client, flag list entries as solved client_pushList.Data[i] = nilPacket server_fileList.Data[j] = nilPacket } } j++ //increase server_fileList index } } j = 0 //resets server_fileList index i++ //increase client_pushList index } //client_pushList entries not flagged as handled are treated as new files and folders and will be downloaded an/or created i = 0 for i < len(client_pushList.Data) { if client_pushList.Data[i].ContentType == "hash" { //file //adds hash to tempHash, if file recieve is successful; tempHash is dumped to db client_pushList.Data[i].Data = "0" + client_pushList.Data[i].Data //adds '0' to indicate INSERT(new file) fs.tempHash[client_pushList.Data[i].Name] = client_pushList.Data[i] fmt.Println("hash for: " + client_pushList.Data[i].Name + " added to tempHash") newPacket := packet.PacketStd{packet.Packet{"hash", client_pushList.Data[i].Name}, "SEND_FILE_TRUE"} go newPacket.SendPacket(fs.Connection) fmt.Println(client_pushList.Data[i].Name + " not exist, send\n") //flag list entry as solved client_pushList.Data[i] = nilPacket } else if client_pushList.Data[i].ContentType == "folder" { //folder error = os.MkdirAll(client_pushList.Data[i].Name[1:], 07777) //liberal chmod if error != nil { fmt.Println(error.Error()) //adds folder to db } else { _, error := db.Exec("INSERT INTO files (path, is_dir, user_id) VALUES (?, ?, ?)", client_pushList.Data[i].Name, 1, fs.User.Id) if error != nil { fmt.Println(error.Error()) } else { fmt.Println("folder: " + client_pushList.Data[i].Name + " created and added to db") } } } i++ } fmt.Println("tempHash size: ", len(fs.tempHash)) //server_fileList entries not flagged as handled are threated as deleted files and gets deleted i = 0 for i < len(server_fileList.Data) { if server_fileList.Data[i].ContentType == "hash" { //file //delete db entry _, error := db.Exec("DELETE FROM files WHERE path = ? AND hash = ? AND user_id = ?", server_fileList.Data[i].Name[:strings.LastIndex(server_fileList.Data[i].Name, "/")+1], server_fileList.Data[i].Data, fs.User.Id) if error != nil { fmt.Println(error.Error()) } else { //delete file _ = os.RemoveAll(fs.RootDir + server_fileList.Data[i].Name) /*if error != nil { fmt.Println(error.Error()) }*/ } //flag list entry as solved server_fileList.Data[i] = nilPacket } else if server_fileList.Data[i].ContentType == "folder" { //delete db entry _, error := db.Exec("DELETE FROM files WHERE path = ? AND is_dir = ? AND user_id = ?", server_fileList.Data[i].Name, 1, fs.User.Id) if error != nil { fmt.Println(error.Error()) } else { //delete folder _ = os.RemoveAll(fs.RootDir + server_fileList.Data[i].Name) /*if error != nil { fmt.Println(error.Error()) }*/ } //flag list entry as solved server_fileList.Data[i] = nilPacket } i++ } } } } }
func (fs *FileSession) pullHandler(incomingPacket packet.PacketStd) { if incomingPacket.Name == "REQ_FILELIST" { //db initializing db, error := sql.Open("sqlite3", "../gypo.db") //tells client pull request recieved newPacket := packet.PacketStd{packet.Packet{"pull", "REQ_FILELIST_RECV"}, ""} go newPacket.SendPacket(fs.Connection) //creates list of server files and sends back to client if error != nil { fmt.Println(error.Error()) } else { //PacketList instance for server files(db) var server_fileList packet.PacketList //get number of files from db to use for file server_fileList.Data size var dbFileCount int error = db.QueryRow("SELECT count(*) AS number FROM files WHERE user_id = ?", fs.User.Id).Scan(&dbFileCount) if error != nil { fmt.Println(error.Error()) } else { //sets PacketList instance variables server_fileList.Data = make([]packet.PacketStd, dbFileCount) server_fileList.ContentType = "pull" server_fileList.Name = "RESP_FILELIST" //get fileList from db rows, error := db.Query("SELECT filename, path, hash, is_dir FROM files WHERE user_id = ?", fs.User.Id) if error != nil { fmt.Println(error.Error()) } else { var rowPacket packet.PacketStd var filename, path, hash string var is_dir int i := 0 for rows.Next() { error = rows.Scan(&filename, &path, &hash, &is_dir) if error != nil { fmt.Println(error.Error()) } else { if is_dir == 1 { rowPacket.ContentType = "folder" rowPacket.Name = path rowPacket.Data = "" } else { rowPacket.ContentType = "hash" rowPacket.Name = path + filename rowPacket.Data = hash } } server_fileList.Data[i] = rowPacket i++ } go server_fileList.SendPacket(fs.Connection) fmt.Println("server_fileList size: ", len(server_fileList.Data)) } } } } else if incomingPacket.Name == "REQ_FILE" { //wraps file in packet and sends it newPacket := packet.PacketStd{packet.Packet{"pull", "RESP_FILE"}, incomingPacket.Data} go newPacket.SendFilePacket(fs.Connection) } }
func (ws WebServer) handler(w http.ResponseWriter, r *http.Request) { var currentSessionCookie *http.Cookie var error error var html []byte //respons data array //check cookie for auth currentSessionCookie, error = r.Cookie("gypoSession") //if /login requests if r.URL.Path[1:] == "login" { //respons packet var newPacket packet.PacketStd //if no cookie, authentiate if error != nil { newWebSession := session.WebSession{} newWebSession.User = user.User{-1} newWebSession.RootDir = ws.RootDir newWebSession.SessionChan = ws.SessionsChan var loginCode int var loginCodeStr string //authenticates form input loginCode = newWebSession.WebSession_Authenticate(r.FormValue("username"), r.FormValue("password")) loginCodeStr = strconv.Itoa(loginCode) //makes respons packets from loginCode return value if loginCode < 0 { //not success newPacket = packet.PacketStd{packet.Packet{"text", "loginCode"}, loginCodeStr} } else { //succes newPacket = packet.PacketStd{packet.Packet{"text", "loginCode"}, loginCodeStr} newWebSession.User.Id = loginCode //sets client cookie newSessionCookie := &http.Cookie{Name: "gypoSession", Value: strconv.Itoa(newWebSession.User.Id), Domain: ".localhost.com", Expires: time.Now().AddDate(0, 0, 1)} //expires in 24h - time.Now().Add(120*60*1000) http.SetCookie(w, newSessionCookie) } //if cookie, prolong expiration } else { newSessionCookie := &http.Cookie{Name: "gypoSession", Value: currentSessionCookie.Value, Domain: ".localhost.com", Expires: time.Now().AddDate(0, 0, 1)} //expires in 24h - time.Now().Add(120*60*1000) http.SetCookie(w, newSessionCookie) } //writes response packets to client with json html, _ = json.Marshal(newPacket) w.Header().Set("Content-Type", "application/json") //everything but /login } else { //if currentSessionCookie missing, no auth if error != nil { if r.URL.Path == "/" || r.URL.Path == "" || r.URL.Path == "/favicon.ico" { //Browsers automatically request the favicon.ico file by default when you issue a request for a web page. The favicon.ico file is the small icon that appears in the URL bar of your browser. //trys to load login for client html, error = ws.loadPage("index") if error != nil { html = []byte("could not load index") } } else { html = []byte("you need to login first") } } else { //refreshes cookie newSessionCookie := &http.Cookie{Name: "gypoSession", Value: currentSessionCookie.Value, Domain: ".localhost.com", Expires: time.Now().AddDate(0, 0, 1)} //expires in 24h - time.Now().Add(120*60*1000) http.SetCookie(w, newSessionCookie) userId, _ := strconv.Atoi(currentSessionCookie.Value) //redirects to overview as auth is ok if r.URL.Path == "/" || r.URL.Path == "" || r.URL.Path == "/favicon.ico" { //trys to load login for client html, error = ws.loadPage("overview") if error != nil { html = []byte("could not load overview") } //overview jason } else if r.URL.Path[1:] == "getOverview" { db, error := sql.Open("sqlite3", ws.RootDir+"/gypo.db") if error != nil { html = []byte(error.Error()) } else { //get number of files to populate fileList array var dbFileCount int error = db.QueryRow("SELECT count(*) AS number FROM files WHERE user_id = ?", userId).Scan(&dbFileCount) if error != nil { html = []byte(error.Error()) } else { rows, error := db.Query("SELECT id, filename, path, is_dir FROM files WHERE user_id = ? ", userId) if error != nil { html = []byte(error.Error()) } else { var id int var filename, path string var is_dir bool var fileList packet.PacketList var file packet.PacketStd //set array size fileList.ContentType = "json" fileList.Name = "fileList" fileList.Data = make([]packet.PacketStd, dbFileCount) //populate array with file objects i := 0 for rows.Next() { error = rows.Scan(&id, &filename, &path, &is_dir) if error != nil { file = packet.PacketStd{packet.Packet{"file", "error"}, error.Error()} } else { if is_dir == true { file = packet.PacketStd{packet.Packet{"folder", path}, strconv.Itoa(id)} } else { mimeStr := mime.TypeByExtension(strings.ToLower(filename[strings.LastIndex(filename, "."):])) //to lower case to ensure equal parse file = packet.PacketStd{packet.Packet{"file|" + mimeStr, path + "|" + filename}, strconv.Itoa(id)} } } fileList.Data[i] = file i++ } //marshals fileList to json and sets proper content-type header html, _ = json.Marshal(fileList) w.Header().Set("Content-Type", "application/json") } db.Close() } } } else if strings.Index(r.URL.Path, "getFile") == 1 { db, error := sql.Open("sqlite3", ws.RootDir+"/gypo.db") defer db.Close() if error != nil { html = []byte(error.Error()) } else { var path, filename string fileId, _ := strconv.Atoi(r.URL.RawQuery[strings.Index(r.URL.RawQuery, "=")+1:]) error = db.QueryRow("SELECT path, filename number FROM files WHERE id = ?", fileId).Scan(&path, &filename) if error != nil { html = []byte(error.Error()) } else { pathfile := ws.RootDir + "/user-" + strconv.Itoa(userId) + path + filename file, error := os.Open(pathfile) if error != nil { html = []byte(error.Error()) } else { defer file.Close() //get filesize fi, _ := file.Stat() fileSize := int(fi.Size()) //reads file and writes it to buffer array html = make([]byte, fileSize) bytesWritten := 0 i := 0 fmt.Println("File to be written: " + fi.Name() + " | size: " + strconv.Itoa(fileSize)) //set headers accoring to file mimeStr := mime.TypeByExtension(filename[strings.LastIndex(filename, "."):]) fmt.Println("setting content-type: " + mimeStr) w.Header().Set("Content-Type", mimeStr) w.Header().Set("Content-Length", strconv.Itoa(fileSize)) w.Header().Set("Content-Disposition", "attachment; filename="+filename) for bytesWritten < fileSize && error == nil { i, error = file.Read(html[bytesWritten:]) if error != nil { html = []byte(error.Error()) } else { bytesWritten = bytesWritten + i } } } } } } else if strings.Index(r.URL.Path, "getImage") == 1 { fmt.Println("getImage") db, error := sql.Open("sqlite3", ws.RootDir+"/gypo.db") defer db.Close() if error != nil { html = []byte(error.Error()) } else { var path, filename string if strings.Index(r.URL.RawQuery, "&width=") == -1 || strings.Index(r.URL.RawQuery, "id=") == -1 { html = []byte("bad url") } else { fileId, error := strconv.Atoi(r.URL.RawQuery[strings.Index(r.URL.RawQuery, "id=")+3 : strings.Index(r.URL.RawQuery, "&width=")]) if error != nil { html = []byte(error.Error()) } else { error = db.QueryRow("SELECT path, filename number FROM files WHERE id = ?", fileId).Scan(&path, &filename) if error != nil { html = []byte(error.Error()) } else { pathfile := ws.RootDir + "/user-" + strconv.Itoa(userId) + path + filename image, error := magick.NewFromFile(pathfile) if error != nil { html = []byte(error.Error()) } else { defer image.Destroy() //if image wider than 50 % of screen; resize screenWidth, _ := strconv.Atoi(r.URL.RawQuery[strings.LastIndex(r.URL.RawQuery, "=")+1:]) var resizeFactor float32 resizeFactor = float32(screenWidth) * 50.0 / 100.0 if int(resizeFactor) < image.Width() { resizeFactor = resizeFactor / float32(image.Width()) error = image.Resize(strconv.Itoa(int(float32(image.Width())*resizeFactor)) + "x" + strconv.Itoa(int(float32(image.Height())*resizeFactor))) if error != nil { fmt.Println(error.Error()) } else { fmt.Println("image resized: " + filename) } fmt.Println("resizeFactor: ", resizeFactor) } if error != nil { html = []byte(error.Error()) } else { //reads image and writes it to buffer array html, error = image.ToBlob(filename[strings.LastIndex(filename, "."):]) if error != nil { html = []byte(error.Error()) fmt.Println(error.Error()) } else { //set headers according to file mimeStr := mime.TypeByExtension(filename[strings.LastIndex(filename, "."):]) fmt.Println("setting content-type: " + mimeStr) w.Header().Set("Content-Type", mimeStr) w.Header().Set("Content-Length", strconv.Itoa(len(html))) w.Header().Set("Content-Disposition", "inline; filename="+filename) fmt.Println("image sent, size: ", len(html), "\n") } } } } } } } } else { //unknown query html, error = ws.loadPage(r.URL.Path[1:]) if error != nil { html = []byte("could not find page") } } } } //writes output to client j, error := w.Write(html) if error != nil { fmt.Println(error.Error()) } else { fmt.Println("WebServer | bytes written: ", j) //writes amount written to client } }