728x90

php.ini 에서 extension=php_gd2.dll 가 앞에 주석처리되어 있다면 ;(주석)을 제거하고 apache 를 재시작한다.


생활코딩(https://opentutorials.org/course/62/5137) 사이트에 나온 걸 기준으로 주석을 좀 더 달았다.

<?php
header("Content-type: image/png"); // 콘텐츠의 타입을 png image 로 선언
$string = isset($_GET['text'])? $_GET['text']:'default';
$im = imagecreatefrompng("image/btn.png"); // 버튼 배경으로 사용할 이미지를 지정
$backgroundColor  = imagecolorallocate($im, 60, 87, 156); // 컬러를 지정
$px = (imagesx($im) - 7.5 * strlen($string)) / 2;
imagestring($im, 4, $px, 9, $string, $backgroundColor );
imagepng($im); // 이미지 파일 만들기
imagedestroy($im); // 정보삭제
?>


심플한 워터마크 만들기

디지털 파일에 저작자를 밝히기 위해 흐릿하게 이미지를 박아넣는 디지털 워터마크.
유료 이미지 소스 제공 사이트들에는 샘플 이미지에 모두 워터마크 처리를 한다.
샘플로 공개할 때 화질을 낮추거나 워터마크 처리를 하여 도용을 방지한다.


http://itrooms.tistory.com/304 에 나온 워터마크 코드를 용어를 좀 더 정리했다.


watermark.zip

사용법 : <img src="./watermark.php?path=image/sandal-01.png">

<?php
$ALIGN_CENTER = true;
$image_source =  $_GET['path']; // 원본 이미지 경로
$watermark_Path = './image/watermark.png'; // 워터마크 사용할 이미지
$Image_Type = strtolower(substr($image_source, strlen($image_source)-4, 4));
$watermark_Type = strtolower(substr($watermark_Path, strlen($watermark_Path)-4, 4));
if($Image_Type == '.bmp') $image = imagecreatefromwbmp($image_source);
if($Image_Type == '.gif') $image = imagecreatefromgif($image_source);
if($Image_Type == '.jpg') $image = imagecreatefromjpeg($image_source);
if($Image_Type == '.png') $image = imagecreatefrompng($image_source);
if($image) {
    if($watermark_Type == '.bmp') $watermark = imagecreatefromwbmp($watermark_Path);
    if($watermark_Type == '.gif') $watermark = imagecreatefromgif($watermark_Path);
    if($watermark_Type == '.jpg') $watermark = imagecreatefromjpeg($watermark_Path);
    if($watermark_Type == '.png') $watermark = imagecreatefrompng($watermark_Path);
    if($watermark) {
        list($imagewidth, $imageheight) = getimagesize($image_source);
        list($watermarkwidth, $watermarkheight) = getimagesize($watermark_Path);
        if($ALIGN_CENTER) { // Center
            $startwidth = (($imagewidth - $watermarkwidth)/2);
            $startheight = (($imageheight - $watermarkheight)/2);
        }
        else {
            $startwidth = ($imagewidth - $watermarkwidth);
            $startheight = ($imageheight - $watermarkheight);
        }
        imagealphablending($image, true);
        imagecopy($image, $watermark, $startwidth, $startheight, 0, 0, $watermarkwidth, $watermarkheight);
        header("Content-type: image/png");
        imagepng($image); // 이미지 파일 만들기
        imagedestroy($image);
        imagedestroy($watermark);
    }
}
// <img src="./watermark.php?path=원본이미지경로">
?>


블로그 이미지

Link2Me

,
728x90

[
    {
    "userID": 1383458400,
    "icon": "partly-cloudy-day",
    "sunriseTime": 1383491266,
    "sunsetTime": 1383523844,
    "temperatureMin": -3.46,
    "temperatureMinTime": 1383544800,
    "temperatureMax": -1.12,
    "temperatureMaxTime": 1383458400
    },
    {
    "userID": 1383458400,
    "icon": "partly-cloudy-day",
    "sunriseTime": 1383491266,
    "sunsetTime": 1383523844,
    "temperatureMin": -3.46,
    "temperatureMinTime": 1383544800,
    "temperatureMax": -1.12,
    "temperatureMaxTime": 1383458400
    }
] 



<?php
// Local JSON 파일 읽어오기

$url ='test.json';

if(!file_exists($url)) {
    echo '파일이 없습니다.';
    exit;
}

$json_string = file_get_contents($url);
$R = json_decode($json_string, true);
// json_decode : JSON 문자열을 PHP 배열로 바꾼다
// json_decode 함수의 두번째 인자를 true 로 설정하면 무조건 array로 변환된다.
// $R : array data
echo '<pre>';
print_r($R);
echo '</pre>';


// 자료 파싱처리

foreach ($R as $key => $value) {
    if (!is_array($value)) {
        echo $key . '=>' . $value . '<br/>';
    } else {
        foreach ($value as $key => $val) {
            echo $key . '=>' . $val . '<br/>';
        }
        echo '<br />';
    }
}
?>


위의 코드의 경우에는 이중 배열이므로 간단하게

foreach ($R as $row) {
    $userID= $row['userID'];
    $sunriseTime = $row['sunriseTime'];
}
로 원하는 데이터를 뽑아서 처리하면 된다.



JSON 데이터 형식이 다음과 같을 때

 { "Sample_Data" :
  [{
    "userID": 1383458400,
    "icon": "partly-cloudy-day",
    "sunriseTime": 1383491266,
    "sunsetTime": 1383523844,
    "temperatureMin": -3.46,
    "temperatureMinTime": 1383544800,
    "temperatureMax": -1.12,
    "temperatureMaxTime": 1383458400
    },
    {
    "userID": 1383458400,
    "icon": "partly-cloudy-day",
    "sunriseTime": 1383491266,
    "sunsetTime": 1383523844,
    "temperatureMin": -3.46,
    "temperatureMinTime": 1383544800,
    "temperatureMax": -1.12,
    "temperatureMaxTime": 1383458400
  }]
}


foreach ($R['Sample_Data'] as $row) {
    echo '<pre>'; print_r($row);echo '</pre>';
    echo $userID= $row['userID'].'<br />';
    echo $sunriseTime = $row['sunriseTime'].'<br />';
}


로 처리하면 해결된다.

'Web 프로그램 > JSON, 파싱 다루기' 카테고리의 다른 글

jQuery 파싱 예제  (0) 2018.12.16
PHP json_encode  (0) 2018.06.19
네이버 동네 날씨정보 파싱  (0) 2017.12.24
기상청 지역 날씨정보 파싱  (0) 2017.12.23
Parse JSON with PHP (JSON 파싱)  (2) 2017.11.27
블로그 이미지

Link2Me

,
728x90

뒤로 버튼을 두번 누르면 앱이 자동 종료되는 제대로 된 코드다.

인터넷 뒤져보면 제대로 동작하는 코드를 찾기 어렵다.

최근 앱 사용목록을 보면 종료되어 있지 않고 앱의 화면이 남이 있는 경우가 많다.

아래 코드는 최근 앱 사용목록에도 보이지 않고 종료된다.

만약 뒤로 가기 버튼 2번 누르지 않고 바로 종료하도록 하고자 한다면, appShutdown() 의 접근 제한자를 public 으로 변경하고 이 함수를 바로 호출하면 된다.


 import android.app.Activity;
import android.os.Build;
import android.widget.Toast;

public class BackPressHandler {
    private long backKeyPressedTime = 0;
    private Toast toast;

    private Activity activity;

    public BackPressHandler(Activity activity) {
        this.activity = activity;
    }

    public void onBackPressed() {

        if (isAfter2Seconds()) {
            backKeyPressedTime = System.currentTimeMillis();
            // 현재시간을 다시 초기화

            toast = Toast.makeText(activity,
                    "\'뒤로\'버튼을 한번 더 누르시면 종료됩니다.",
                    Toast.LENGTH_SHORT);
            toast.show();

            return;
        }

        if (isBefore2Seconds()) {
            appShutdown();
            toast.cancel();
        }
    }

    private Boolean isAfter2Seconds() {
        return System.currentTimeMillis() > backKeyPressedTime + 2000;
        // 2초 지났을 경우
    }

    private Boolean isBefore2Seconds() {
        return System.currentTimeMillis() <= backKeyPressedTime + 2000;
        // 2초가 지나지 않았을 경우
    }

    private void appShutdown() {
        if (Build.VERSION.SDK_INT >= 21) {
            activity.finishAndRemoveTask(); // Activity를 종료하고 최근 앱 사용 목록에서도 해당 앱을 제거
        } else {
            activity.finish();
        }
        System.runFinalization(); // 작업중인 쓰레드가 다 종료되면, 종료 시키라는 명령어
        System.exit(0); // 현재 Activity 종료
    }
}


사용법

 public class Main extends Activity {
    private BackPressHandler backPressHandler;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        backPressHandler = new BackPressHandler(this); // 뒤로 가기 버튼 이벤트

    } // onCreate End

    @Override
    public void onBackPressed() {
        backPressHandler.onBackPressed();
    }

}



