Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions Projects/CyberGuys/cyberduck-clone-project/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Cyberduck Clone Project
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.

## Project Overview
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.

<img src="https://github.com/buraxta/cyberduck-clone-project/blob/master/Untitled.jpg?raw=true" />

## Technologies Used
### Frontend
- Next.js
- TypeScript
### Backend
- Flask (Python)
- Linux SSH Server
### How It Works
1. <b>Frontend Requests:</b> The web interface allows users to initiate file transfer requests.
2. <b>Backend Processing:</b> Requests from the frontend are processed by a Flask server.
2. <b>File Transfer:</b> The Flask server interacts with an SSH server installed on a Linux machine to perform file transfer operations.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
37 changes: 37 additions & 0 deletions Projects/CyberGuys/cyberduck-clone-project/app/api/images/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { NextRequest, NextResponse } from "next/server";
import { promises as fs } from "fs";
import path from "path";

export async function POST(req: NextRequest) {
try {
const formData = await req.formData();
const file = formData.get("file") as File;

if (!file || typeof file === "string") {
return NextResponse.json(
{ message: "No file uploaded" },
{ status: 400 }
);
}

const arrayBuffer = await file.arrayBuffer();
const buffer = Buffer.from(arrayBuffer);

const newImagesDir = path.join(process.cwd(), "newImages");
const filePath = path.join(newImagesDir, file.name);

await fs.mkdir(newImagesDir, { recursive: true });

await fs.writeFile(filePath, buffer);

return NextResponse.json({
message: "Image uploaded and saved successfully!",
});
} catch (error) {
console.error("Error:", error);
return NextResponse.json(
{ message: "Error uploading file" },
{ status: 500 }
);
}
}
Binary file not shown.
76 changes: 76 additions & 0 deletions Projects/CyberGuys/cyberduck-clone-project/app/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;

--card: 0 0% 100%;
--card-foreground: 222.2 84% 4.9%;

--popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%;

--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;

--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;

--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;

--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;

--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;

--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--ring: 222.2 84% 4.9%;

--radius: 0.5rem;
}

.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;

--card: 222.2 84% 4.9%;
--card-foreground: 210 40% 98%;

--popover: 222.2 84% 4.9%;
--popover-foreground: 210 40% 98%;

--primary: 210 40% 98%;
--primary-foreground: 222.2 47.4% 11.2%;

--secondary: 217.2 32.6% 17.5%;
--secondary-foreground: 210 40% 98%;

--muted: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%;

--accent: 217.2 32.6% 17.5%;
--accent-foreground: 210 40% 98%;

--destructive: 0 62.8% 30.6%;
--destructive-foreground: 210 40% 98%;

--border: 217.2 32.6% 17.5%;
--input: 217.2 32.6% 17.5%;
--ring: 212.7 26.8% 83.9%;
}
}

@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}
26 changes: 26 additions & 0 deletions Projects/CyberGuys/cyberduck-clone-project/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import Menu from "@/components/menu";

const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};

export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body className={inter.className}>
<Menu />
{children}
</body>
</html>
);
}
128 changes: 128 additions & 0 deletions Projects/CyberGuys/cyberduck-clone-project/app/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
"use client";
import Footer from "@/components/footer";
import Header from "@/components/header";
import { SubHeader } from "@/components/subheader";
import { Button } from "@/components/ui/button";
import { redirect } from "next/navigation";
import { useEffect, useState } from "react";

export default function Home() {
const [files, setFiles] = useState([]);
const [selected, setSelected] = useState(150);

useEffect(() => {
const fetchFiles = async () => {
try {
const response = await fetch("http://127.0.0.1:5000/getfiles");
if (!response.ok) {
throw new Error("Network response was not ok");
}
const data = await response.json();
setFiles(data.files); // Gelen dosyaları state'e kaydet
} catch (error) {
console.error("Error fetching files:", error);
}
};

fetchFiles();
}, []);

const handleSubmit = async (event) => {
event.preventDefault();

try {
const response = await fetch("http://127.0.0.1:5000/download", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ id: selected }),
});

if (!response.ok) {
throw new Error("Network response was not ok");
}

const blob = await response.blob();
const url = window.URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = files[selected];
document.body.appendChild(a);
a.click();
a.remove();
} catch (error) {
console.error("Error downloading file:", error);
}
};

const handleDelete = async () => {
try {
const response = await fetch("http://127.0.0.1:5000/delete", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ id: selected }),
});

if (!response.ok) {
throw new Error("Network response was not ok");
}

const result = await response.json();
if (result.success) {
// Dosya başarıyla silindiyse dosyaları yeniden yükle
setFiles(files.filter((_, index) => index !== selected));
setSelected(null);
} else {
console.error("Error deleting file:", result.error);
}
} catch (error) {
console.error("Error deleting file:", error);
}
};

return (
<div className="relative h-[95vh]">
<Header />
<SubHeader />
<div className="ml-5 mt-5">
<table className="">
<thead>
<tr>
<th className="">id</th>
<th className=" flex justify-start ml-5">File Name</th>
</tr>
</thead>
<tbody>
{files.map((file, index) => (
<tr
key={index}
className={`hover:bg-slate-200 cursor-pointer ${
selected === index ? "bg-slate-200" : ""
}`}
onClick={() => {
setSelected(index);
console.log(index);
}}
>
<td className="">{index}</td>
<td className="pl-5">{file}</td>
</tr>
))}
</tbody>
</table>
<div>
<Button className="mt-5 " onClick={handleSubmit}>
Request File
</Button>
<Button className="ml-5" variant="destructive" onClick={handleDelete}>
Delete
</Button>
</div>
</div>
<Footer />
</div>
);
}
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"your credentials file"
Loading