Skip to content

Commit 96c89de

Browse files
authored
Merge pull request #138 from yavuzserdogan/master
Add CyburGuys project
2 parents 6fb7cb7 + 32cfd56 commit 96c89de

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+7542
-0
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Cyberduck Clone Project
2+
This project aims to create a web version of the popular Cyberduck application as part of a university project. Our team worked collaboratively to build this project, focusing on both the frontend and backend components.
3+
4+
## Project Overview
5+
The Cyberduck Clone Project is designed to replicate the core functionalities of Cyberduck, a well-known file transfer application. Due to time constraints, we have implemented essential features primarily on the backend, with limited functionalities on the frontend.
6+
7+
<img src="https://github.com/buraxta/cyberduck-clone-project/blob/master/Untitled.jpg?raw=true" />
8+
9+
## Technologies Used
10+
### Frontend
11+
- Next.js
12+
- TypeScript
13+
### Backend
14+
- Flask (Python)
15+
- Linux SSH Server
16+
### How It Works
17+
1. <b>Frontend Requests:</b> The web interface allows users to initiate file transfer requests.
18+
2. <b>Backend Processing:</b> Requests from the frontend are processed by a Flask server.
19+
2. <b>File Transfer:</b> The Flask server interacts with an SSH server installed on a Linux machine to perform file transfer operations.
118 KB
Loading
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { NextRequest, NextResponse } from "next/server";
2+
import { promises as fs } from "fs";
3+
import path from "path";
4+
5+
export async function POST(req: NextRequest) {
6+
try {
7+
const formData = await req.formData();
8+
const file = formData.get("file") as File;
9+
10+
if (!file || typeof file === "string") {
11+
return NextResponse.json(
12+
{ message: "No file uploaded" },
13+
{ status: 400 }
14+
);
15+
}
16+
17+
const arrayBuffer = await file.arrayBuffer();
18+
const buffer = Buffer.from(arrayBuffer);
19+
20+
const newImagesDir = path.join(process.cwd(), "newImages");
21+
const filePath = path.join(newImagesDir, file.name);
22+
23+
await fs.mkdir(newImagesDir, { recursive: true });
24+
25+
await fs.writeFile(filePath, buffer);
26+
27+
return NextResponse.json({
28+
message: "Image uploaded and saved successfully!",
29+
});
30+
} catch (error) {
31+
console.error("Error:", error);
32+
return NextResponse.json(
33+
{ message: "Error uploading file" },
34+
{ status: 500 }
35+
);
36+
}
37+
}
25.3 KB
Binary file not shown.
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
@tailwind base;
2+
@tailwind components;
3+
@tailwind utilities;
4+
5+
@layer base {
6+
:root {
7+
--background: 0 0% 100%;
8+
--foreground: 222.2 84% 4.9%;
9+
10+
--card: 0 0% 100%;
11+
--card-foreground: 222.2 84% 4.9%;
12+
13+
--popover: 0 0% 100%;
14+
--popover-foreground: 222.2 84% 4.9%;
15+
16+
--primary: 222.2 47.4% 11.2%;
17+
--primary-foreground: 210 40% 98%;
18+
19+
--secondary: 210 40% 96.1%;
20+
--secondary-foreground: 222.2 47.4% 11.2%;
21+
22+
--muted: 210 40% 96.1%;
23+
--muted-foreground: 215.4 16.3% 46.9%;
24+
25+
--accent: 210 40% 96.1%;
26+
--accent-foreground: 222.2 47.4% 11.2%;
27+
28+
--destructive: 0 84.2% 60.2%;
29+
--destructive-foreground: 210 40% 98%;
30+
31+
--border: 214.3 31.8% 91.4%;
32+
--input: 214.3 31.8% 91.4%;
33+
--ring: 222.2 84% 4.9%;
34+
35+
--radius: 0.5rem;
36+
}
37+
38+
.dark {
39+
--background: 222.2 84% 4.9%;
40+
--foreground: 210 40% 98%;
41+
42+
--card: 222.2 84% 4.9%;
43+
--card-foreground: 210 40% 98%;
44+
45+
--popover: 222.2 84% 4.9%;
46+
--popover-foreground: 210 40% 98%;
47+
48+
--primary: 210 40% 98%;
49+
--primary-foreground: 222.2 47.4% 11.2%;
50+
51+
--secondary: 217.2 32.6% 17.5%;
52+
--secondary-foreground: 210 40% 98%;
53+
54+
--muted: 217.2 32.6% 17.5%;
55+
--muted-foreground: 215 20.2% 65.1%;
56+
57+
--accent: 217.2 32.6% 17.5%;
58+
--accent-foreground: 210 40% 98%;
59+
60+
--destructive: 0 62.8% 30.6%;
61+
--destructive-foreground: 210 40% 98%;
62+
63+
--border: 217.2 32.6% 17.5%;
64+
--input: 217.2 32.6% 17.5%;
65+
--ring: 212.7 26.8% 83.9%;
66+
}
67+
}
68+
69+
@layer base {
70+
* {
71+
@apply border-border;
72+
}
73+
body {
74+
@apply bg-background text-foreground;
75+
}
76+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import type { Metadata } from "next";
2+
import { Inter } from "next/font/google";
3+
import "./globals.css";
4+
import Menu from "@/components/menu";
5+
6+
const inter = Inter({ subsets: ["latin"] });
7+
8+
export const metadata: Metadata = {
9+
title: "Create Next App",
10+
description: "Generated by create next app",
11+
};
12+
13+
export default function RootLayout({
14+
children,
15+
}: Readonly<{
16+
children: React.ReactNode;
17+
}>) {
18+
return (
19+
<html lang="en">
20+
<body className={inter.className}>
21+
<Menu />
22+
{children}
23+
</body>
24+
</html>
25+
);
26+
}
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
"use client";
2+
import Footer from "@/components/footer";
3+
import Header from "@/components/header";
4+
import { SubHeader } from "@/components/subheader";
5+
import { Button } from "@/components/ui/button";
6+
import { redirect } from "next/navigation";
7+
import { useEffect, useState } from "react";
8+
9+
export default function Home() {
10+
const [files, setFiles] = useState([]);
11+
const [selected, setSelected] = useState(150);
12+
13+
useEffect(() => {
14+
const fetchFiles = async () => {
15+
try {
16+
const response = await fetch("http://127.0.0.1:5000/getfiles");
17+
if (!response.ok) {
18+
throw new Error("Network response was not ok");
19+
}
20+
const data = await response.json();
21+
setFiles(data.files); // Gelen dosyaları state'e kaydet
22+
} catch (error) {
23+
console.error("Error fetching files:", error);
24+
}
25+
};
26+
27+
fetchFiles();
28+
}, []);
29+
30+
const handleSubmit = async (event) => {
31+
event.preventDefault();
32+
33+
try {
34+
const response = await fetch("http://127.0.0.1:5000/download", {
35+
method: "POST",
36+
headers: {
37+
"Content-Type": "application/json",
38+
},
39+
body: JSON.stringify({ id: selected }),
40+
});
41+
42+
if (!response.ok) {
43+
throw new Error("Network response was not ok");
44+
}
45+
46+
const blob = await response.blob();
47+
const url = window.URL.createObjectURL(blob);
48+
const a = document.createElement("a");
49+
a.href = url;
50+
a.download = files[selected];
51+
document.body.appendChild(a);
52+
a.click();
53+
a.remove();
54+
} catch (error) {
55+
console.error("Error downloading file:", error);
56+
}
57+
};
58+
59+
const handleDelete = async () => {
60+
try {
61+
const response = await fetch("http://127.0.0.1:5000/delete", {
62+
method: "POST",
63+
headers: {
64+
"Content-Type": "application/json",
65+
},
66+
body: JSON.stringify({ id: selected }),
67+
});
68+
69+
if (!response.ok) {
70+
throw new Error("Network response was not ok");
71+
}
72+
73+
const result = await response.json();
74+
if (result.success) {
75+
// Dosya başarıyla silindiyse dosyaları yeniden yükle
76+
setFiles(files.filter((_, index) => index !== selected));
77+
setSelected(null);
78+
} else {
79+
console.error("Error deleting file:", result.error);
80+
}
81+
} catch (error) {
82+
console.error("Error deleting file:", error);
83+
}
84+
};
85+
86+
return (
87+
<div className="relative h-[95vh]">
88+
<Header />
89+
<SubHeader />
90+
<div className="ml-5 mt-5">
91+
<table className="">
92+
<thead>
93+
<tr>
94+
<th className="">id</th>
95+
<th className=" flex justify-start ml-5">File Name</th>
96+
</tr>
97+
</thead>
98+
<tbody>
99+
{files.map((file, index) => (
100+
<tr
101+
key={index}
102+
className={`hover:bg-slate-200 cursor-pointer ${
103+
selected === index ? "bg-slate-200" : ""
104+
}`}
105+
onClick={() => {
106+
setSelected(index);
107+
console.log(index);
108+
}}
109+
>
110+
<td className="">{index}</td>
111+
<td className="pl-5">{file}</td>
112+
</tr>
113+
))}
114+
</tbody>
115+
</table>
116+
<div>
117+
<Button className="mt-5 " onClick={handleSubmit}>
118+
Request File
119+
</Button>
120+
<Button className="ml-5" variant="destructive" onClick={handleDelete}>
121+
Delete
122+
</Button>
123+
</div>
124+
</div>
125+
<Footer />
126+
</div>
127+
);
128+
}
2.23 KB
Binary file not shown.
1.7 KB
Binary file not shown.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"your credentials file"

0 commit comments

Comments
 (0)