블로그 이미지

Link2Me

,
728x90

jQuery 를 이용하여 input 태그명을 각각 다르게 넘기는 코드를 작성했다.

다른 코드는 동일하므로 이전 게시글(http://link2me.tistory.com/1464)을 참조하면 된다.


<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<link rel="stylesheet" type="text/css" href="write.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
function checkInput(sel,item){
    if($(sel).val().trim().length == 0){
        alert(item + ' 입력하세요');
        $(sel).focus();
        return false;
    }
    return true;
}
$(document).ready(function(){
    var maxField = 5; //최대 개수
    var wrapper = $('.append');
    var extcnt = 1; // 최초 카운트 1
    $('.add_btn').click(function(){
        if(extcnt < maxField){
            extcnt++; // 숫자 증가
            var fieldHTML = '<div><input type="text" name="ext'+extcnt+'" value="" class="input" /><a href="#" class="remove_btn"><img src="./img/remove-icon.png"/></a></div>';
            $('.append').append(fieldHTML); // Add field
            $('#extcount').html("(" + extcnt + "개)");
            $('input[name="extcnt"]').val(extcnt);
        } else {
            alert('5개까지만 추가할 수 있습니다.');
            return;
        }
    });
    $(wrapper).on('click', '.remove_btn', function(e){
        e.preventDefault();
        $(this).parent('div').remove(); // Remove field
        extcnt--; // 카운트 감소
        $('#extcount').html("(" + extcnt + "개)");
        $('input[name="extcnt"]').val(extcnt);
    });
   
    $('#submit').click(function(){
        var subject =$('input[name="subject"]');
        if(subject.val().trim().length == 0){
            alert('제목을 입력하세요');
            subject.focus();
            return false;
        }
       
        var extcnt = $("input[name='extcnt']").val();// 동적 필드 생성개수 구함
        // 동적 입력 항목 입력 여부 체크
        var i;
        for(i=1; i <= extcnt;i++){
            var sel ='input[name="ext'+i+'"]';
            var item= '내용'+i;
            if(checkInput(sel,item)==false){
                return false;
            }
        };
        form.submit();
    });

});
</script>
</head>
<body>
<?php
    $R['subject'] = isset($R['subject'])? $R['subject']:'';
    $R['kor'] = isset($R['kor'])? $R['kor']:'';
?>
<form name="writeForm" method='post' action='a.write.php'>
    <input type="hidden" name="extcnt" value="1">
    <table class="table table-bordered">
        <tr>
            <td class="td1">제목</td>
            <td><input type="text" name="subject" value="<?php echo $R['subject'];?>" class="input" /></td>
        </tr>
        <tr>
            <td class="td1">내용</td>
            <td>
                <input type="text" name="ext1" value="<?php echo $R['kor'];?>" class="input" />
                <span id="extcount" style="color: #ff0000;font: 10px verdana,dotum;">(1개)</span>
                <a href="#" class="add_btn"><img src="./img/add-icon.png"/></a>
                <div class="append"></div>
            </td>
        </tr>
        <tr>
            <td colspan='2' align='center'>
                <button type="submit" id="submit" class="button">생성</button>
            </td>
        </tr>
    </table>
</form>

</body>
</html>


블로그 이미지

Link2Me

,
728x90

Input 필드를 동적으로 추가/삭제하는 코드를 실 활용 코드 수준으로 연습하고 적어둔다.

테스트에 사용한 코드

InputAddRemovejQuery.zip




<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<link rel="stylesheet" type="text/css" href="write.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
    var maxField = 5; //최대 개수
    var wrapper = $('.append');
    var extcnt = 1; // 최초 카운트 1
    var fieldHTML = '<div><input type="text" name="ext[]" value="" class="input" /><a href="#" class="remove_btn"><img src="./img/remove-icon.png"/></a></div>';
    $('.add_btn').click(function(){
        if(extcnt < maxField){
            extcnt++; // 숫자 증가
            $('.append').append(fieldHTML); // Add field
            $('#extcount').html("(" + extcnt + "개)");
        }
    });
    $(wrapper).on('click', '.remove_btn', function(e){
        e.preventDefault();
        $(this).parent('div').remove(); // Remove field
        extcnt--; // 카운트 감소
        $('#extcount').html("(" + extcnt + "개)");
    });
});
</script>
</head>
<body>
<?php
    $R['subject'] = isset($R['subject'])? $R['subject']:'';
    $R['ext'] = isset($R['ext'])? $R['kor']:'';
?>
<form name="writeForm" method='post' action='a.write.php'>
    <input type="hidden" name="extcnt" value="0">
    <table class="table table-bordered">
        <tr>
            <td class="td1">제목</td>
            <td><input type="text" name="subject" value="<?php echo $R['subject'];?>" class="input" /></td>
        </tr>
        <tr>
            <td class="td1">내용</td>
            <td>
                <input type="text" name="ext[]" value="<?php echo $R['ext'];?>" class="input" />
                <span id="extcount" style="color: #ff0000;font: 10px verdana,dotum;">(1개)</span>
                <a href="#" class="add_btn"><img src="./img/add-icon.png"/></a>
                <div class="append"></div>
            </td>
        </tr>
        <tr>
            <td colspan='2' align='center'>
                <button type="submit" class="button">생성</button>
            </td>
        </tr>
    </table>
</form>

</body>
</html>

 /* write */
body {    
    font-family: 나눔바른고딕, NanumBarunGothic, 맑은고딕, "Malgun Gothic", 돋움, Dotum, "Apple SD Gothic Neo", sans-serif;
    font-size: 13px;
    color: rgb(33, 33, 33);
    letter-spacing: 0.03em;
}
.input {
    width:400px;
    text-indent: 5px;
    height: auto;  /* 높이값 초기화 */
    line-height : normal; /* line-height 초기화 */
    padding: .2em .3em; /* 상하 우좌 */
    font-family: inherit; /* 폰트 상속 */
    border: 1px solid #ccc; /* 999가 약간 더 진한 색 */
    margin-bottom:5px;
    font-size:12pt;
    border-radius: 3px;
    -webkit-border-radius: 3px;
    -moz-border-radius: 3px;
}
.button {
    background-color:#E9C28B;
    border: none;
    border-radius: 5px;
    padding: 10px 20px;
    text-align: center;
    text-decoration: none;
    display: inline-block;
    font-size: 16px;
    margin: 4px 2px;
    cursor: pointer
}
.title {
    font-family:inherit; /* 폰트 상속 */
    font-size: 13pt;
    color:black;
}

.td1 {
    width:60px;
    font-weight:bold;
    color:#444444;
    text-align : center;
    padding:5px 0 5px 0;
    letter-spacing:2px; /* 글자간 간격 */
}

 <?php
// $_POST 데이터 값만 확인하기 위한 코드
if(isset($_POST) && $_SERVER['REQUEST_METHOD'] == "POST"){
    // POST 방식으로 보낸 데이터가 있는지 체크
    extract($_POST);
    print '<pre>';
    print_r($_POST);
    print '</pre>';
}

?>


본 코드는 DB에서 읽어온 데이터를 화면에 표시하고, 데이터 수정, 추가, 삭제하는 로직이 반영된 코드는 아니다.

그냥 단순하게 name 을 배열로 받아서 여러개의 값이 어떻게 넘어가는지 확인하는 코드라고 보면 된다.

name 명칭이 다르게 생성하는 것은 아직 테스트 중이다.

블로그 이미지

Link2Me

,
728x90

css 를 이용하여 테이블을 미려하게 디자인해보자.

<style></style> 사이에 코드를 추가한다.


테이블 테두리를 만드는 속성

테두리는 border 속성으로 만든다.
table, th, td 요소에 적용할 수 있다. tr 요소에는 적용 안된다.


table 요소에 border를 적용하면 표 외각에 테두리가 그려진다.

table {
    width: 100%;
    border: 1px solid #dddddd; /* 테이블 외곽선이 그려진다 */
    border-collapse: collapse; /* 테두리 사이의 간격 제거 */

}


th, td 요소에 border를 적용하면 각 셀에 테두리가 생긴다.

- border와 padding은 상속하지 않는 속성이다.

th, td {
    border: 1px solid #dddddd; /* 각 셀의 외곽선 그리기 */

    padding: 10px; /* 테두리와 내용 사이의 간격 */

    text-align: center; /* 글자 가운데 정렬 */

    vertical-align: middle; /* 셀 안의 내용 세로 정렬 : top, middle, bottom */

}


세로선 없이 가로선만 보이게 하고  싶을 때
table {
  width: 100%;
  border-top: 1px solid #dddddd;
  border-collapse: collapse;
}
th, td {
  border-bottom: 1px solid #dddddd;
  padding: 10px;
}


제목 행에 배경색 추가하기

th {
  background-color: #bbdefb;
}


짝수행에 배경색 추가하기

tr 요소에 nth-child (가상클랙스) 선택자를 이용하여 배경색을 추가한다.

:nth-child는 형제 요소 중에서 규칙을 만족하는 요소를 선택할 때 사용한다.

an+b 대신에 odd을 쓰면 홀수번째 요소가, even을 적으면 짝수번째 요소가 선택된다.

- a와 b는 상수, n은 변수
- n은 정수 0, 1, 2, 3, ···

- even 대신에 2n 으로, odd 대신 2n + 1 로 해도 된다.


tbody tr:nth-child(even) {
    background-color: #f1f1f1;
}


테이블 행(row)에 마우스 올림 효과

table > tbody > tr:hover {
    background-color: #d1f1f1;
}


클랙스를 적용한 테이블 행에 마우스 올림 효과

table.YourClass tr:hover td {
    background-color: #d1f1f1;
}



'Web 프로그램 > CSS' 카테고리의 다른 글

CSS 문법  (0) 2015.03.26
CSS 기초  (0) 2015.03.16
블로그 이미지

Link2Me

,
728x90

로그인한 폰의 전화번호를 자동으로 인식하여 가져오는 코드다.

DB 에 등록된 전화번호와 로그인한 전화번호가 다른지 파악해 달라는 요청으로 검색하고 수정했다.


AndroidManifest.xml 파일에 추가할 사항

<uses-permission android:name="android.permission.READ_PHONE_STATE" />


전화번호 자동 읽어오기 코드

@SuppressLint("MissingPermission")
public String getPhoneNumber() {
    TelephonyManager telephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
    String phoneNumber = "";
    try {
        if (telephony.getLine1Number() != null) {
            phoneNumber = telephony.getLine1Number();
        } else {
            if (telephony.getSimSerialNumber() != null) {
                phoneNumber = telephony.getSimSerialNumber();
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

    if (phoneNumber.startsWith("+82")) {
        phoneNumber = phoneNumber.replace("+82", "0");
// +8210xxxxyyyy 로 시작되는 번호

    }
    //phoneNumber = phoneNumber.substring(phoneNumber.length()-10,phoneNumber.length());
    //phoneNumber="0"+phoneNumber;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        phoneNumber = PhoneNumberUtils.formatNumber(phoneNumber, Locale.getDefault().getCountry());
    } else {
        phoneNumber = PhoneNumberUtils.formatNumber(phoneNumber);
    }
    return phoneNumber;
}



2020.3.26 Update

코틀린에서 전화번호 읽어오는 함수로 변환했더니 아래와 같은 결과를 반환했다.

fun getPhoneNumber(): String {
    val telephony =
        getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
    var phoneNumber = ""
    try {
        if (ActivityCompat.checkSelfPermission(
                this,
                Manifest.permission.READ_SMS
            ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
                this,
                Manifest.permission.READ_PHONE_NUMBERS
            ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
                this,
                Manifest.permission.READ_PHONE_STATE
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            return ""
        }
        if (telephony.line1Number != null) {
            phoneNumber = telephony.line1Number
        } else {
            if (telephony.simSerialNumber != null) {
                phoneNumber = telephony.simSerialNumber
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
    if (phoneNumber.startsWith("+82")) {
        phoneNumber = phoneNumber.replace("+82", "0")
    }
    phoneNumber = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        PhoneNumberUtils.formatNumber(
            phoneNumber,
            Locale.getDefault().country
        )
    } else {
        PhoneNumberUtils.formatNumber(phoneNumber)
    }
    return phoneNumber
}


블로그 이미지

Link2Me

,
728x90

네이버스마트 에디터를 이용하여 게시판을 만들어보려고 하니 XSS 대한 공부를 해야 할 거 같다.


크로스 사이트 스크립트란
사이트 간 스크립팅(또는 크로스 사이트 스크립팅, 영문 명칭 cross-site scripting, 영문 약어 XSS)은 웹 애플리케이션에서 많이 나타나는 취약점의 하나로 웹 페이지에 악성 스크립트를 삽입할 수 있는 취약점이다.
주로 여러 사용자가 보게 되는 게시판에 악성 스크립트가 담긴 글을 올리는 형태로 이루어진다.
이 취약점은 웹 애플리케이션이 사용자로부터 입력 받은 값을 제대로 검사하지 않고 사용할 경우 나타난다.
이 취약점으로 해커가 사용자의 정보(쿠키, 세션 등)를 탈취하거나, 자동으로 비정상적인 기능을 수행할 수 있다.
주로 다른 웹사이트와 정보를 교환하는 식으로 작동하므로 사이트 간 스크립팅이라고 한다.



기능을 테스트한 걸 적어둔다. 아직 완벽하게 다 기능 구현을 이해 못한거 같다.

구글링해서 찾은 코드와 여러 자료를 참조하여 함수를 만들어보고 있는 중이다.


입력 데이터


MySQL DB에 저장된 내용(html_encode 함수 이용)




 <?php
class bbsClass {

    function html_encode($str){
        // SQL 과 XSS 공격을 모두 막는 함수
        // htmlentities는 문자열에서 모든 HTML을 제거한다. 한글이 깨질수 있다.
        // ENT_QUOTES : 홑따옴표와 겹따옴표 모두 변환
        // htmlspecialchars, htmlentities 두개다 기본 euc-kr을 지원하지 않는다.
        return htmlentities($this->mysql_fix_string($str), ENT_QUOTES, "UTF-8");
    }

    function mysql_fix_string($str){
        global $db;
        // escape variables for security
        // mysqli_real_escape_string() 함수는 SQL 문에서 특수 문자열을 이스케이프한다.
        // $firstname = mysqli_real_escape_string($con, $_POST['firstname']);
        if(get_magic_quotes_gpc()) $str = stripslashes($str);
        return mysqli_real_escape_string($db,$str);
    }

    function html_decode($str){
        return htmlspecialchars_decode(stripslashes($str));
    }

    function xss_clean($data){ // html_decode 함수의 일종
        // 출처 : https://stackoverflow.com/questions/1336776/xss-filtering-function-in-php
        // Fix &entity\n;
        $data = str_replace(array('&amp;','&lt;','&gt;'), array('&amp;amp;','&amp;lt;','&amp;gt;'), $data);
        $data = preg_replace('/(&#*\w+)[\x00-\x20]+;/u', '$1;', $data);
        $data = preg_replace('/(&#x*[0-9A-F]+);*/iu', '$1;', $data);
        $data = html_entity_decode($data, ENT_COMPAT, 'UTF-8');

        // Remove any attribute starting with "on" or xmlns
        $data = preg_replace('#(<[^>]+?[\x00-\x20"\'])(?:on|xmlns)[^>]*+>#iu', '$1>', $data);

        // Remove javascript: and vbscript: protocols
        $data = preg_replace('#([a-z]*)[\x00-\x20]*=[\x00-\x20]*([`\'"]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2nojavascript...', $data);
        $data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2novbscript...', $data);
        $data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#u', '$1=$2nomozbinding...', $data);

        // Only works in IE: <span style="width: expression(alert('Ping!'));"></span>
        $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?expression[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
        $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?behaviour[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
        $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:*[^>]*+>#iu', '$1>', $data);

        // Remove namespaced elements (we do not need them)
        $data = preg_replace('#</*\w+:\w[^>]*+>#i', '', $data);

        do
        {
            // Remove really unwanted tags
            $old_data = $data;
            $data = preg_replace('#</*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|i(?:frame|layer)|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|title|xml)[^>]*+>#i', '', $data);
        }
        while ($old_data !== $data);

        // we are done...
        return $data;
    }

}//end class bbsClass


검색하다보니 HTML Purifier 를 이용한 필터링을 하는 걸 추천하는거 같다.

http://htmlpurifier.org/ 에서 파일을 다운로드하여 압축을 푼다.

HTML Purifier 4.10.0 버전이 PHP5, PHP7 지원한다고 적혀있다.


기능을 테스트 해보니 $html_decode 함수인거 같다.

https://gist.github.com/kijin/5829736 에 사용법이 잘 설명되어 있다.


'Web 프로그램 > 테이블, 게시판, 검색' 카테고리의 다른 글

PHP 위지윅 에디터 글쓰기 기능  (0) 2023.06.28
bootstrap4 paging with PHP  (0) 2022.02.27
PHP 네이버 스마트에디터 연동 방법  (0) 2018.04.15
PHP 검색어 함수  (0) 2018.04.08
HTML 특수기호  (0) 2018.01.17
블로그 이미지

Link2Me

,